Skip to content
This repository

std::bad_alloc exception if a too big buffer is allocated #1710

Closed
exi opened this Issue September 15, 2011 · 4 comments

3 participants

Reno Reckling Ben Noordhuis tshinnic
Reno Reckling

if i allocate a buffer that is bigger than the RAM left, i get:
%node (master,134)
> var b = new Buffer(999999999);
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
[2] 13425 abort node

this happens in the current master (commit cb6b9eb)

tshinnic

Tested on 0.5.8 pre master dcd911e:

> [ os.type(), os.platform(), os.arch(), os.release(), os.totalmem(), os.freemem() ]
[ 'Linux',
  'linux',
  'ia32',
  '2.6.40.4-5.fc15.i686.PAE',
  1051783168,
  143138816 ]
> [ process.versions, process.platform, process.arch ]
[ { node: '0.5.8-pre',
    v8: '3.6.4',
    ares: '1.7.4',
    uv: '0.1',
    openssl: '1.0.0e-fips' },
  'linux',
  'ia32' ]

Four different behaviors:

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(999999999)
> 

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(1250000000)
FATAL ERROR: v8::Object::SetIndexedPropertiesToExternalArrayData() length exceeds max acceptable value

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(1500000000)
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

> [Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(2999999999)
TypeError: Bad argument
    at new Buffer (buffer.js:235:21)
    at repl:1:9
    at REPLServer.eval (repl.js:80:28)
    at repl.js:178:16
    at REPLServer.eval (repl.js:84:5)
    at Interface.<anonymous> (repl.js:170:12)
    at Interface.emit (events.js:67:17)
    at Interface._onLine (readline.js:162:10)
    at Interface._line (readline.js:425:8)
    at Interface._ttyWrite (readline.js:602:14)

Three different memory sizes for changes in behavior

1073741824 == 0x40000000

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(1073741823)
>

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(1073741824)
FATAL ERROR: v8::Object::SetIndexedPropertiesToExternalArrayData() length exceeds max acceptable value

1500025000 == 0x596890A8
(Note that this address moved on me while testing, so probably is dependent on a system value like free memory)

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(1500025000)
FATAL ERROR: v8::Object::SetIndexedPropertiesToExternalArrayData() length exceeds max acceptable value

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(1500025050)
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

2147483647 == 0x7FFFFFFF

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(2147483647)      == 7FFFFFFF
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

[Tom@TLSF15A node-1]$ ./node
> var b = new Buffer(2147483648)
TypeError: Bad argument
    at new Buffer (buffer.js:235:21)
    at repl:1:9
    at REPLServer.eval (repl.js:80:28)
    at repl.js:178:16
    at REPLServer.eval (repl.js:84:5)
    at Interface.<anonymous> (repl.js:170:12)
    at Interface.emit (events.js:67:17)
    at Interface._onLine (readline.js:162:10)
    at Interface._line (readline.js:425:8)
    at Interface._ttyWrite (readline.js:602:14)

Testing which of all these errors might be caught:

[Tom@TLSF15A node-1]$ ./node
> function swh(howMany) {
...   try {
...     var b = new Buffer(howMany);
...   } catch(ex) {
...     console.log('  eek! ', ex);
...   }
... }
> swh(1250000000)
FATAL ERROR: v8::Object::SetIndexedPropertiesToExternalArrayData() length exceeds max acceptable value

> swh(1500030000)
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

> swh(2999999999)
  eek!  [TypeError: Bad argument]
>
tshinnic

Internally external arrays are checked against the limit in deps/v8/src/objects.h

    ExternalArray::kMaxLength = 0x3fffffff;

or 1073741823 which is the first magic number in testing above.

buffer.js and maybe node_buffer.cc should check for sizes below this, e.g.

    if (this.length > Buffer.poolSize) {
      // Big buffer, just alloc one.
      this.parent = new SlowBuffer(this.length);

should have an additional check for 'goodness'.

Unfortunately the v8 limit is only known from v8/src/objects.h in v8/src/v8.h which is not the same beast as v8/include/v8.h. Is it okay to just use the magic constant by copying rather than importing/including?

tshinnic tshinnic referenced this issue from a commit in tshinnic/node-1 September 18, 2011
tshinnic Fix for issue #1710 : aborts from new Buffer(too_large)
"std::bad_alloc exception if a too big buffer is allocated"

Add check against for upper limit size for ExternalArray within v8.
edd1fd3
tshinnic

Submitted pull request #1735

Ben Noordhuis

Addressed in 8c02f9b.

Ben Noordhuis bnoordhuis closed this July 28, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.