This commit is contained in:
@@ -9,7 +9,7 @@ import (
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -91,7 +91,7 @@ func (e *MarshalEncoder) marshal(v any) error {
|
||||
val := reflect.ValueOf(v)
|
||||
typ := reflect.TypeOf(v)
|
||||
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
if typ.Kind() == reflect.Pointer {
|
||||
val = val.Elem()
|
||||
typ = typ.Elem()
|
||||
}
|
||||
|
||||
@@ -8,13 +8,12 @@ import (
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/validation"
|
||||
"gitea.dev/modules/util"
|
||||
"gitea.dev/modules/validation"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
"go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -26,8 +25,14 @@ var (
|
||||
ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid")
|
||||
)
|
||||
|
||||
var versionMatcher = sync.OnceValue(func() *regexp.Regexp {
|
||||
return regexp.MustCompile(`\A[0-9]+(?:\.[0-9a-zA-Z]+)*(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?\z`)
|
||||
var globalVars = sync.OnceValue(func() (ret struct {
|
||||
nameMatcher, versionMatcher *regexp.Regexp
|
||||
},
|
||||
) {
|
||||
// https://github.com/rubygems/rubygems/blob/master/lib/rubygems/specification.rb (VALID_NAME_PATTERN)
|
||||
ret.nameMatcher = regexp.MustCompile(`\A[\w.-]+\z`)
|
||||
ret.versionMatcher = regexp.MustCompile(`\A[0-9]+(?:\.[0-9a-zA-Z]+)*(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?\z`)
|
||||
return ret
|
||||
})
|
||||
|
||||
// Package represents a RubyGems package
|
||||
@@ -175,11 +180,11 @@ func parseMetadataFile(r io.Reader) (*Package, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(spec.Name) == 0 || strings.Contains(spec.Name, "/") {
|
||||
if !globalVars().nameMatcher.MatchString(spec.Name) {
|
||||
return nil, ErrInvalidName
|
||||
}
|
||||
|
||||
if !versionMatcher().MatchString(spec.Version.Version) {
|
||||
if !globalVars().versionMatcher.MatchString(spec.Version.Version) {
|
||||
return nil, ErrInvalidVersion
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ package rubygems
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"gitea.dev/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -32,6 +32,17 @@ version:
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, rp)
|
||||
})
|
||||
|
||||
t.Run("InvalidName", func(t *testing.T) {
|
||||
// a name carrying a newline would be re-emitted verbatim into the
|
||||
// line-based compact index, letting an upload forge extra entries
|
||||
for _, quotedName := range []string{`"evil\n1.0.0"`, `"a b"`, `"a/b"`, `""`} {
|
||||
content := test.CompressGzip("name: " + quotedName + "\nversion:\n version: 1\n")
|
||||
rp, err := parseMetadataFile(content)
|
||||
assert.ErrorIs(t, err, ErrInvalidName, "name %s should be rejected", quotedName)
|
||||
assert.Nil(t, rp)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseMetadataFile(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user