Skip to content

Commit

Permalink
fix: limitation for length of package/realm path (#2108)
Browse files Browse the repository at this point in the history
<!-- please provide a detailed description of the changes made in this
pull request. -->

<details><summary>Contributors' checklist...</summary>

- [x] Added new tests, or not needed, or not feasible
- [ ] Provided an example (e.g. screenshot) to aid review or the PR is
self-explanatory
- [ ] Updated the official documentation or not needed
- [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message
was included in the description
- [x] Added references to related issues and PRs
- [ ] Provided any useful hints for running manual tests
- [ ] Added new benchmarks to [generated
graphs](https://gnoland.github.io/benchmarks), if any. More info
[here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
</details>

---------

Co-authored-by: Thinh <thinhnx@192.168.1.9>
Co-authored-by: Thinh <thinhnx@thinhnx.local>
Co-authored-by: Thinh <thinhnx@192.168.1.6>
Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com>
Co-authored-by: Morgan Bazalgette <morgan@morganbaz.com>
  • Loading branch information
6 people authored May 28, 2024
1 parent a21f12f commit f43cbfa
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 109 deletions.
7 changes: 7 additions & 0 deletions tm2/pkg/std/memfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ func (mempkg *MemPackage) IsEmpty() bool {
return len(mempkg.Files) == 0
}

const pathLengthLimit = 256

var (
rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]*$`)
rePkgOrRlmPath = regexp.MustCompile(`^gno\.land\/(?:p|r)(?:\/_?[a-z]+[a-z0-9_]*)+$`)
Expand All @@ -52,9 +54,14 @@ func (mempkg *MemPackage) Validate() error {
return fmt.Errorf("no files found within package %q", mempkg.Name)
}

if len(mempkg.Path) > pathLengthLimit {
return fmt.Errorf("path length %d exceeds limit %d", len(mempkg.Path), pathLengthLimit)
}

if !rePkgName.MatchString(mempkg.Name) {
return fmt.Errorf("invalid package name %q, failed to match %q", mempkg.Name, rePkgName)
}

if !rePkgOrRlmPath.MatchString(mempkg.Path) {
return fmt.Errorf("invalid package/realm path %q, failed to match %q", mempkg.Path, rePkgOrRlmPath)
}
Expand Down
288 changes: 179 additions & 109 deletions tm2/pkg/std/memfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
)

func TestMemPackage_Validate(t *testing.T) {
t.Parallel()
tt := []struct {
name string
mpkg *MemPackage
Expand All @@ -28,7 +29,7 @@ func TestMemPackage_Validate(t *testing.T) {
Path: "gno.land/r/demo/hey",
Files: []*MemFile{{Name: "b.gno"}, {Name: "a.gno"}},
},
`mempackage "gno.land/r/demo/hey" has unsorted files`,
"unsorted",
},
{
"Duplicate",
Expand All @@ -37,166 +38,235 @@ func TestMemPackage_Validate(t *testing.T) {
Path: "gno.land/r/demo/hey",
Files: []*MemFile{{Name: "a.gno"}, {Name: "a.gno"}},
},
`duplicate file name "a.gno"`,
"duplicate",
},
}
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
err := tc.mpkg.Validate()
if tc.errContains == "" {
assert.NoError(t, err)
} else {
assert.ErrorContains(t, err, tc.errContains)
}
})
}
}

func TestRePkgOrRlmPath(t *testing.T) {
t.Parallel()

testTable := []struct {
desc, in string
expected bool
}{
{
desc: "Valid p",
in: "gno.land/p/path/path",
expected: true,
},
{
desc: "Valid r",
in: "gno.land/r/path/path",
expected: true,
},
{
desc: "Leading Underscore",
in: "gno.land/r/path/_path",
expected: true,
"InvalidPathLength",
&MemPackage{
Name: "hey",
Path: "gno.land/r/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/long/path",
Files: []*MemFile{{Name: "a.gno"}},
},
"path length",
},
{
desc: "Trailing Underscore",
in: "gno.land/r/path/path_",
expected: true,
"valid p",
&MemPackage{
Name: "hey",
Path: "gno.land/p/path/path",
Files: []*MemFile{{Name: "a.gno"}},
},
"",
},
{
desc: "Underscore in Between",
in: "gno.land/r/path/p_ath",
expected: true,
"valid r",
&MemPackage{
Name: "hey",
Path: "gno.land/r/path/path",
Files: []*MemFile{{Name: "a.gno"}},
},
"",
},
{
desc: "Invalid With Underscore 1",
in: "gno.land/r/path/_",
expected: false,
"Leading underscore",
&MemPackage{
Name: "hey",
Path: "gno.land/r/path/_path",
Files: []*MemFile{{Name: "a.gno"}},
},
"",
},
{
desc: "Invalid With Underscore 2",
in: "gno.land/r/path/_/_",
expected: false,
"Trailing underscore",
&MemPackage{
Name: "hey",
Path: "gno.land/r/path/path_",
Files: []*MemFile{{Name: "a.gno"}},
},
"",
},
{
desc: "Invalid With Underscore 3",
in: "gno.land/r/path/__/path",
expected: false,
"Between underscore",
&MemPackage{
Name: "hey",
Path: "gno.land/r/path/p_ath",
Files: []*MemFile{{Name: "a.gno"}},
},
"",
},
{
desc: "Invalid With Hyphen",
in: "gno.land/r/path/pa-th",
expected: false,
"Invalid underscore",
&MemPackage{
Name: "hey",
Path: "gno.land/r/path/_",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Invalid x",
in: "gno.land/x/path/path",
expected: false,
"Invalid underscore 2",
&MemPackage{
Name: "hey",
Path: "gno.land/r/path/_/_",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Missing Path 1",
in: "gno.land/p",
expected: false,
"Invalid underscore 3",
&MemPackage{
Name: "hey",
Path: "gno.land/r/path/__/path",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Missing Path 2",
in: "gno.land/p/",
expected: false,
"Invalid hyphen",
&MemPackage{
Name: "hey",
Path: "gno.land/r/path/pa-th",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Invalid domain",
in: "github.com/p/path/path",
expected: false,
"Invalid x",
&MemPackage{
Name: "hey",
Path: "gno.land/x/path/path",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Special Character 1",
in: "gno.land/p/p@th/abc/def",
expected: false,
"Invalid missing path 1",
&MemPackage{
Name: "hey",
Path: "gno.land/p",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Special Character 2",
in: "gno.land/p/p&th/abc/def",
expected: false,
"Invalid missing path 2",
&MemPackage{
Name: "hey",
Path: "gno.land/p/",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Special Character 3",
in: "gno.land/p/p&%$#h/abc/def",
expected: false,
"Invalid path",
&MemPackage{
Name: "hey",
Path: "github.com/p/path/path",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Leading Number",
in: "gno.land/p/1Path/abc/def",
expected: false,
"Special character",
&MemPackage{
Name: "hey",
Path: "gno.land/p/p@th/abc/def",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Uppercase Letters",
in: "gno.land/p/PaTh/abc/def",
expected: false,
"Special character 2",
&MemPackage{
Name: "hey",
Path: "gno.land/p/p&th/abc/def",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Empty Path Part",
in: "gno.land/p/path//def",
expected: false,
"Invalid number",
&MemPackage{
Name: "hey",
Path: "gno.land/p/1Path/abc/def",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Trailing Slash",
in: "gno.land/p/path/abc/def/",
expected: false,
"Invalid uppercase",
&MemPackage{
Name: "hey",
Path: "gno.land/p/PaTh/abc/def",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Extra Slash(s)",
in: "gno.land/p/path///abc/def",
expected: false,
"Invalid empty path",
&MemPackage{
Name: "hey",
Path: "gno.land/p/path//def",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Valid Long path",
in: "gno.land/r/very/very/very/long/path",
expected: true,
"Invalid trailing slash",
&MemPackage{
Name: "hey",
Path: "gno.land/p/path/abc/def/",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Long Path With Special Character 1",
in: "gno.land/r/very/very/very/long/p@th",
expected: false,
"valid long path",
&MemPackage{
Name: "hey",
Path: "gno.land/r/very/very/very/long/path",
Files: []*MemFile{{Name: "a.gno"}},
},
"",
},
{
desc: "Long Path With Special Character 2",
in: "gno.land/r/very/very/v%ry/long/path",
expected: false,
"Invalid long path with special character",
&MemPackage{
Name: "hey",
Path: "gno.land/r/very/very/very/long/p@th",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Long Path With Trailing Slash",
in: "gno.land/r/very/very/very/long/path/",
expected: false,
"Invalid long path with trailing slash",
&MemPackage{
Name: "hey",
Path: "gno.land/r/very/very/very/long/path/",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
{
desc: "Long Path With Empty Path Part",
in: "gno.land/r/very/very/very//long/path/",
expected: false,
"Invalid long path with empty",
&MemPackage{
Name: "hey",
Path: "gno.land/r/very/very/very//long/path/",
Files: []*MemFile{{Name: "a.gno"}},
},
"invalid package/realm path",
},
}

for _, tc := range testTable {
tc := tc
t.Run(tc.desc, func(t *testing.T) {
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

assert.Equal(t, tc.expected, rePkgOrRlmPath.MatchString(tc.in))
err := tc.mpkg.Validate()
if tc.errContains != "" {
assert.ErrorContains(t, err, tc.errContains)
} else {
assert.NoError(t, err)
}
})
}
}

0 comments on commit f43cbfa

Please sign in to comment.