diff --git a/archiver.go b/archiver.go index 32baf3e0..6bf20162 100644 --- a/archiver.go +++ b/archiver.go @@ -112,7 +112,7 @@ func sanitizeExtractPath(filePath string, destination string) error { // the target path, and make sure it's nested in the intended // destination, or bail otherwise. destpath := filepath.Join(destination, filePath) - if !strings.HasPrefix(destpath, destination) { + if !strings.HasPrefix(destpath, filepath.Clean(destination)) { return fmt.Errorf("%s: illegal file path", filePath) } return nil diff --git a/archiver_test.go b/archiver_test.go index 22de14ea..305030f7 100644 --- a/archiver_test.go +++ b/archiver_test.go @@ -19,6 +19,7 @@ func TestArchiver(t *testing.T) { } testWriteRead(t, name, ar) testMakeOpen(t, name, ar) + testMakeOpenWithDestinationEndingInSlash(t, name, ar) }) } } @@ -83,6 +84,39 @@ func testMakeOpen(t *testing.T, name string, ar Archiver) { symmetricTest(t, name, dest) } +// testMakeOpenWithDestinationEndingInSlash is similar to testMakeOpen except that +// it tests the case where destination path has a terminating forward slash especially +// on Windows os. +func testMakeOpenWithDestinationEndingInSlash(t *testing.T, name string, ar Archiver) { + tmp, err := ioutil.TempDir("", "archiver") + if err != nil { + t.Fatalf("[%s] %v", name, err) + } + defer os.RemoveAll(tmp) + + // Test creating archive + outfile := filepath.Join(tmp, "test-"+name) + err = ar.Make(outfile, []string{"testdata"}) + if err != nil { + t.Fatalf("[%s] making archive: didn't expect an error, but got: %v", name, err) + } + + if !ar.Match(outfile) { + t.Fatalf("[%s] identifying format should be 'true', but got 'false'", name) + } + + // Test extracting archive with destination that has a slash at the end + dest := filepath.Join(tmp, "extraction_test") + os.Mkdir(dest, 0755) + err = ar.Open(outfile, dest+"/") + if err != nil { + t.Fatalf("[%s] extracting archive [%s -> %s]: didn't expect an error, but got: %v", name, outfile, dest, err) + } + + // Check that what was extracted is what was compressed + symmetricTest(t, name, dest) +} + // symmetricTest compares the contents of a destination directory to the contents // of the test corpus and tests that they are equal. func symmetricTest(t *testing.T, name, dest string) {