mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00: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) { | 		if strings.HasPrefix(hd.Name, controlTar) { | ||||||
| 			var inner io.Reader | 			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 "": | 			case "": | ||||||
| 				inner = arr | 				inner = arr | ||||||
| 			case ".gz": | 			case ".gz": | ||||||
|   | |||||||
| @@ -69,50 +69,54 @@ func TestParsePackage(t *testing.T) { | |||||||
| 		tw.Write([]byte("Package: gitea\nVersion: 1.0.0\nArchitecture: amd64\n")) | 		tw.Write([]byte("Package: gitea\nVersion: 1.0.0\nArchitecture: amd64\n")) | ||||||
| 		tw.Close() | 		tw.Close() | ||||||
|  |  | ||||||
| 		t.Run("None", func(t *testing.T) { | 		cases := []struct { | ||||||
| 			data := createArchive(map[string][]byte{"control.tar": buf.Bytes()}) | 			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 | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		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() | ||||||
|  |  | ||||||
|  | 				data := createArchive(map[string][]byte{"control.tar" + c.Extension: cbuf.Bytes()}) | ||||||
|  |  | ||||||
| 				p, err := ParsePackage(data) | 				p, err := ParsePackage(data) | ||||||
| 				assert.NotNil(t, p) | 				assert.NotNil(t, p) | ||||||
| 				assert.NoError(t, err) | 				assert.NoError(t, err) | ||||||
| 				assert.Equal(t, "gitea", p.Name) | 				assert.Equal(t, "gitea", p.Name) | ||||||
| 		}) |  | ||||||
|  |  | ||||||
| 		t.Run("gz", func(t *testing.T) { | 				t.Run("TrailingSlash", func(t *testing.T) { | ||||||
| 			var zbuf bytes.Buffer | 					data := createArchive(map[string][]byte{"control.tar" + c.Extension + "/": cbuf.Bytes()}) | ||||||
| 			zw := gzip.NewWriter(&zbuf) |  | ||||||
| 			zw.Write(buf.Bytes()) |  | ||||||
| 			zw.Close() |  | ||||||
|  |  | ||||||
| 			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) |  | ||||||
| 		}) |  | ||||||
|  |  | ||||||
| 		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) | 					p, err := ParsePackage(data) | ||||||
| 					assert.NotNil(t, p) | 					assert.NotNil(t, p) | ||||||
| @@ -121,6 +125,16 @@ func TestParsePackage(t *testing.T) { | |||||||
| 				}) | 				}) | ||||||
| 			}) | 			}) | ||||||
| 		} | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type nopCloser struct { | ||||||
|  | 	io.Writer | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (nopCloser) Close() error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestParseControlFile(t *testing.T) { | func TestParseControlFile(t *testing.T) { | ||||||
| 	buildContent := func(name, version, architecture string) *bytes.Buffer { | 	buildContent := func(name, version, architecture string) *bytes.Buffer { | ||||||
|   | |||||||
| @@ -187,7 +187,7 @@ func UploadPackageFile(ctx *context.Context) { | |||||||
| 	) | 	) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		switch err { | 		switch err { | ||||||
| 		case packages_model.ErrDuplicatePackageVersion: | 		case packages_model.ErrDuplicatePackageVersion, packages_model.ErrDuplicatePackageFile: | ||||||
| 			apiError(ctx, http.StatusBadRequest, err) | 			apiError(ctx, http.StatusBadRequest, err) | ||||||
| 		case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize: | 		case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize: | ||||||
| 			apiError(ctx, http.StatusForbidden, err) | 			apiError(ctx, http.StatusForbidden, err) | ||||||
|   | |||||||
| @@ -144,6 +144,10 @@ func TestPackageDebian(t *testing.T) { | |||||||
| 								} | 								} | ||||||
| 								return seen | 								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) { | 						t.Run("Download", func(t *testing.T) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 KN4CK3R
					KN4CK3R