Fix Buffer drops last null character in UTF-8
authorkoichik <koichik@improvement.jp>
Tue, 21 Jun 2011 15:53:31 +0000 (00:53 +0900)
committerkoichik <koichik@improvement.jp>
Wed, 13 Jul 2011 17:21:56 +0000 (02:21 +0900)
Reproduce:

    $ node
    > buf = new Buffer('\0')
    <Buffer >
    > buf.length
    0
    > buf = new Buffer(1)
    <Buffer 28>
    > buf.write('\0')
    0

Fixes #394.
Fixes #1210.

src/node_buffer.cc
test/simple/test-buffer.js

index 33870c3..4520548 100644 (file)
@@ -447,7 +447,15 @@ Handle<Value> Buffer::Utf8Write(const Arguments &args) {
 
   size_t offset = args[1]->Uint32Value();
 
-  if (s->Length() > 0 && offset >= buffer->length_) {
+  int length = s->Length();
+
+  if (length == 0) {
+    constructor_template->GetFunction()->Set(chars_written_sym,
+                                             Integer::New(0));
+    return scope.Close(Integer::New(0));
+  }
+
+  if (length > 0 && offset >= buffer->length_) {
     return ThrowException(Exception::TypeError(String::New(
             "Offset is out of bounds")));
   }
@@ -468,7 +476,13 @@ Handle<Value> Buffer::Utf8Write(const Arguments &args) {
   constructor_template->GetFunction()->Set(chars_written_sym,
                                            Integer::New(char_written));
 
-  if (written > 0 && p[written-1] == '\0') written--;
+  if (written > 0 && p[written-1] == '\0' && char_written == length) {
+    uint16_t last_char;
+    s->Write(&last_char, length - 1, 1, String::NO_HINTS);
+    if (last_char != 0 || written > s->Utf8Length()) {
+      written--;
+    }
+  }
 
   return scope.Close(Integer::New(written));
 }
index ad062e6..6b35d72 100644 (file)
@@ -526,3 +526,30 @@ assert.equal(0xef, b[3]);
 assert.throws(function() {
   new Buffer('"pong"', 0, 6, 8031, '127.0.0.1')
 });
+
+// #1210 Test UTF-8 string includes null character
+var buf = new Buffer('\0');
+assert.equal(buf.length, 1);
+buf = new Buffer('\0\0');
+assert.equal(buf.length, 2);
+
+buf = new Buffer(2);
+var written = buf.write(''); // 0byte
+assert.equal(written, 0);
+written = buf.write('\0'); // 1byte (v8 adds null terminator)
+assert.equal(written, 1);
+written = buf.write('a\0'); // 1byte * 2
+assert.equal(written, 2);
+written = buf.write('あ'); // 3bytes
+assert.equal(written, 0);
+written = buf.write('\0あ'); // 1byte + 3bytes
+assert.equal(written, 1);
+written = buf.write('\0\0あ'); // 1byte * 2 + 3bytes
+assert.equal(written, 2);
+
+buf = new Buffer(10);
+written = buf.write('あいう'); // 3bytes * 3 (v8 adds null terminator)
+assert.equal(written, 9);
+written = buf.write('あいう\0'); // 3bytes * 3 + 1byte
+assert.equal(written, 10);
+