зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1769094 - nsLocalFile::Append{,RelativePath} should throw when appending .. r=xpcom-reviewers,nika
Differential Revision: https://phabricator.services.mozilla.com/D146228
This commit is contained in:
Родитель
13691c6ee7
Коммит
f32c9fbea0
|
@ -346,12 +346,8 @@
|
||||||
tmpDir,
|
tmpDir,
|
||||||
"foo",
|
"foo",
|
||||||
".",
|
".",
|
||||||
"..",
|
|
||||||
"foo",
|
|
||||||
".",
|
|
||||||
"bar",
|
"bar",
|
||||||
"..",
|
".",
|
||||||
"bar"
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
PathUtils.join(tmpDir, "foo", "bar"),
|
PathUtils.join(tmpDir, "foo", "bar"),
|
||||||
|
|
|
@ -69,8 +69,9 @@ interface nsIFile : nsISupports
|
||||||
*
|
*
|
||||||
* @param node
|
* @param node
|
||||||
* A string which is intended to be a child node of the nsIFile.
|
* A string which is intended to be a child node of the nsIFile.
|
||||||
* For the |appendNative| method, the node must be in the native
|
* For security reasons, this cannot contain .. and cannot start with
|
||||||
* filesystem charset.
|
* a directory separator. For the |appendNative| method, the node must
|
||||||
|
* be in the native filesystem charset.
|
||||||
*/
|
*/
|
||||||
void append(in AString node);
|
void append(in AString node);
|
||||||
[noscript] void appendNative(in ACString node);
|
[noscript] void appendNative(in ACString node);
|
||||||
|
@ -463,7 +464,7 @@ interface nsIFile : nsISupports
|
||||||
*
|
*
|
||||||
* @param relativeFilePath
|
* @param relativeFilePath
|
||||||
* relativeFilePath is a native relative path. For security reasons,
|
* relativeFilePath is a native relative path. For security reasons,
|
||||||
* this cannot contain .. or cannot start with a directory separator.
|
* this cannot contain .. and cannot start with a directory separator.
|
||||||
* For the |appendRelativeNativePath| method, the relativeFilePath
|
* For the |appendRelativeNativePath| method, the relativeFilePath
|
||||||
* must be in the native filesystem charset.
|
* must be in the native filesystem charset.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -556,9 +556,10 @@ nsLocalFile::AppendNative(const nsACString& aFragment) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only one component of path can be appended
|
// only one component of path can be appended and cannot append ".."
|
||||||
nsACString::const_iterator begin, end;
|
nsACString::const_iterator begin, end;
|
||||||
if (FindCharInReadable('/', aFragment.BeginReading(begin),
|
if (aFragment.EqualsASCII("..") ||
|
||||||
|
FindCharInReadable('/', aFragment.BeginReading(begin),
|
||||||
aFragment.EndReading(end))) {
|
aFragment.EndReading(end))) {
|
||||||
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
||||||
}
|
}
|
||||||
|
@ -572,11 +573,35 @@ nsLocalFile::AppendRelativeNativePath(const nsACString& aFragment) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No leading '/'
|
// No leading '/' and cannot be ".."
|
||||||
if (aFragment.First() == '/') {
|
if (aFragment.First() == '/' || aFragment.EqualsASCII("..")) {
|
||||||
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aFragment.Contains('/')) {
|
||||||
|
// can't contain .. as a path component. Ensure that the valid components
|
||||||
|
// "foo..foo", "..foo", and "foo.." are not falsely detected,
|
||||||
|
// but the invalid paths "../", "foo/..", "foo/../foo",
|
||||||
|
// "../foo", etc are.
|
||||||
|
constexpr auto doubleDot = "/.."_ns;
|
||||||
|
nsACString::const_iterator start, end, offset;
|
||||||
|
aFragment.BeginReading(start);
|
||||||
|
aFragment.EndReading(end);
|
||||||
|
offset = end;
|
||||||
|
while (FindInReadable(doubleDot, start, offset)) {
|
||||||
|
if (offset == end || *offset == '/') {
|
||||||
|
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
||||||
|
}
|
||||||
|
start = offset;
|
||||||
|
offset = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// catches the remaining cases of prefixes
|
||||||
|
if (StringBeginsWith(aFragment, "../"_ns)) {
|
||||||
|
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mPath.EqualsLiteral("/")) {
|
if (!mPath.EqualsLiteral("/")) {
|
||||||
mPath.Append('/');
|
mPath.Append('/');
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,9 +151,7 @@ TEST(TestFilePreferencesUnix, Simple)
|
||||||
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(newPath));
|
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(newPath));
|
||||||
ASSERT_EQ(rv, NS_OK);
|
ASSERT_EQ(rv, NS_OK);
|
||||||
rv = newPath->AppendRelativeNativePath("allowed/../forbidden_dir/file"_ns);
|
rv = newPath->AppendRelativeNativePath("allowed/../forbidden_dir/file"_ns);
|
||||||
ASSERT_EQ(rv, NS_OK);
|
ASSERT_EQ(rv, NS_ERROR_FILE_UNRECOGNIZED_PATH);
|
||||||
rv = newPath->Exists(&exists);
|
|
||||||
ASSERT_EQ(rv, NS_ERROR_FILE_ACCESS_DENIED);
|
|
||||||
|
|
||||||
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(newPath));
|
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(newPath));
|
||||||
ASSERT_EQ(rv, NS_OK);
|
ASSERT_EQ(rv, NS_OK);
|
||||||
|
|
|
@ -183,3 +183,27 @@ add_task(
|
||||||
file.remove(true);
|
file.remove(true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
add_task(function test_file_append_parent() {
|
||||||
|
const SEPARATOR = AppConstants.platform === "win" ? "\\" : "/";
|
||||||
|
|
||||||
|
const file = do_get_profile();
|
||||||
|
|
||||||
|
Assert.throws(
|
||||||
|
() => file.append(".."),
|
||||||
|
/NS_ERROR_FILE_UNRECOGNIZED_PATH/,
|
||||||
|
`nsLocalFile::Append("..") throws`
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.throws(
|
||||||
|
() => file.appendRelativePath(".."),
|
||||||
|
/NS_ERROR_FILE_UNRECOGNIZED_PATH/,
|
||||||
|
`nsLocalFile::AppendRelativePath("..") throws`
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.throws(
|
||||||
|
() => file.appendRelativePath(`foo${SEPARATOR}..${SEPARATOR}baz`),
|
||||||
|
/NS_ERROR_FILE_UNRECOGNIZED_PATH/,
|
||||||
|
`nsLocalFile::AppendRelativePath(path) fails when path contains ".."`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче