Add "bool FilePath::ReferencesParent()" which adds a clean & simple way for
checking for ".." in a FilePath. Needed to make an upcoming security fix
clean.

BUG=NONE
TEST=FilePathTest.ReferencesParent

Review URL: http://codereview.chromium.org/172012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23528 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 067086103743fa898f4dedae1c7c07a9688c27be
diff --git a/base/file_path.cc b/base/file_path.cc
index 6134f2b..222b225 100644
--- a/base/file_path.cc
+++ b/base/file_path.cc
@@ -461,3 +461,17 @@
     }
   }
 }
+
+bool FilePath::ReferencesParent() const {
+  std::vector<FilePath::StringType> components;
+  GetComponents(&components);
+
+  std::vector<FilePath::StringType>::const_iterator it = components.begin();
+  for (; it != components.end(); ++it) {
+    const FilePath::StringType& component = *it;
+    if (component == kParentDirectory)
+      return true;
+  }
+  return false;
+}
+
diff --git a/base/file_path.h b/base/file_path.h
index 6bd2216..0b2ba5c 100644
--- a/base/file_path.h
+++ b/base/file_path.h
@@ -226,6 +226,10 @@
   // separator.
   FilePath StripTrailingSeparators() const;
 
+  // Returns true if this FilePath contains any attempt to reference a parent
+  // directory (i.e. has a path component that is ".."
+  bool ReferencesParent() const;
+
   // Older Chromium code assumes that paths are always wstrings.
   // This function converts a wstring to a FilePath, and is useful to smooth
   // porting that old code to the FilePath API.
diff --git a/base/file_path_unittest.cc b/base/file_path_unittest.cc
index ca30baa..e14bbca 100644
--- a/base/file_path_unittest.cc
+++ b/base/file_path_unittest.cc
@@ -535,7 +535,6 @@
       b.value();
   }
 
-  
   for (size_t i = 0; i < arraysize(cases); ++i) {
     FilePath a(cases[i].inputs[0]);
     FilePath b(cases[i].inputs[1]);
@@ -734,3 +733,35 @@
         "i: " << i << ", path: " << path.value() << ", ext: " << ext;
   }
 }
+
+TEST_F(FilePathTest, ReferencesParent) {
+  const struct UnaryBooleanTestData cases[] = {
+    { FPL("."),        false },
+    { FPL(".."),       true },
+    { FPL("a.."),      false },
+    { FPL("..a"),      false },
+    { FPL("../"),      true },
+    { FPL("/.."),      true },
+    { FPL("/../"),     true },
+    { FPL("/a../"),    false },
+    { FPL("/..a/"),    false },
+    { FPL("//.."),     true },
+    { FPL("..//"),     true },
+    { FPL("//..//"),   true },
+    { FPL("a//..//c"), true },
+    { FPL("../b/c"),   true },
+    { FPL("/../b/c"),  true },
+    { FPL("a/b/.."),   true },
+    { FPL("a/b/../"),  true },
+    { FPL("a/../c"),   true },
+    { FPL("a/b/c"),    false },
+  };
+
+  for (size_t i = 0; i < arraysize(cases); ++i) {
+    FilePath input(cases[i].input);
+    bool observed = input.ReferencesParent();
+    EXPECT_EQ(cases[i].expected, observed) <<
+              "i: " << i << ", input: " << input.value();
+  }
+}
+