Skip to content

Commit 6aa30af

Browse files
authored
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
1 parent 4211efe commit 6aa30af

File tree

4 files changed

+70
-50
lines changed

4 files changed

+70
-50
lines changed

modules/packages/debian/metadata.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ func ParsePackage(r io.Reader) (*Package, error) {
8080

8181
if strings.HasPrefix(hd.Name, controlTar) {
8282
var inner io.Reader
83-
switch hd.Name[len(controlTar):] {
83+
// https://man7.org/linux/man-pages/man5/deb-split.5.html#FORMAT
84+
// The file names might contain a trailing slash (since dpkg 1.15.6).
85+
switch strings.TrimSuffix(hd.Name[len(controlTar):], "/") {
8486
case "":
8587
inner = arr
8688
case ".gz":

modules/packages/debian/metadata_test.go

+62-48
Original file line numberDiff line numberDiff line change
@@ -69,57 +69,71 @@ func TestParsePackage(t *testing.T) {
6969
tw.Write([]byte("Package: gitea\nVersion: 1.0.0\nArchitecture: amd64\n"))
7070
tw.Close()
7171

72-
t.Run("None", func(t *testing.T) {
73-
data := createArchive(map[string][]byte{"control.tar": buf.Bytes()})
74-
75-
p, err := ParsePackage(data)
76-
assert.NotNil(t, p)
77-
assert.NoError(t, err)
78-
assert.Equal(t, "gitea", p.Name)
79-
})
80-
81-
t.Run("gz", func(t *testing.T) {
82-
var zbuf bytes.Buffer
83-
zw := gzip.NewWriter(&zbuf)
84-
zw.Write(buf.Bytes())
85-
zw.Close()
86-
87-
data := createArchive(map[string][]byte{"control.tar.gz": zbuf.Bytes()})
88-
89-
p, err := ParsePackage(data)
90-
assert.NotNil(t, p)
91-
assert.NoError(t, err)
92-
assert.Equal(t, "gitea", p.Name)
93-
})
94-
95-
t.Run("xz", func(t *testing.T) {
96-
var xbuf bytes.Buffer
97-
xw, _ := xz.NewWriter(&xbuf)
98-
xw.Write(buf.Bytes())
99-
xw.Close()
100-
101-
data := createArchive(map[string][]byte{"control.tar.xz": xbuf.Bytes()})
102-
103-
p, err := ParsePackage(data)
104-
assert.NotNil(t, p)
105-
assert.NoError(t, err)
106-
assert.Equal(t, "gitea", p.Name)
107-
})
72+
cases := []struct {
73+
Extension string
74+
WriterFactory func(io.Writer) io.WriteCloser
75+
}{
76+
{
77+
Extension: "",
78+
WriterFactory: func(w io.Writer) io.WriteCloser {
79+
return nopCloser{w}
80+
},
81+
},
82+
{
83+
Extension: ".gz",
84+
WriterFactory: func(w io.Writer) io.WriteCloser {
85+
return gzip.NewWriter(w)
86+
},
87+
},
88+
{
89+
Extension: ".xz",
90+
WriterFactory: func(w io.Writer) io.WriteCloser {
91+
xw, _ := xz.NewWriter(w)
92+
return xw
93+
},
94+
},
95+
{
96+
Extension: ".zst",
97+
WriterFactory: func(w io.Writer) io.WriteCloser {
98+
zw, _ := zstd.NewWriter(w)
99+
return zw
100+
},
101+
},
102+
}
108103

109-
t.Run("zst", func(t *testing.T) {
110-
var zbuf bytes.Buffer
111-
zw, _ := zstd.NewWriter(&zbuf)
112-
zw.Write(buf.Bytes())
113-
zw.Close()
104+
for _, c := range cases {
105+
t.Run(c.Extension, func(t *testing.T) {
106+
var cbuf bytes.Buffer
107+
w := c.WriterFactory(&cbuf)
108+
w.Write(buf.Bytes())
109+
w.Close()
110+
111+
data := createArchive(map[string][]byte{"control.tar" + c.Extension: cbuf.Bytes()})
112+
113+
p, err := ParsePackage(data)
114+
assert.NotNil(t, p)
115+
assert.NoError(t, err)
116+
assert.Equal(t, "gitea", p.Name)
117+
118+
t.Run("TrailingSlash", func(t *testing.T) {
119+
data := createArchive(map[string][]byte{"control.tar" + c.Extension + "/": cbuf.Bytes()})
120+
121+
p, err := ParsePackage(data)
122+
assert.NotNil(t, p)
123+
assert.NoError(t, err)
124+
assert.Equal(t, "gitea", p.Name)
125+
})
126+
})
127+
}
128+
})
129+
}
114130

115-
data := createArchive(map[string][]byte{"control.tar.zst": zbuf.Bytes()})
131+
type nopCloser struct {
132+
io.Writer
133+
}
116134

117-
p, err := ParsePackage(data)
118-
assert.NotNil(t, p)
119-
assert.NoError(t, err)
120-
assert.Equal(t, "gitea", p.Name)
121-
})
122-
})
135+
func (nopCloser) Close() error {
136+
return nil
123137
}
124138

125139
func TestParseControlFile(t *testing.T) {

routers/api/packages/debian/debian.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func UploadPackageFile(ctx *context.Context) {
187187
)
188188
if err != nil {
189189
switch err {
190-
case packages_model.ErrDuplicatePackageVersion:
190+
case packages_model.ErrDuplicatePackageVersion, packages_model.ErrDuplicatePackageFile:
191191
apiError(ctx, http.StatusBadRequest, err)
192192
case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize:
193193
apiError(ctx, http.StatusForbidden, err)

tests/integration/api_packages_debian_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ func TestPackageDebian(t *testing.T) {
144144
}
145145
return seen
146146
})
147+
148+
req = NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion, architecture))
149+
AddBasicAuthHeader(req, user.Name)
150+
MakeRequest(t, req, http.StatusBadRequest)
147151
})
148152

149153
t.Run("Download", func(t *testing.T) {

0 commit comments

Comments
 (0)