Browse Source

Fix handling of Debian files with trailing slash (#26087) (#26098)

Backport #26087 by @KN4CK3R

Fixes #26022

- Fix handling of files with trailing slash
- Fix handling of duplicate package file errors
- Added test for both

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
tags/v1.20.2
Giteabot 10 months ago
parent
commit
a424f6d4f8
No account linked to committer's email address

+ 3
- 1
modules/packages/debian/metadata.go View File

@@ -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":

+ 62
- 48
modules/packages/debian/metadata_test.go View File

@@ -69,57 +69,71 @@ 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()})

p, err := ParsePackage(data)
assert.NotNil(t, p)
assert.NoError(t, err)
assert.Equal(t, "gitea", p.Name)
})

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.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)
})
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
},
},
}

t.Run("zst", func(t *testing.T) {
var zbuf bytes.Buffer
zw, _ := zstd.NewWriter(&zbuf)
zw.Write(buf.Bytes())
zw.Close()
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)
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()})

p, err := ParsePackage(data)
assert.NotNil(t, p)
assert.NoError(t, err)
assert.Equal(t, "gitea", p.Name)
})
})
}
})
}

data := createArchive(map[string][]byte{"control.tar.zst": zbuf.Bytes()})
type nopCloser struct {
io.Writer
}

p, err := ParsePackage(data)
assert.NotNil(t, p)
assert.NoError(t, err)
assert.Equal(t, "gitea", p.Name)
})
})
func (nopCloser) Close() error {
return nil
}

func TestParseControlFile(t *testing.T) {

+ 1
- 1
routers/api/packages/debian/debian.go View File

@@ -195,7 +195,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)

+ 4
- 0
tests/integration/api_packages_debian_test.go View File

@@ -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) {

Loading…
Cancel
Save