Skip to content

Commit

Permalink
Fix for character incompatibility corner case on Windows.
Browse files Browse the repository at this point in the history
We generally rely on system calls rejecting invalid path names so that
we can avoid checking every path for invalid characters, but backslashes
on Windows can be problematic if synchronizing against a POSIX system
where a directory at the same level as the invalid filename has a name
that is the prefix (pre-'\' string) of the invalid filename. This commit
adds an explicit check for this case with negligible overhead.
  • Loading branch information
xenoscopic committed Jul 20, 2018
1 parent 52ebbe9 commit cca818e
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 0 deletions.
37 changes: 37 additions & 0 deletions pkg/sync/transition.go
Expand Up @@ -190,6 +190,11 @@ func (t *transitioner) ensureNotExists(path string) error {
}

func (t *transitioner) removeFile(path string, target *Entry) error {
// Watch for special characters.
if pathContainsInvalidCharacters(path) {
return errors.New("path contains invalid characters")
}

// Ensure that the existing entry hasn't been modified from what we're
// expecting.
if _, _, _, err := t.ensureExpectedFile(path, target); err != nil {
Expand All @@ -201,6 +206,11 @@ func (t *transitioner) removeFile(path string, target *Entry) error {
}

func (t *transitioner) removeSymlink(path string, target *Entry) error {
// Watch for special characters.
if pathContainsInvalidCharacters(path) {
return errors.New("path contains invalid characters")
}

// Ensure that the existing symlink hasn't been modified from what we're
// expecting.
if err := t.ensureExpectedSymlink(path, target); err != nil {
Expand All @@ -212,6 +222,12 @@ func (t *transitioner) removeSymlink(path string, target *Entry) error {
}

func (t *transitioner) removeDirectory(path string, target *Entry) bool {
// Watch for special characters.
if pathContainsInvalidCharacters(path) {
t.recordProblem(path, errors.New("path contains invalid characters"))
return false
}

// Compute the full path to this directory.
fullPath := filepath.Join(t.root, path)

Expand Down Expand Up @@ -332,6 +348,11 @@ func (t *transitioner) remove(path string, target *Entry) *Entry {
}

func (t *transitioner) swapFile(path string, oldEntry, newEntry *Entry) error {
// Watch for special characters.
if pathContainsInvalidCharacters(path) {
return errors.New("path contains invalid characters")
}

// Compute the full path to this file.
fullPath := filepath.Join(t.root, path)

Expand Down Expand Up @@ -394,6 +415,11 @@ func (t *transitioner) swapFile(path string, oldEntry, newEntry *Entry) error {
}

func (t *transitioner) createFile(path string, target *Entry) error {
// Watch for special characters.
if pathContainsInvalidCharacters(path) {
return errors.New("path contains invalid characters")
}

// Ensure that the target path doesn't exist, e.g. due to a case conflict or
// modification since the last scan.
if err := t.ensureNotExists(path); err != nil {
Expand Down Expand Up @@ -429,6 +455,11 @@ func (t *transitioner) createFile(path string, target *Entry) error {
}

func (t *transitioner) createSymlink(path string, target *Entry) error {
// Watch for special characters.
if pathContainsInvalidCharacters(path) {
return errors.New("path contains invalid characters")
}

// Ensure that the target path doesn't exist, e.g. due to a case conflict or
// modification since the last scan.
if err := t.ensureNotExists(path); err != nil {
Expand All @@ -445,6 +476,12 @@ func (t *transitioner) createSymlink(path string, target *Entry) error {
}

func (t *transitioner) createDirectory(path string, target *Entry) *Entry {
// Watch for special characters.
if pathContainsInvalidCharacters(path) {
t.recordProblem(path, errors.New("path contains invalid characters"))
return nil
}

// Ensure that the target path doesn't exist, e.g. due to a case conflict or
// modification since the last scan.
if err := t.ensureNotExists(path); err != nil {
Expand Down
7 changes: 7 additions & 0 deletions pkg/sync/transition_posix.go
@@ -0,0 +1,7 @@
// +build !windows

package sync

func pathContainsInvalidCharacters(path string) bool {
return false
}
9 changes: 9 additions & 0 deletions pkg/sync/transition_windows.go
@@ -0,0 +1,9 @@
package sync

import (
"strings"
)

func pathContainsInvalidCharacters(path string) bool {
return strings.Contains(path, "\\")
}

0 comments on commit cca818e

Please sign in to comment.