mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Fix handling of Debian files with trailing slash (#26087)
Fixes #26022 - Fix handling of files with trailing slash - Fix handling of duplicate package file errors - Added test for both
This commit is contained in:
		@@ -80,7 +80,9 @@ func ParsePackage(r io.Reader) (*Package, error) {
 | 
			
		||||
 | 
			
		||||
		if strings.HasPrefix(hd.Name, controlTar) {
 | 
			
		||||
			var inner io.Reader
 | 
			
		||||
			switch hd.Name[len(controlTar):] {
 | 
			
		||||
			// https://man7.org/linux/man-pages/man5/deb-split.5.html#FORMAT
 | 
			
		||||
			// The file names might contain a trailing slash (since dpkg 1.15.6).
 | 
			
		||||
			switch strings.TrimSuffix(hd.Name[len(controlTar):], "/") {
 | 
			
		||||
			case "":
 | 
			
		||||
				inner = arr
 | 
			
		||||
			case ".gz":
 | 
			
		||||
 
 | 
			
		||||
@@ -69,59 +69,73 @@ func TestParsePackage(t *testing.T) {
 | 
			
		||||
		tw.Write([]byte("Package: gitea\nVersion: 1.0.0\nArchitecture: amd64\n"))
 | 
			
		||||
		tw.Close()
 | 
			
		||||
 | 
			
		||||
		t.Run("None", func(t *testing.T) {
 | 
			
		||||
			data := createArchive(map[string][]byte{"control.tar": buf.Bytes()})
 | 
			
		||||
		cases := []struct {
 | 
			
		||||
			Extension     string
 | 
			
		||||
			WriterFactory func(io.Writer) io.WriteCloser
 | 
			
		||||
		}{
 | 
			
		||||
			{
 | 
			
		||||
				Extension: "",
 | 
			
		||||
				WriterFactory: func(w io.Writer) io.WriteCloser {
 | 
			
		||||
					return nopCloser{w}
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				Extension: ".gz",
 | 
			
		||||
				WriterFactory: func(w io.Writer) io.WriteCloser {
 | 
			
		||||
					return gzip.NewWriter(w)
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				Extension: ".xz",
 | 
			
		||||
				WriterFactory: func(w io.Writer) io.WriteCloser {
 | 
			
		||||
					xw, _ := xz.NewWriter(w)
 | 
			
		||||
					return xw
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				Extension: ".zst",
 | 
			
		||||
				WriterFactory: func(w io.Writer) io.WriteCloser {
 | 
			
		||||
					zw, _ := zstd.NewWriter(w)
 | 
			
		||||
					return zw
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			p, err := ParsePackage(data)
 | 
			
		||||
			assert.NotNil(t, p)
 | 
			
		||||
			assert.NoError(t, err)
 | 
			
		||||
			assert.Equal(t, "gitea", p.Name)
 | 
			
		||||
		})
 | 
			
		||||
		for _, c := range cases {
 | 
			
		||||
			t.Run(c.Extension, func(t *testing.T) {
 | 
			
		||||
				var cbuf bytes.Buffer
 | 
			
		||||
				w := c.WriterFactory(&cbuf)
 | 
			
		||||
				w.Write(buf.Bytes())
 | 
			
		||||
				w.Close()
 | 
			
		||||
 | 
			
		||||
		t.Run("gz", func(t *testing.T) {
 | 
			
		||||
			var zbuf bytes.Buffer
 | 
			
		||||
			zw := gzip.NewWriter(&zbuf)
 | 
			
		||||
			zw.Write(buf.Bytes())
 | 
			
		||||
			zw.Close()
 | 
			
		||||
				data := createArchive(map[string][]byte{"control.tar" + c.Extension: cbuf.Bytes()})
 | 
			
		||||
 | 
			
		||||
			data := createArchive(map[string][]byte{"control.tar.gz": zbuf.Bytes()})
 | 
			
		||||
				p, err := ParsePackage(data)
 | 
			
		||||
				assert.NotNil(t, p)
 | 
			
		||||
				assert.NoError(t, err)
 | 
			
		||||
				assert.Equal(t, "gitea", p.Name)
 | 
			
		||||
 | 
			
		||||
			p, err := ParsePackage(data)
 | 
			
		||||
			assert.NotNil(t, p)
 | 
			
		||||
			assert.NoError(t, err)
 | 
			
		||||
			assert.Equal(t, "gitea", p.Name)
 | 
			
		||||
		})
 | 
			
		||||
				t.Run("TrailingSlash", func(t *testing.T) {
 | 
			
		||||
					data := createArchive(map[string][]byte{"control.tar" + c.Extension + "/": cbuf.Bytes()})
 | 
			
		||||
 | 
			
		||||
		t.Run("xz", func(t *testing.T) {
 | 
			
		||||
			var xbuf bytes.Buffer
 | 
			
		||||
			xw, _ := xz.NewWriter(&xbuf)
 | 
			
		||||
			xw.Write(buf.Bytes())
 | 
			
		||||
			xw.Close()
 | 
			
		||||
 | 
			
		||||
			data := createArchive(map[string][]byte{"control.tar.xz": xbuf.Bytes()})
 | 
			
		||||
 | 
			
		||||
			p, err := ParsePackage(data)
 | 
			
		||||
			assert.NotNil(t, p)
 | 
			
		||||
			assert.NoError(t, err)
 | 
			
		||||
			assert.Equal(t, "gitea", p.Name)
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		t.Run("zst", func(t *testing.T) {
 | 
			
		||||
			var zbuf bytes.Buffer
 | 
			
		||||
			zw, _ := zstd.NewWriter(&zbuf)
 | 
			
		||||
			zw.Write(buf.Bytes())
 | 
			
		||||
			zw.Close()
 | 
			
		||||
 | 
			
		||||
			data := createArchive(map[string][]byte{"control.tar.zst": zbuf.Bytes()})
 | 
			
		||||
 | 
			
		||||
			p, err := ParsePackage(data)
 | 
			
		||||
			assert.NotNil(t, p)
 | 
			
		||||
			assert.NoError(t, err)
 | 
			
		||||
			assert.Equal(t, "gitea", p.Name)
 | 
			
		||||
		})
 | 
			
		||||
					p, err := ParsePackage(data)
 | 
			
		||||
					assert.NotNil(t, p)
 | 
			
		||||
					assert.NoError(t, err)
 | 
			
		||||
					assert.Equal(t, "gitea", p.Name)
 | 
			
		||||
				})
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type nopCloser struct {
 | 
			
		||||
	io.Writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (nopCloser) Close() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseControlFile(t *testing.T) {
 | 
			
		||||
	buildContent := func(name, version, architecture string) *bytes.Buffer {
 | 
			
		||||
		var buf bytes.Buffer
 | 
			
		||||
 
 | 
			
		||||
@@ -187,7 +187,7 @@ func UploadPackageFile(ctx *context.Context) {
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		switch err {
 | 
			
		||||
		case packages_model.ErrDuplicatePackageVersion:
 | 
			
		||||
		case packages_model.ErrDuplicatePackageVersion, packages_model.ErrDuplicatePackageFile:
 | 
			
		||||
			apiError(ctx, http.StatusBadRequest, err)
 | 
			
		||||
		case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize:
 | 
			
		||||
			apiError(ctx, http.StatusForbidden, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -144,6 +144,10 @@ func TestPackageDebian(t *testing.T) {
 | 
			
		||||
								}
 | 
			
		||||
								return seen
 | 
			
		||||
							})
 | 
			
		||||
 | 
			
		||||
							req = NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion, architecture))
 | 
			
		||||
							AddBasicAuthHeader(req, user.Name)
 | 
			
		||||
							MakeRequest(t, req, http.StatusBadRequest)
 | 
			
		||||
						})
 | 
			
		||||
 | 
			
		||||
						t.Run("Download", func(t *testing.T) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user