mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Fix one-character directory issue in the volume option (#20122).
The issue comes from the implementation of volumeSplitN() where a driver letter (`[a-zA-Z]:`) was assumed to follow either `:`, `/`, or `\\`. In Windows driver letter appears in two situations: a. `^[a-zA-Z]:` (A colon followed by `^[a-zA-Z]:` is OK as colon is the separator in volume option) b. A string in the format like `\\?\C:\Windows\...` (UNC). Therefore, a driver letter can only follow either a `:` or `\\` This PR removes the condition of `/` before the driver letter so that options like `-v /tmp/q:/foo` could be handled correctly. A couple of tests has also been added. This PR fixes #20122. Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
parent
9ea7e082ef
commit
800a7d513d
3 changed files with 20 additions and 3 deletions
|
@ -4243,3 +4243,12 @@ func (s *DockerSuite) TestRunAttachFailedNoLeak(c *check.C) {
|
||||||
// NGoroutines is not updated right away, so we need to wait before failing
|
// NGoroutines is not updated right away, so we need to wait before failing
|
||||||
c.Assert(waitForGoroutines(nroutines), checker.IsNil)
|
c.Assert(waitForGoroutines(nroutines), checker.IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test for one character directory name case (#20122)
|
||||||
|
func (s *DockerSuite) TestRunVolumeWithOneCharacter(c *check.C) {
|
||||||
|
testRequires(c, DaemonIsLinux)
|
||||||
|
|
||||||
|
out, _ := dockerCmd(c, "run", "-v", "/tmp/q:/foo", "busybox", "sh", "-c", "find /foo")
|
||||||
|
fmt.Printf("OUTPUT: %+v", out)
|
||||||
|
c.Assert(strings.TrimSpace(out), checker.Equals, "/foo")
|
||||||
|
}
|
||||||
|
|
|
@ -695,8 +695,12 @@ func validatePath(val string, validator func(string) bool) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// volumeSplitN splits raw into a maximum of n parts, separated by a separator colon.
|
// volumeSplitN splits raw into a maximum of n parts, separated by a separator colon.
|
||||||
// A separator colon is the last `:` character in the regex `[/:\\]?[a-zA-Z]:` (note `\\` is `\` escaped).
|
// A separator colon is the last `:` character in the regex `[:\\]?[a-zA-Z]:` (note `\\` is `\` escaped).
|
||||||
// This allows to correctly split strings such as `C:\foo:D:\:rw`.
|
// In Windows driver letter appears in two situations:
|
||||||
|
// a. `^[a-zA-Z]:` (A colon followed by `^[a-zA-Z]:` is OK as colon is the separator in volume option)
|
||||||
|
// b. A string in the format like `\\?\C:\Windows\...` (UNC).
|
||||||
|
// Therefore, a driver letter can only follow either a `:` or `\\`
|
||||||
|
// This allows to correctly split strings such as `C:\foo:D:\:rw` or `/tmp/q:/foo`.
|
||||||
func volumeSplitN(raw string, n int) []string {
|
func volumeSplitN(raw string, n int) []string {
|
||||||
var array []string
|
var array []string
|
||||||
if len(raw) == 0 || raw[0] == ':' {
|
if len(raw) == 0 || raw[0] == ':' {
|
||||||
|
@ -721,7 +725,8 @@ func volumeSplitN(raw string, n int) []string {
|
||||||
if (potentialDriveLetter >= 'A' && potentialDriveLetter <= 'Z') || (potentialDriveLetter >= 'a' && potentialDriveLetter <= 'z') {
|
if (potentialDriveLetter >= 'A' && potentialDriveLetter <= 'Z') || (potentialDriveLetter >= 'a' && potentialDriveLetter <= 'z') {
|
||||||
if right > 1 {
|
if right > 1 {
|
||||||
beforePotentialDriveLetter := raw[right-2]
|
beforePotentialDriveLetter := raw[right-2]
|
||||||
if beforePotentialDriveLetter != ':' && beforePotentialDriveLetter != '/' && beforePotentialDriveLetter != '\\' {
|
// Only `:` or `\\` are checked (`/` could fall into the case of `/tmp/q:/foo`)
|
||||||
|
if beforePotentialDriveLetter != ':' && beforePotentialDriveLetter != '\\' {
|
||||||
// e.g. `C:` is not preceded by any delimiter, therefore it was not a drive letter but a path ending with `C:`.
|
// e.g. `C:` is not preceded by any delimiter, therefore it was not a drive letter but a path ending with `C:`.
|
||||||
array = append(array, raw[left:right])
|
array = append(array, raw[left:right])
|
||||||
left = right + 1
|
left = right + 1
|
||||||
|
|
|
@ -801,6 +801,9 @@ func TestVolumeSplitN(t *testing.T) {
|
||||||
{`..\`, -1, []string{`..\`}},
|
{`..\`, -1, []string{`..\`}},
|
||||||
{`c:\:..\`, -1, []string{`c:\`, `..\`}},
|
{`c:\:..\`, -1, []string{`c:\`, `..\`}},
|
||||||
{`c:\:d:\:xyzzy`, -1, []string{`c:\`, `d:\`, `xyzzy`}},
|
{`c:\:d:\:xyzzy`, -1, []string{`c:\`, `d:\`, `xyzzy`}},
|
||||||
|
|
||||||
|
// Cover directories with one-character name
|
||||||
|
{`/tmp/x/y:/foo/x/y`, -1, []string{`/tmp/x/y`, `/foo/x/y`}},
|
||||||
} {
|
} {
|
||||||
res := volumeSplitN(x.input, x.n)
|
res := volumeSplitN(x.input, x.n)
|
||||||
if len(res) < len(x.expected) {
|
if len(res) < len(x.expected) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue