Bug 1117580 - Throw an exception if PR_APPEND is passed without PR_TRUNCATE to nsAtomicFileOutputStream::Init. r=yoric

This commit is contained in:
Tooru Fujisawa 2015-01-16 00:01:46 +09:00
parent 03fd8f8f79
commit 512bb0faad
3 changed files with 50 additions and 0 deletions

View File

@ -869,6 +869,13 @@ NS_IMETHODIMP
nsAtomicFileOutputStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
int32_t behaviorFlags)
{
// While `PR_APPEND` is not supported, `-1` is used as `ioFlags` parameter
// in some places, and `PR_APPEND | PR_TRUNCATE` does not require appending
// to existing file. So, throw an exception only if `PR_APPEND` is
// explicitly specified without `PR_TRUNCATE`.
if ((ioFlags & PR_APPEND) && !(ioFlags & PR_TRUNCATE)) {
return NS_ERROR_INVALID_ARG;
}
return nsFileOutputStream::Init(file, ioFlags, perm, behaviorFlags);
}

View File

@ -0,0 +1,42 @@
/* atomic-file-output-stream and safe-file-output-stream should throw and
* exception if PR_APPEND is explicity specified without PR_TRUNCATE. */
const PR_WRONLY = 0x02;
const PR_CREATE_FILE = 0x08;
const PR_APPEND = 0x10;
const PR_TRUNCATE = 0x20;
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
function check_flag(file, contractID, flags, throws) {
let stream = Cc[contractID].createInstance(Ci.nsIFileOutputStream);
if (throws) {
/* NS_ERROR_INVALID_ARG is reported as NS_ERROR_ILLEGAL_VALUE, since they
* are same value. */
Assert.throws(() => stream.init(file, flags, 0o644, 0),
/NS_ERROR_ILLEGAL_VALUE/);
} else {
stream.init(file, flags, 0o644, 0);
stream.close();
}
}
function run_test() {
let filename = "test.txt";
let file = Services.dirsvc.get("TmpD", Ci.nsIFile);
file.append(filename);
let tests = [
[PR_WRONLY | PR_CREATE_FILE | PR_APPEND | PR_TRUNCATE, false],
[PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, false],
[PR_WRONLY | PR_CREATE_FILE | PR_APPEND, true],
[-1, false],
];
for (let contractID of ["@mozilla.org/network/atomic-file-output-stream;1",
"@mozilla.org/network/safe-file-output-stream;1"]) {
for (let [flags, throws] of tests) {
check_flag(file, contractID, flags, throws);
}
}
}

View File

@ -307,3 +307,4 @@ run-if = os == "win"
# The local cert service used by this test is not currently shipped on Android
skip-if = os == "android"
[test_1073747.js]
[test_safeoutputstream_append.js]