Bug 1354308 - Entries API must support patches containing '..', r=froydnj
☠☠ backed out by 7ea39575ae0c ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 26 Apr 2017 15:13:43 +0200
changeset 403189 b06d30abb3581884f6c698ed772258295bec8379
parent 403188 28e4528663c45f76f8faf5111db3cf59bb0f9154
child 403190 d5fc098d4088acaf3fcfa57b547f4f54e2aa69be
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1354308
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1354308 - Entries API must support patches containing '..', r=froydnj
dom/filesystem/FileSystemSecurity.cpp
dom/filesystem/compat/tests/script_entries.js
dom/filesystem/compat/tests/test_basic.html
--- a/dom/filesystem/FileSystemSecurity.cpp
+++ b/dom/filesystem/FileSystemSecurity.cpp
@@ -84,19 +84,27 @@ FileSystemSecurity::Forget(ContentParent
 
 bool
 FileSystemSecurity::ContentProcessHasAccessTo(ContentParentId aId,
                                               const nsAString& aPath)
 {
   MOZ_ASSERT(NS_IsMainThread());
   AssertIsInMainProcess();
 
-  if (FindInReadable(NS_LITERAL_STRING(".."), aPath)) {
+#if defined(XP_WIN)
+  if (StringBeginsWith(aPath, NS_LITERAL_STRING("..\\")) ||
+      FindInReadable(NS_LITERAL_STRING("\\..\\"), aPath)) {
     return false;
   }
+#elif defined(XP_UNIX)
+  if (StringBeginsWith(aPath, NS_LITERAL_STRING("../")) ||
+      FindInReadable(NS_LITERAL_STRING("/../"), aPath)) {
+    return false;
+  }
+#endif
 
   nsTArray<nsString>* paths;
   if (!mPaths.Get(aId, &paths)) {
     return false;
   }
 
   for (uint32_t i = 0, len = paths->Length(); i < len; ++i) {
     if (FileSystemUtils::IsDescendantPath(paths->ElementAt(i), aPath)) {
--- a/dom/filesystem/compat/tests/script_entries.js
+++ b/dom/filesystem/compat/tests/script_entries.js
@@ -23,23 +23,31 @@ addMessageListener("entries.open", funct
   file1.append('foo.txt');
   file1.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
 
   var dir1 = tmpDir.clone();
   dir1.append('subdir');
   dir1.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
 
   var file2 = dir1.clone();
-  file2.append('bar.txt');
+  file2.append('bar..txt'); // Note the double ..
   file2.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
 
   var dir2 = dir1.clone();
   dir2.append('subsubdir');
   dir2.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
 
+  var dir3 = tmpDir.clone();
+  dir3.append('..subdir..');
+  dir3.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
+
+  var file3 = dir3.clone();
+  file3.append('bar.txt');
+  file3.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
+
   File.createFromNsIFile(tmpFile).then(function(file) {
     sendAsyncMessage("entries.opened", {
       data: [ new Directory(tmpDir.path), file ]
     });
   });
 });
 
 addMessageListener("entries.delete", function(e) {
--- a/dom/filesystem/compat/tests/test_basic.html
+++ b/dom/filesystem/compat/tests/test_basic.html
@@ -90,20 +90,20 @@ function test_directoryEntry() {
 }
 
 function test_directoryEntry_createReader() {
   var reader = directoryEntry.createReader();
   ok(reader, "We have a DirectoryReader");
 
   reader.readEntries(function(a) {
     ok(Array.isArray(a), "We want an array.");
-    is(a.length, 2, "reader.readyEntries returns 2 elements.");
+    is(a.length, 3, "reader.readyEntries returns 2 elements.");
 
-    for (var i = 0; i < 2; ++i) {
-      ok(a[i].name == "subdir" || a[i].name == "foo.txt", "Correct names");
+    for (var i = 0; i < 3; ++i) {
+      ok(a[i].name == "subdir" || a[i].name == "foo.txt" || a[i].name == "..subdir..", "Correct names");
       is(a[i].fullPath, directoryEntry.fullPath + "/" + a[i].name, "FullPath is correct");
     }
 
     // Called twice:
     reader.readEntries(function(a) {
       ok(Array.isArray(a), "We want an array.");
       is(a.length, 0, "reader.readyEntries returns 0 elements.");
       next();
@@ -171,17 +171,27 @@ function test_directoryEntry_getFile_sim
     is(e.name, "foo.txt", "We have the right FileEntry.");
     test_getParent(e, directoryEntry, /* nested */ false);
   }, function(e) {
     ok(false, "This should not happen.");
   });
 }
 
 function test_directoryEntry_getFile_deep() {
-  directoryEntry.getFile("subdir/bar.txt", {},
+  directoryEntry.getFile("subdir/bar..txt", {},
+  function(e) {
+    is(e.name, "bar..txt", "We have the right FileEntry.");
+    test_getParent(e, directoryEntry, /* nested */ true);
+  }, function(e) {
+    ok(false, "This should not happen.");
+  });
+}
+
+function test_directoryEntry_getFile_funnyName() {
+  directoryEntry.getFile("..subdir../bar.txt", {},
   function(e) {
     is(e.name, "bar.txt", "We have the right FileEntry.");
     test_getParent(e, directoryEntry, /* nested */ true);
   }, function(e) {
     ok(false, "This should not happen.");
   });
 }
 
@@ -240,16 +250,26 @@ function test_directoryEntry_getDirector
   function(e) {
     is(e.name, "subsubdir", "We have the right DirectoryEntry.");
     test_getParent(e, directoryEntry, /* nested */ true);
   }, function(e) {
     ok(false, "This should not happen.");
   });
 }
 
+function test_directoryEntry_getDirectory_funnyName() {
+  directoryEntry.getDirectory("..subdir..", {},
+  function(e) {
+    is(e.name, "..subdir..", "We have the right DirectoryEntry.");
+    test_getParent(e, directoryEntry, /* nested */ false);
+  }, function(e) {
+    ok(false, "This should not happen.");
+  });
+}
+
 function test_filesystem() {
   is(fileEntry.filesystem, directoryEntry.filesystem, "FileSystem object is shared.");
 
   var fs = fileEntry.filesystem;
   ok(fs.name, "FileSystem.name exists.");
   ok(fs.root, "FileSystem has a root.");
 
   is(fs.root.name, "", "FileSystem.root.name must be an empty string.");
@@ -311,19 +331,19 @@ function test_root_getFile_simple() {
     is(e.name, fileEntry.name, "We have the right FileEntry.");
     next();
   }, function(e) {
     ok(false, "This should not happen.");
   });
 }
 
 function test_root_getFile_deep() {
-  fileEntry.filesystem.root.getFile(directoryEntry.name + "/subdir/bar.txt", {},
+  fileEntry.filesystem.root.getFile(directoryEntry.name + "/subdir/bar..txt", {},
   function(e) {
-    is(e.name, "bar.txt", "We have the right FileEntry.");
+    is(e.name, "bar..txt", "We have the right FileEntry.");
     next();
   }, function(e) {
     ok(false, "This should not happen.");
   });
 }
 
 function test_root_getDirectory_securityError() {
   fileEntry.filesystem.root.getDirectory("foo", { create: true },
@@ -443,23 +463,25 @@ var tests = [
   test_directoryEntry_getParent,
 
   test_directoryEntry_getFile_securityError,
   test_directoryEntry_getFile_typeMismatchError,
   test_directoryEntry_getFile_nonValidPath,
   test_directoryEntry_getFile_nonExistingPath,
   test_directoryEntry_getFile_simple,
   test_directoryEntry_getFile_deep,
+  test_directoryEntry_getFile_funnyName,
 
   test_directoryEntry_getDirectory_securityError,
   test_directoryEntry_getDirectory_typeMismatchError,
   test_directoryEntry_getDirectory_nonValidPath,
   test_directoryEntry_getDirectory_nonExistingPath,
   test_directoryEntry_getDirectory_simple,
   test_directoryEntry_getDirectory_deep,
+  test_directoryEntry_getDirectory_funnyName,
 
   test_filesystem,
 
   test_root_getFile_securityError,
   test_root_getFile_typeMismatchError,
   test_root_getFile_nonValidPath,
   test_root_getFile_nonExistingPath,
   test_root_getFile_simple,