loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Relax generic package filename restrictions (#30135)

Now, the chars `=:;()[]{}~!@#$%^ &` are possible as well
Fixes #30134

---------

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
(cherry picked from commit 1ad48f781eb0681561b083b49dfeff84ba51f2fe)

authored by

wxiaoguang
KN4CK3R
and committed by
Earl Warren
ea4755be 708fdf2d

+91 -7
+24 -5
routers/api/packages/generic/generic.go
··· 8 8 "net/http" 9 9 "regexp" 10 10 "strings" 11 + "unicode" 11 12 12 13 packages_model "code.gitea.io/gitea/models/packages" 13 14 "code.gitea.io/gitea/modules/log" ··· 18 19 ) 19 20 20 21 var ( 21 - packageNameRegex = regexp.MustCompile(`\A[A-Za-z0-9\.\_\-\+]+\z`) 22 - filenameRegex = packageNameRegex 22 + packageNameRegex = regexp.MustCompile(`\A[-_+.\w]+\z`) 23 + filenameRegex = regexp.MustCompile(`\A[-_+=:;.()\[\]{}~!@#$%^& \w]+\z`) 23 24 ) 24 25 25 26 func apiError(ctx *context.Context, status int, obj any) { ··· 54 55 helper.ServePackageFile(ctx, s, u, pf) 55 56 } 56 57 58 + func isValidPackageName(packageName string) bool { 59 + if len(packageName) == 1 && !unicode.IsLetter(rune(packageName[0])) && !unicode.IsNumber(rune(packageName[0])) { 60 + return false 61 + } 62 + return packageNameRegex.MatchString(packageName) && packageName != ".." 63 + } 64 + 65 + func isValidFileName(filename string) bool { 66 + return filenameRegex.MatchString(filename) && 67 + strings.TrimSpace(filename) == filename && 68 + filename != "." && filename != ".." 69 + } 70 + 57 71 // UploadPackage uploads the specific generic package. 58 72 // Duplicated packages get rejected. 59 73 func UploadPackage(ctx *context.Context) { 60 74 packageName := ctx.Params("packagename") 61 75 filename := ctx.Params("filename") 62 76 63 - if !packageNameRegex.MatchString(packageName) || !filenameRegex.MatchString(filename) { 64 - apiError(ctx, http.StatusBadRequest, errors.New("Invalid package name or filename")) 77 + if !isValidPackageName(packageName) { 78 + apiError(ctx, http.StatusBadRequest, errors.New("invalid package name")) 79 + return 80 + } 81 + 82 + if !isValidFileName(filename) { 83 + apiError(ctx, http.StatusBadRequest, errors.New("invalid filename")) 65 84 return 66 85 } 67 86 68 87 packageVersion := ctx.Params("packageversion") 69 88 if packageVersion != strings.TrimSpace(packageVersion) { 70 - apiError(ctx, http.StatusBadRequest, errors.New("Invalid package version")) 89 + apiError(ctx, http.StatusBadRequest, errors.New("invalid package version")) 71 90 return 72 91 } 73 92
+65
routers/api/packages/generic/generic_test.go
··· 1 + // Copyright 2024 The Gitea Authors. All rights reserved. 2 + // SPDX-License-Identifier: MIT 3 + 4 + package generic 5 + 6 + import ( 7 + "testing" 8 + 9 + "github.com/stretchr/testify/assert" 10 + ) 11 + 12 + func TestValidatePackageName(t *testing.T) { 13 + bad := []string{ 14 + "", 15 + ".", 16 + "..", 17 + "-", 18 + "a?b", 19 + "a b", 20 + "a/b", 21 + } 22 + for _, name := range bad { 23 + assert.False(t, isValidPackageName(name), "bad=%q", name) 24 + } 25 + 26 + good := []string{ 27 + "a", 28 + "1", 29 + "a-", 30 + "a_b", 31 + "c.d+", 32 + } 33 + for _, name := range good { 34 + assert.True(t, isValidPackageName(name), "good=%q", name) 35 + } 36 + } 37 + 38 + func TestValidateFileName(t *testing.T) { 39 + bad := []string{ 40 + "", 41 + ".", 42 + "..", 43 + "a?b", 44 + "a/b", 45 + " a", 46 + "a ", 47 + } 48 + for _, name := range bad { 49 + assert.False(t, isValidFileName(name), "bad=%q", name) 50 + } 51 + 52 + good := []string{ 53 + "-", 54 + "a", 55 + "1", 56 + "a-", 57 + "a_b", 58 + "a b", 59 + "c.d+", 60 + `-_+=:;.()[]{}~!@#$%^& aA1`, 61 + } 62 + for _, name := range good { 63 + assert.True(t, isValidFileName(name), "good=%q", name) 64 + } 65 + }
+2 -2
tests/integration/api_packages_generic_test.go
··· 84 84 t.Run("InvalidParameter", func(t *testing.T) { 85 85 defer tests.PrintCurrentTest(t)() 86 86 87 - req := NewRequestWithBody(t, "PUT", fmt.Sprintf("/api/packages/%s/generic/%s/%s/%s", user.Name, "invalid+package name", packageVersion, filename), bytes.NewReader(content)). 87 + req := NewRequestWithBody(t, "PUT", fmt.Sprintf("/api/packages/%s/generic/%s/%s/%s", user.Name, "invalid package name", packageVersion, filename), bytes.NewReader(content)). 88 88 AddBasicAuth(user.Name) 89 89 MakeRequest(t, req, http.StatusBadRequest) 90 90 ··· 92 92 AddBasicAuth(user.Name) 93 93 MakeRequest(t, req, http.StatusBadRequest) 94 94 95 - req = NewRequestWithBody(t, "PUT", fmt.Sprintf("/api/packages/%s/generic/%s/%s/%s", user.Name, packageName, packageVersion, "inval+id.na me"), bytes.NewReader(content)). 95 + req = NewRequestWithBody(t, "PUT", fmt.Sprintf("/api/packages/%s/generic/%s/%s/%s", user.Name, packageName, packageVersion, "inva|id.name"), bytes.NewReader(content)). 96 96 AddBasicAuth(user.Name) 97 97 MakeRequest(t, req, http.StatusBadRequest) 98 98 })