fs: fix corruption in writeFile and writeFileSync
authorOlov Lassus <olov.lassus@gmail.com>
Thu, 5 Mar 2015 00:03:34 +0000 (01:03 +0100)
committerBert Belder <bertbelder@gmail.com>
Wed, 25 Mar 2015 01:18:16 +0000 (18:18 -0700)
1. writeFileSync bumps position incorrectly, causing it to drift in
iteration three and onwards.

2. Append mode files will get corrupted in the middle if writeFile or
writeFileSync iterates multiple times, unless running on Linux. position
starts out as null so first write is OK, but then position will refer to
a location inside an existing file, corrupting that data. Linux ignores
position for append mode files so it doesn't happen there.

This commit fixes these two related issues by bumping position correctly
and by always using null as the position argument to write/writeSync for
append mode files.

PR-URL: https://github.com/iojs/io.js/pull/1063
Reviewed-By: Bert Belder <bertbelder@gmail.com>
lib/fs.js

index 77bcbac61a5eca257d06e8db12ed6e6c6962c96d..472d03cc75414c094be4b7405a89d2f66bfeb841 100644 (file)
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -1099,7 +1099,9 @@ function writeAll(fd, buffer, offset, length, position, callback) {
       } else {
         offset += written;
         length -= written;
-        position += written;
+        if (position !== null) {
+          position += written;
+        }
         writeAll(fd, buffer, offset, length, position, callback);
       }
     }
@@ -1148,13 +1150,17 @@ fs.writeFileSync = function(path, data, options) {
   if (!(data instanceof Buffer)) {
     data = new Buffer('' + data, options.encoding || 'utf8');
   }
-  var written = 0;
+  var offset = 0;
   var length = data.length;
   var position = /a/.test(flag) ? null : 0;
   try {
-    while (written < length) {
-      written += fs.writeSync(fd, data, written, length - written, position);
-      position += written;
+    while (length > 0) {
+      var written = fs.writeSync(fd, data, offset, length, position);
+      offset += written;
+      length -= written;
+      if (position !== null) {
+        position += written;
+      }
     }
   } finally {
     fs.closeSync(fd);