Skip to content

New Uint8Arrays are sometimes filled with garbage #2930

Closed
@dchest

Description

Unfortunately, I don't have a neat small test case, so please bear with me.

One TweetNaCl-js test with Node.js 4.1 fails, while succeeding with 0.12 and io.js v3.3.1. The test is encrypting a message and comparing the result with a known good value.

To reproduce:

mkdir reproduce
cd reproduce
git clone https://github.com/dchest/tweetnacl-js.git
cd tweetnacl-js
npm install tape
NACL_SRC=nacl.js node ./test/04-secretbox.js | more

Output:

TAP version 13
# nacl.secretbox random test vectors
ok 1 box should be created
ok 2 should be equal
ok 3 box should open
ok 4 should be equal
ok 5 box should be created
not ok 6 should be equal
  ---
    operator: equal
    expected: 'VJViVugBhKeaOvfSlHkTzUQ='
    actual:   'ZpRiVugBhKeaOvfSlHkTzUQ='
    at: Test.<anonymous> (/Users/dchest/reproduce/tweetnacl-js/test/04-secretbox.js:10:17)
  ...

(actual may be different for you)

The cause is in this function in nacl.js:

https://github.com/dchest/tweetnacl-js/blob/master/nacl.js#L990

nacl.secretbox = function(msg, nonce, key) {
  checkArrayTypes(msg, nonce, key);
  checkLengths(key, nonce);
  var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); // <-- BUG HERE
  var c = new Uint8Array(m.length);
  for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i];
  crypto_secretbox(c, m, m.length, nonce, key);
  return c.subarray(crypto_secretbox_BOXZEROBYTES);
};

This function requires that m must be zero-filled.

If I add console.log after creating m to see what's there:

nacl.secretbox = function(msg, nonce, key) {
  checkArrayTypes(msg, nonce, key);
  checkLengths(key, nonce);
  var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); // <-- BUG HERE
  console.log(m); // <--- ADDED
  var c = new Uint8Array(m.length);
  for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i];
  crypto_secretbox(c, m, m.length, nonce, key);
  return c.subarray(crypto_secretbox_BOXZEROBYTES);
};

and run the test again, I see that m contains some garbage data (results differ from time to time):

Uint8Array {
  '0': 0,
  '1': 0,
  '2': 0,
  '3': 0,
  '4': 0,
  '5': 0,
  '6': 0,
  '7': 0,
  '8': 0,
  '9': 0,
  '10': 0,
  '11': 0,
  '12': 0,
  '13': 0,
  '14': 0,
  '15': 0,
  '16': 232,
  '17': 0,
  '18': 0,
  '19': 0,
  '20': 0,
  '21': 0,
  '22': 0,
  '23': 0,
  '24': 64,
  '25': 231,
  '26': 96,
  '27': 1,
  '28': 1,
  '29': 0,
  '30': 0,
  '31': 0,
  '32': 0 }

This only happens for this particular 33-byte Uint8Array in this particular setting (e.g. I couldn't reproduce this outside of this test). I can work around this by manually zeroing the array after creating it.

Any ideas? As I said, io.js v3.3.1 and previous Node versions doesn't have this bug.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

bufferIssues and PRs related to the buffer subsystem.confirmed-bugIssues with confirmed bugs.v8 engineIssues and PRs related to the V8 dependency.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions