fixing panic when root is symlink (#1429)

* fixing panic when root is symlink
checking root path is a symlink before os.Stat which panics

* fixing formatting

* adding test to verify symlink root path check

* fixing typo
This commit is contained in:
Alex Harrington 2017-02-16 05:02:51 +00:00 committed by Matt Holt
parent dc3efc939c
commit 55bded68c2
2 changed files with 54 additions and 11 deletions

View File

@ -28,16 +28,23 @@ func setupRoot(c *caddy.Controller) error {
return c.ArgErr()
}
}
// Check if root path exists
_, err := os.Stat(config.Root)
if err != nil {
if os.IsNotExist(err) {
// Allow this, because the folder might appear later.
// But make sure the user knows!
log.Printf("[WARNING] Root path does not exist: %s", config.Root)
} else {
return c.Errf("Unable to access root path '%s': %v", config.Root, err)
//first check that the path is not a symlink, os.Stat panics when this is true
info, _ := os.Lstat(config.Root)
if info != nil && info.Mode()&os.ModeSymlink == os.ModeSymlink {
//just print out info, delegate responsibility for symlink validity to
//underlying Go framework, no need to test / verify twice
log.Printf("[INFO] Root path is symlink: %s", config.Root)
} else {
// Check if root path exists
_, err := os.Stat(config.Root)
if err != nil {
if os.IsNotExist(err) {
// Allow this, because the folder might appear later.
// But make sure the user knows!
log.Printf("[WARNING] Root path does not exist: %s", config.Root)
} else {
return c.Errf("Unable to access root path '%s': %v", config.Root, err)
}
}
}

View File

@ -91,7 +91,7 @@ func TestRoot(t *testing.T) {
}
}
// getTempDirPath returnes the path to the system temp directory. If it does not exists - an error is returned.
// getTempDirPath returns the path to the system temp directory. If it does not exists - an error is returned.
func getTempDirPath() (string, error) {
tempDir := os.TempDir()
_, err := os.Stat(tempDir)
@ -104,3 +104,39 @@ func getTempDirPath() (string, error) {
func getInaccessiblePath(file string) string {
return filepath.Join("C:", "file\x00name") // null byte in filename is not allowed on Windows AND unix
}
func TestSymlinkRoot(t *testing.T) {
origDir, err := ioutil.TempDir("", "root_test")
if err != nil {
t.Fatalf("BeforeTest: Failed to create temp dir for testing! Error was: %v", err)
}
defer func() {
os.Remove(origDir)
}()
tempDir, err := getTempDirPath()
if err != nil {
t.Fatalf("BeforeTest: Failed to find an existing directory for testing! Error was: %v", err)
}
symlinkDir := filepath.Join(tempDir, "symlink")
err = os.Symlink(origDir, symlinkDir)
if err != nil {
if strings.Contains(err.Error(), "A required privilege is not held by the client") {
t.Skip("BeforeTest: A required privilege is not held by the client and is required to create a symlink to run this test.")
}
t.Fatalf("BeforeTest: Cannot create symlink! Error was: %v", err)
}
defer func() {
os.Remove(symlinkDir)
}()
input := fmt.Sprintf(`root %s`, symlinkDir)
c := caddy.NewTestController("http", input)
err = setupRoot(c)
_ = httpserver.GetConfig(c)
if err != nil {
t.Errorf("Test Symlink Root: Expected no error but found one for input %s. Error was: %v", input, err)
}
}