Skip to content
This repository
Browse code

Buffer: adjust buffer size so the base64-decoded input fits snugly.

Stops Valgrind from complaining about uninitialized memory access.
  • Loading branch information...
commit 95638c9b0d3a1133f944d9fcd65ae812dc914974 1 parent b5b83b2
Ben Noordhuis bnoordhuis authored ry committed
2  src/node.cc
@@ -783,6 +783,8 @@ enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
783 783 return UTF8;
784 784 } else if (strcasecmp(*encoding, "ascii") == 0) {
785 785 return ASCII;
  786 + } else if (strcasecmp(*encoding, "base64") == 0) {
  787 + return BASE64;
786 788 } else if (strcasecmp(*encoding, "binary") == 0) {
787 789 return BINARY;
788 790 } else if (strcasecmp(*encoding, "raw") == 0) {
2  src/node.h
@@ -41,7 +41,7 @@ do { \
41 41 __callback##_TEM); \
42 42 } while (0)
43 43
44   -enum encoding {ASCII, UTF8, BINARY};
  44 +enum encoding {ASCII, UTF8, BASE64, BINARY};
45 45 enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v,
46 46 enum encoding _default = BINARY);
47 47 void FatalException(v8::TryCatch &try_catch);
28 src/node_buffer.cc
@@ -149,6 +149,29 @@ Handle<Value> Buffer::New(const Arguments &args) {
149 149 Local<String> s = args[0]->ToString();
150 150 enum encoding e = ParseEncoding(args[1], UTF8);
151 151 int length = e == UTF8 ? s->Utf8Length() : s->Length();
  152 +
  153 + // input gets base64-decoded, adjust buffer size
  154 + if (e == BASE64 && length > 0) {
  155 + const int remainder = length % 4;
  156 +
  157 + length = (length / 4) * 3;
  158 + if (remainder) {
  159 + if (length == 0 && remainder == 1) {
  160 + // special case: 1-byte input cannot be decoded, return empty buffer
  161 + length = 0;
  162 + } else {
  163 + // non-padded input, add 1 or 2 extra bytes
  164 + length += 1 + (remainder == 3);
  165 + }
  166 + } else {
  167 + // check for trailing padding (1 or 2 bytes)
  168 + const String::AsciiValue data(s);
  169 + const char *const end = *data + data.length();
  170 + if (end[-1] == '=') length--;
  171 + if (end[-2] == '=') length--;
  172 + }
  173 + }
  174 +
152 175 buffer = new Buffer(length);
153 176 } else if (Buffer::HasInstance(args[0]) && args.Length() > 2) {
154 177 // var slice = new Buffer(buffer, 123, 130);
@@ -516,6 +539,11 @@ Handle<Value> Buffer::Base64Write(const Arguments &args) {
516 539 String::AsciiValue s(args[0]->ToString());
517 540 size_t offset = args[1]->Int32Value();
518 541
  542 + // handle zero-length buffers graciously
  543 + if (offset == 0 && buffer->length_ == 0) {
  544 + return scope.Close(Integer::New(0));
  545 + }
  546 +
519 547 if (offset >= buffer->length_) {
520 548 return ThrowException(Exception::TypeError(String::New(
521 549 "Offset is out of bounds")));
42 test/simple/test-buffer.js
@@ -258,5 +258,43 @@ bytesWritten = b.write(expected, 0, 'base64');
258 258 assert.equal(quote, b.toString('ascii', 0, quote.length));
259 259 assert.equal(quote.length+1, bytesWritten); // writes a \0 too
260 260
261   -
262   -
  261 +assert.equal(new Buffer('', 'base64').toString(), '');
  262 +assert.equal(new Buffer('K', 'base64').toString(), '');
  263 +
  264 +// multiple-of-4 with padding
  265 +assert.equal(new Buffer('Kg==', 'base64').toString(), '*');
  266 +assert.equal(new Buffer('Kio=', 'base64').toString(), '**');
  267 +assert.equal(new Buffer('Kioq', 'base64').toString(), '***');
  268 +assert.equal(new Buffer('KioqKg==', 'base64').toString(), '****');
  269 +assert.equal(new Buffer('KioqKio=', 'base64').toString(), '*****');
  270 +assert.equal(new Buffer('KioqKioq', 'base64').toString(), '******');
  271 +assert.equal(new Buffer('KioqKioqKg==', 'base64').toString(), '*******');
  272 +assert.equal(new Buffer('KioqKioqKio=', 'base64').toString(), '********');
  273 +assert.equal(new Buffer('KioqKioqKioq', 'base64').toString(), '*********');
  274 +assert.equal(new Buffer('KioqKioqKioqKg==', 'base64').toString(), '**********');
  275 +assert.equal(new Buffer('KioqKioqKioqKio=', 'base64').toString(), '***********');
  276 +assert.equal(new Buffer('KioqKioqKioqKioq', 'base64').toString(), '************');
  277 +assert.equal(new Buffer('KioqKioqKioqKioqKg==', 'base64').toString(), '*************');
  278 +assert.equal(new Buffer('KioqKioqKioqKioqKio=', 'base64').toString(), '**************');
  279 +assert.equal(new Buffer('KioqKioqKioqKioqKioq', 'base64').toString(), '***************');
  280 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKg==', 'base64').toString(), '****************');
  281 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKio=', 'base64').toString(), '*****************');
  282 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKioq', 'base64').toString(), '******************');
  283 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKioqKg==', 'base64').toString(), '*******************');
  284 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKioqKio=', 'base64').toString(), '********************');
  285 +
  286 +// no padding, not a multiple of 4
  287 +assert.equal(new Buffer('Kg', 'base64').toString(), '*');
  288 +assert.equal(new Buffer('Kio', 'base64').toString(), '**');
  289 +assert.equal(new Buffer('KioqKg', 'base64').toString(), '****');
  290 +assert.equal(new Buffer('KioqKio', 'base64').toString(), '*****');
  291 +assert.equal(new Buffer('KioqKioqKg', 'base64').toString(), '*******');
  292 +assert.equal(new Buffer('KioqKioqKio', 'base64').toString(), '********');
  293 +assert.equal(new Buffer('KioqKioqKioqKg', 'base64').toString(), '**********');
  294 +assert.equal(new Buffer('KioqKioqKioqKio', 'base64').toString(), '***********');
  295 +assert.equal(new Buffer('KioqKioqKioqKioqKg', 'base64').toString(), '*************');
  296 +assert.equal(new Buffer('KioqKioqKioqKioqKio', 'base64').toString(), '**************');
  297 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKg', 'base64').toString(), '****************');
  298 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKio', 'base64').toString(), '*****************');
  299 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKioqKg', 'base64').toString(), '*******************');
  300 +assert.equal(new Buffer('KioqKioqKioqKioqKioqKioqKio', 'base64').toString(), '********************');

3 comments on commit 95638c9

Peteris Krumins

Base64 is broken currently for binary data. Please add binary tests, not just ascii.

Ben Noordhuis

@pkrumins: If we are talking about the same thing then this problem should be fixed. Could you post an example test if it hasn't?

Please sign in to comment.
Something went wrong with that request. Please try again.