-
Notifications
You must be signed in to change notification settings - Fork 26
fix(upload): validate path #575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
2d0a440
fix(upload): validate path
cnlangzi 4f7a0b5
fix(upload): validate path
cnlangzi 375a92b
fix(upload): improved naming
cnlangzi 1bc97e2
fix(upload): improved naming
cnlangzi c8d369e
fix(upload): fixed parent path bug
cnlangzi 789a7ed
fix(upload): fixed and improved path validation logic
cnlangzi 9ff1466
fix(upload): fixed handler test
cnlangzi cb0b175
fix(refwalker): improved code
cnlangzi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| package reference | ||
|
|
||
| import ( | ||
| "path" | ||
| "strings" | ||
| ) | ||
|
|
||
| func NewRefWalkerFromPath(p string) *RefWalker { | ||
| return NewRefWalker(strings.Split(path.Clean(p), "/")) | ||
| } | ||
|
|
||
| // NewRefWalker wrap dirs as RefWaller | ||
| func NewRefWalker(dirs []string) *RefWalker { | ||
|
|
||
| return &RefWalker{ | ||
| items: dirs, | ||
| length: len(dirs), | ||
| index: 0, | ||
| } | ||
| } | ||
|
|
||
| type RefWalker struct { | ||
| items []string | ||
| length int | ||
| index int | ||
| } | ||
|
|
||
| // Name get current dir name | ||
| func (d *RefWalker) Name() (string, bool) { | ||
| if d == nil { | ||
| return "", false | ||
| } | ||
|
|
||
| // current is root | ||
| if d.index == 0 { | ||
| return "/", true | ||
| } | ||
|
|
||
| if d.index < d.length { | ||
| return d.items[d.index], true | ||
| } | ||
|
|
||
| return "", false | ||
| } | ||
|
|
||
| // Path get current dir path | ||
| func (d *RefWalker) Path() (string, bool) { | ||
| if d == nil { | ||
| return "", false | ||
| } | ||
|
|
||
| // current is root | ||
| if d.index == 0 { | ||
| return "/", true | ||
| } | ||
|
|
||
| if d.index < d.length { | ||
| return "/" + path.Join(d.items[:d.index+1]...), true | ||
| } | ||
|
|
||
| return "", false | ||
| } | ||
|
|
||
| // Parent get curerent parent path | ||
| func (d *RefWalker) Parent() (string, bool) { | ||
| if d == nil { | ||
| return "", false | ||
| } | ||
|
|
||
| // current is root | ||
| if d.index == 0 { | ||
| return "", true | ||
| } | ||
|
|
||
| return "/" + path.Join(d.items[:d.index]...), true | ||
| } | ||
|
|
||
| // Level get current dir level | ||
| func (d *RefWalker) Level() int { | ||
| if d == nil { | ||
| return 0 | ||
| } | ||
|
|
||
| return d.index + 1 | ||
| } | ||
|
|
||
| // Level get the numbers of dir | ||
| func (d *RefWalker) Length() int { | ||
| if d == nil { | ||
| return 0 | ||
| } | ||
|
|
||
| return len(d.items) | ||
| } | ||
|
|
||
| // Top move to root dir | ||
| func (d *RefWalker) Top() bool { | ||
| if d == nil { | ||
| return false | ||
| } | ||
|
|
||
| d.index = 0 | ||
|
|
||
| return true | ||
| } | ||
|
|
||
| // Last move to last sub dir | ||
| func (d *RefWalker) Last() bool { | ||
| if d == nil { | ||
| return false | ||
| } | ||
|
|
||
| if d.length > 0 { | ||
| d.index = d.length - 1 | ||
| return true | ||
| } | ||
|
|
||
| return false | ||
| } | ||
|
|
||
| // Back back to parent dir | ||
| func (d *RefWalker) Back() bool { | ||
| if d == nil { | ||
| return false | ||
| } | ||
|
|
||
| i := d.index - 1 | ||
|
|
||
| // it is root | ||
| if i < 0 { | ||
| return false | ||
| } | ||
|
|
||
| d.index = i | ||
|
|
||
| return true | ||
| } | ||
|
|
||
| // Forward go to sub dir | ||
| func (d *RefWalker) Forward() bool { | ||
| if d == nil { | ||
| return false | ||
| } | ||
|
|
||
| i := d.index + 1 | ||
|
|
||
| // it is root | ||
| if i >= len(d.items) { | ||
| return false | ||
| } | ||
|
|
||
| d.index = i | ||
|
|
||
| return true | ||
| } | ||
96 changes: 96 additions & 0 deletions
96
code/go/0chain.net/blobbercore/reference/ref_walker_test.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| package reference | ||
|
|
||
| import ( | ||
| "path" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestRefWalker(t *testing.T) { | ||
| list := []struct { | ||
| TestName string | ||
| TestPath string | ||
| WalkFunc func(w *RefWalker) bool | ||
| WalkResult bool | ||
| Name string | ||
| Level int | ||
| Path string | ||
| Parent string | ||
| }{ | ||
| {TestName: "invalid_path", TestPath: "", WalkFunc: func(w *RefWalker) bool { | ||
| return w.Top() | ||
| }, WalkResult: true, Name: "/", Level: 1, Path: "/", Parent: ""}, | ||
|
|
||
| {TestName: "top", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { | ||
| return w.Top() | ||
| }, WalkResult: true, Name: "/", Level: 1, Path: "/", Parent: ""}, | ||
|
|
||
| {TestName: "forward_2", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { | ||
| w.Top() | ||
| return w.Forward() | ||
| }, WalkResult: true, Name: "d1", Level: 2, Path: "/d1", Parent: "/"}, | ||
|
|
||
| {TestName: "forward_3", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { | ||
| w.Top() | ||
| w.Forward() | ||
| return w.Forward() | ||
| }, WalkResult: true, Name: "d2", Level: 3, Path: "/d1/d2", Parent: "/d1"}, | ||
|
|
||
| {TestName: "forward_last", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { | ||
| w.Last() | ||
| return w.Forward() | ||
| }, WalkResult: false, Name: "d3", Level: 4, Path: "/d1/d2/d3", Parent: "/d1/d2"}, | ||
|
|
||
| {TestName: "last", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { | ||
| return w.Last() | ||
| }, WalkResult: true, Name: "d3", Level: 4, Path: "/d1/d2/d3", Parent: "/d1/d2"}, | ||
|
|
||
| {TestName: "back_2", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { | ||
| w.Last() | ||
| return w.Back() | ||
| }, WalkResult: true, Name: "d2", Level: 3, Path: "/d1/d2", Parent: "/d1"}, | ||
|
|
||
| {TestName: "back_3", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { | ||
| w.Last() | ||
| w.Back() | ||
| return w.Back() | ||
| }, WalkResult: true, Name: "d1", Level: 2, Path: "/d1", Parent: "/"}, | ||
|
|
||
| {TestName: "back_3_with_invalid_dir", TestPath: `/d1///d2/d3`, WalkFunc: func(w *RefWalker) bool { | ||
| w.Last() | ||
| w.Back() | ||
| return w.Back() | ||
| }, WalkResult: true, Name: "d1", Level: 2, Path: "/d1", Parent: "/"}, | ||
| } | ||
|
|
||
| for _, it := range list { | ||
| t.Run(it.TestName, func(test *testing.T) { | ||
|
|
||
| dirs := strings.Split(path.Clean(it.TestPath), "/") | ||
|
|
||
| rw := NewRefWalker(dirs) | ||
| result := it.WalkFunc(rw) | ||
|
|
||
| r := require.New(test) | ||
|
|
||
| r.Equal(it.WalkResult, result) | ||
| name, ok := rw.Name() | ||
| r.True(ok) | ||
| r.Equal(it.Name, name) | ||
|
|
||
| r.Equal(it.Level, rw.Level()) | ||
|
|
||
| path, ok := rw.Path() | ||
| r.True(ok) | ||
| r.Equal(it.Path, path) | ||
|
|
||
| parentPath, ok := rw.Parent() | ||
| r.True(ok) | ||
| r.Equal(it.Parent, parentPath) | ||
|
|
||
| }) | ||
| } | ||
|
|
||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package util | ||
|
|
||
| import ( | ||
| "strings" | ||
| ) | ||
|
|
||
| // SplitPath split files from a path | ||
| func SplitPath(path string) []string { | ||
| items := make([]string, 0) | ||
| for _, it := range strings.Split(path, "/") { | ||
| if len(it) > 0 { | ||
| items = append(items, it) | ||
| } | ||
| } | ||
|
|
||
| return items | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package util | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestSplitPath(t *testing.T) { | ||
|
|
||
| tests := []struct { | ||
| name string | ||
| path string | ||
| items []string | ||
| }{ | ||
| { | ||
| name: "empty root", | ||
| path: "/", | ||
| items: []string{}, | ||
| }, | ||
| { | ||
| name: "only 1 directory level deep", | ||
| path: "/file1", | ||
| items: []string{"file1"}, | ||
| }, | ||
| { | ||
| name: "nested directories", | ||
| path: "/dir1/dir2/dir3/file1", | ||
| items: []string{"dir1", "dir2", "dir3", "file1"}, | ||
| }, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding cases for empty subpath perhaps, e.g. /dir1/dir2//dir3///dir4
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| } | ||
|
|
||
| for _, it := range tests { | ||
| t.Run(it.name, func(t *testing.T) { | ||
|
|
||
| files := SplitPath(it.path) | ||
|
|
||
| require.Len(t, files, len(it.items)) | ||
|
|
||
| for i, v := range it.items { | ||
| require.Equal(t, v, files[i]) | ||
| } | ||
|
|
||
| }) | ||
| } | ||
|
|
||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should return error when d is nil, or when index is >= length, otherwise users will have to check the code to know what happened when the returned value is "".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed