summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
Diffstat (limited to 'base')
-rw-r--r--base/file_path.cc28
-rw-r--r--base/file_path.h4
-rw-r--r--base/file_path_unittest.cc37
3 files changed, 63 insertions, 6 deletions
diff --git a/base/file_path.cc b/base/file_path.cc
index 094c699..70cfb51 100644
--- a/base/file_path.cc
+++ b/base/file_path.cc
@@ -47,6 +47,8 @@ namespace {
const char* kCommonDoubleExtensionSuffixes[] = { "gz", "z", "bz2" };
const char* kCommonDoubleExtensions[] = { "user.js" };
+const FilePath::CharType kStringTerminator = FILE_PATH_LITERAL('\0');
+
// If this FilePath contains a drive letter specification, returns the
// position of the last character of the drive letter specification,
// otherwise returns npos. This can only be true on Windows, when a pathname
@@ -182,6 +184,9 @@ FilePath::FilePath(const FilePath& that) : path_(that.path_) {
}
FilePath::FilePath(const StringType& path) : path_(path) {
+ StringType::size_type nul_pos = path_.find(kStringTerminator);
+ if (nul_pos != StringType::npos)
+ path_.erase(nul_pos, StringType::npos);
}
FilePath::~FilePath() {
@@ -454,7 +459,17 @@ bool FilePath::MatchesExtension(const StringType& extension) const {
}
FilePath FilePath::Append(const StringType& component) const {
- DCHECK(!IsPathAbsolute(component));
+ const StringType* appended = &component;
+ StringType without_nuls;
+
+ StringType::size_type nul_pos = component.find(kStringTerminator);
+ if (nul_pos != StringType::npos) {
+ without_nuls = component.substr(0, nul_pos);
+ appended = &without_nuls;
+ }
+
+ DCHECK(!IsPathAbsolute(*appended));
+
if (path_.compare(kCurrentDirectory) == 0) {
// Append normally doesn't do any normalization, but as a special case,
// when appending to kCurrentDirectory, just return a new path for the
@@ -463,7 +478,7 @@ FilePath FilePath::Append(const StringType& component) const {
// it's likely in practice to wind up with FilePath objects containing
// only kCurrentDirectory when calling DirName on a single relative path
// component.
- return FilePath(component);
+ return FilePath(*appended);
}
FilePath new_path(path_);
@@ -472,7 +487,7 @@ FilePath FilePath::Append(const StringType& component) const {
// Don't append a separator if the path is empty (indicating the current
// directory) or if the path component is empty (indicating nothing to
// append).
- if (component.length() > 0 && new_path.path_.length() > 0) {
+ if (appended->length() > 0 && new_path.path_.length() > 0) {
// Don't append a separator if the path still ends with a trailing
// separator after stripping (indicating the root directory).
if (!IsSeparator(new_path.path_[new_path.path_.length() - 1])) {
@@ -483,7 +498,7 @@ FilePath FilePath::Append(const StringType& component) const {
}
}
- new_path.path_.append(component);
+ new_path.path_.append(*appended);
return new_path;
}
@@ -589,7 +604,7 @@ FilePath FilePath::FromUTF8Unsafe(const std::string& utf8) {
}
#endif
-void FilePath::WriteToPickle(Pickle* pickle) {
+void FilePath::WriteToPickle(Pickle* pickle) const {
#if defined(OS_WIN)
pickle->WriteString16(path_);
#else
@@ -606,6 +621,9 @@ bool FilePath::ReadFromPickle(PickleIterator* iter) {
return false;
#endif
+ if (path_.find(kStringTerminator) != StringType::npos)
+ return false;
+
return true;
}
diff --git a/base/file_path.h b/base/file_path.h
index 09e8269..81de702 100644
--- a/base/file_path.h
+++ b/base/file_path.h
@@ -53,6 +53,8 @@
// between char[]-based pathnames on POSIX systems and wchar_t[]-based
// pathnames on Windows.
//
+// Paths can't contain NULs as a precaution agaist premature truncation.
+//
// Because a FilePath object should not be instantiated at the global scope,
// instead, use a FilePath::CharType[] and initialize it with
// FILE_PATH_LITERAL. At runtime, a FilePath object can be created from the
@@ -343,7 +345,7 @@ class BASE_EXPORT FilePath {
// AsUTF8Unsafe() for details.
static FilePath FromUTF8Unsafe(const std::string& utf8);
- void WriteToPickle(Pickle* pickle);
+ void WriteToPickle(Pickle* pickle) const;
bool ReadFromPickle(PickleIterator* iter);
// Normalize all path separators to backslash on Windows
diff --git a/base/file_path_unittest.cc b/base/file_path_unittest.cc
index ab25543..5a9e5cd 100644
--- a/base/file_path_unittest.cc
+++ b/base/file_path_unittest.cc
@@ -12,6 +12,9 @@
// This macro helps avoid wrapped lines in the test structs.
#define FPL(x) FILE_PATH_LITERAL(x)
+// This macro constructs strings which can contain NULs.
+#define FPS(x) FilePath::StringType(FPL(x), arraysize(FPL(x)) - 1)
+
struct UnaryTestData {
const FilePath::CharType* input;
const FilePath::CharType* expected;
@@ -1115,6 +1118,40 @@ TEST_F(FilePathTest, FromUTF8Unsafe_And_AsUTF8Unsafe) {
}
}
+TEST_F(FilePathTest, ConstructWithNUL) {
+ // Assert FPS() works.
+ ASSERT_TRUE(FPS("a\0b").length() == 3);
+
+ // Test constructor strips '\0'
+ FilePath path(FPS("a\0b"));
+ EXPECT_TRUE(path.value().length() == 1);
+ EXPECT_EQ(path.value(), FPL("a"));
+}
+
+TEST_F(FilePathTest, AppendWithNUL) {
+ // Assert FPS() works.
+ ASSERT_TRUE(FPS("b\0b").length() == 3);
+
+ // Test Append() strips '\0'
+ FilePath path(FPL("a"));
+ path = path.Append(FPS("b\0b"));
+ EXPECT_TRUE(path.value().length() == 3);
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+ EXPECT_EQ(path.value(), FPL("a\\b"));
+#else
+ EXPECT_EQ(path.value(), FPL("a/b"));
+#endif
+}
+
+TEST_F(FilePathTest, ReferencesParentWithNUL) {
+ // Assert FPS() works.
+ ASSERT_TRUE(FPS("..\0").length() == 3);
+
+ // Test ReferencesParent() doesn't break with "..\0"
+ FilePath path(FPS("..\0"));
+ EXPECT_TRUE(path.ReferencesParent());
+}
+
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
TEST_F(FilePathTest, NormalizePathSeparators) {
const struct UnaryTestData cases[] = {