src: fix StringBytes::Write if string is external
authorRefael Ackermann <refack@gmail.com>
Fri, 9 May 2014 11:12:37 +0000 (14:12 +0300)
committerFedor Indutny <fedor@indutny.com>
Mon, 12 May 2014 10:59:16 +0000 (14:59 +0400)
Signed-off-by: Fedor Indutny <fedor@indutny.com>
src/string_bytes.cc
test/simple/test-crypto-from-binary.js [new file with mode: 0644]
test/simple/test-stringbytes-external.js

index 744021096979ac7836e71ee68814e0b62e43b5d9..de41ec1d4ace6c334b20ab5d61f00097f4e642f7 100644 (file)
@@ -300,6 +300,7 @@ size_t StringBytes::Write(Isolate* isolate,
   const char* data = NULL;
   size_t len = 0;
   bool is_extern = GetExternalParts(isolate, val, &data, &len);
+  size_t extlen = len;
 
   CHECK(val->IsString() == true);
   Local<String> str = val.As<String>();
@@ -342,7 +343,7 @@ size_t StringBytes::Write(Isolate* isolate,
 
     case BASE64:
       if (is_extern) {
-        base64_decode(buf, buflen, data, len);
+        len = base64_decode(buf, buflen, data, extlen);
       } else {
         String::Value value(str);
         len = base64_decode(buf, buflen, *value, value.length());
@@ -354,7 +355,7 @@ size_t StringBytes::Write(Isolate* isolate,
 
     case HEX:
       if (is_extern) {
-        hex_decode(buf, buflen, data, len);
+        len = hex_decode(buf, buflen, data, extlen);
       } else {
         String::Value value(str);
         len = hex_decode(buf, buflen, *value, value.length());
diff --git a/test/simple/test-crypto-from-binary.js b/test/simple/test-crypto-from-binary.js
new file mode 100644 (file)
index 0000000..2033617
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// This is the same as test/simple/test-crypto, but from before the shift
+// to use buffers by default.
+
+
+var common = require('../common');
+var assert = require('assert');
+
+try {
+  var crypto = require('crypto');
+} catch (e) {
+  console.log('Not compiled with OPENSSL support.');
+  process.exit();
+}
+
+var EXTERN_APEX = 0xFBEE9;
+
+// manually controlled string for checking binary output
+var ucs2_control = 'a\u0000';
+
+// grow the strings to proper length
+while (ucs2_control.length <= EXTERN_APEX) {
+  ucs2_control += ucs2_control;
+}
+
+
+// check resultant buffer and output string
+var b = new Buffer(ucs2_control + ucs2_control, 'ucs2');
+
+//
+// Test updating from birant data
+//
+(function() {
+  var datum1 = b.slice(700000);
+  var hash1_converted = crypto.createHash('sha1')
+    .update(datum1.toString('base64'), 'base64')
+    .digest('hex');
+  var hash1_direct = crypto.createHash('sha1').update(datum1).digest('hex');
+  assert.equal(hash1_direct, hash1_converted, 'should hash the same.');
+
+  var datum2 = b;
+  var hash2_converted = crypto.createHash('sha1')
+    .update(datum2.toString('base64'), 'base64')
+    .digest('hex');
+  var hash2_direct = crypto.createHash('sha1').update(datum2).digest('hex');
+  assert.equal(hash2_direct, hash2_converted, 'should hash the same.');
+})();
index 87823cd07230db47efd9096a8cdc67486e459abf..c7c716c836b394f1ab595fcff59045d9fd6a73b1 100644 (file)
@@ -72,3 +72,63 @@ for (var i = 0; i < c_bin.length; i++) {
 assert.equal(c_bin.toString('ucs2'), c_ucs.toString('ucs2'));
 assert.equal(c_bin.toString('binary'), ucs2_control);
 assert.equal(c_ucs.toString('binary'), ucs2_control);
+
+
+
+// now let's test BASE64 and HEX ecoding/decoding
+var RADIOS = 2;
+var PRE_HALF_APEX = Math.ceil(EXTERN_APEX / 2) - RADIOS;
+var PRE_3OF4_APEX = Math.ceil((EXTERN_APEX / 4) * 3) - RADIOS;
+
+(function () {
+  for (var j = 0; j < RADIOS * 2; j += 1) {
+    var datum = b;
+    var slice = datum.slice(0, PRE_HALF_APEX + j);
+    var slice2 = datum.slice(0, PRE_HALF_APEX + j + 2);
+    var pumped_string = slice.toString('hex');
+    var pumped_string2 = slice2.toString('hex');
+    var decoded = new Buffer(pumped_string, 'hex');
+
+    var metadata = "\nEXTERN_APEX=1031913 - pumped_string.length="
+    metadata += pumped_string.length + '\n';
+
+    // the string are the same?
+    for (var k = 0; k < pumped_string.length; ++k) {
+      assert.equal(pumped_string[k], pumped_string2[k],
+                   metadata + 'chars should be the same at ' + k);
+    }
+
+    // the recoded buffer is the same?
+    for (var i = 0; i < decoded.length; ++i) {
+      assert.equal(datum[i], decoded[i],
+                   metadata + 'bytes should be the same at ' + i);
+    }
+  }
+})();
+
+(function () {
+  for (var j = 0; j < RADIOS * 2; j += 1) {
+    var datum = b;
+    var slice = datum.slice(0, PRE_3OF4_APEX + j);
+    var slice2 = datum.slice(0, PRE_3OF4_APEX + j + 2);
+    var pumped_string = slice.toString('base64');
+    var pumped_string2 = slice2.toString('base64');
+    var decoded = new Buffer(pumped_string, 'base64');
+
+    var metadata = "\nEXTERN_APEX=1031913 - data=" + slice.length
+    metadata += " pumped_string.length=" + pumped_string.length + '\n';
+
+    // the string are the same?
+    for (var k = 0; k < pumped_string.length - 3; ++k) {
+      assert.equal(pumped_string[k], pumped_string2[k],
+                   metadata + 'chars should be the same for two slices at '
+                   + k + ' ' + pumped_string[k] + ' ' + pumped_string2[k]);
+    }
+
+    // the recoded buffer is the same?
+    for (var i = 0; i < decoded.length; ++i) {
+      assert.equal(datum[i], decoded[i],
+                   metadata + 'bytes should be the same at ' + i);
+    }
+  }
+})();