Allocating large ArrayBuffer fails in unexpected ways

NEW
Unassigned

Status

()

Core
JavaScript Engine
5 years ago
3 years ago

People

(Reporter: Jeroen van der Gun, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(2 attachments, 2 obsolete attachments)

(Reporter)

Description

5 years ago
Created attachment 768593 [details]
Test suite allocating ArrayBuffers of various sizes

User Agent: Mozilla/5.0 (Windows NT 5.1; rv:22.0) Gecko/20100101 Firefox/22.0 (Beta/Release)
Build ID: 20130617145905

Steps to reproduce:

Constructing ArrayBuffers in JavaScript lead to strange failures in case large buffers are being requested.


Actual results:

One of the following failure modes may occur:
* The script requesting the buffer is silently aborted (<2^31 bytes).
* A RangeError is thrown (=2^31 bytes).
* An ArrayBuffer with byteLength == 0 is returned (>2^31 bytes).


Expected results:

As per spec, in all failure cases an exception should be thrown:
https://www.khronos.org/registry/typedarray/specs/latest/#5
(Reporter)

Updated

5 years ago
Attachment #768593 - Attachment mime type: text/plain → text/html
(Reporter)

Comment 1

5 years ago
Created attachment 768595 [details]
Test results for my computer
(Reporter)

Comment 2

5 years ago
Created attachment 768596 [details]
Test results for my computer
Attachment #768595 - Attachment is obsolete: true

Updated

5 years ago
Assignee: nobody → general
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
> As per spec, in all failure cases an exception should be thrown:

Per that spec, the argument is first converted to a 32-bit unsigned integer by taking it mod 2^32.  So for 2^n with n > 31, you get a length of 0 per that spec.

That said, it looks like we're converting to a _signed_ 32-bit int (using the ES ToInteger operation), which explains the behavior for 2^31.  There's a comment in the code about how that's technically wrong...

For smaller sizes, I can't reproduce a problem offhand, though it's possible that on a 32-bit system we can end up with out-of-address-space issues that manifest as an uncatchable "out of memory" abort (because catching out of memory is usually nonsense: you're out of memory).

Note also that the spec for this stuff is in the process of being rewritten as part of ES itself, so the final spec behavior for large sizes is a bit up in the air.
(In reply to Boris Zbarsky (:bz) (reading mail, but on paternity leave) from comment #3)
> That said, it looks like we're converting to a _signed_ 32-bit int (using
> the ES ToInteger operation), which explains the behavior for 2^31.  There's
> a comment in the code about how that's technically wrong...

I haven't (yet) looked into what that means for your analysis, but note that ToInteger returns a signed integral of Number, not a 32-bit int.
Created attachment 769364 [details]
shell version of the test
Comment on attachment 769364 [details]
shell version of the test

Yeah, so I now see how the shell version is entirely bogus, at least when it comes to tests 28-30. Sorry about that.
Attachment #769364 - Attachment is obsolete: true
I can reproduce the issue in 32-bit mode, latest OS X Nightly, too. Not on 64-bit, though, so it looks like bz's theory from comment 3 is right.
Status: UNCONFIRMED → NEW
Ever confirmed: true
OS: Windows XP → All
Version: 22 Branch → unspecified
(Reporter)

Comment 8

5 years ago
(In reply to Boris Zbarsky (:bz) (reading mail, but on paternity leave) from comment #3)
> Per that spec, the argument is first converted to a 32-bit unsigned integer
> by taking it mod 2^32.  So for 2^n with n > 31, you get a length of 0 per
> that spec.
Fair enough.

> For smaller sizes, I can't reproduce a problem offhand, though it's possible
> that on a 32-bit system we can end up with out-of-address-space issues that
> manifest as an uncatchable "out of memory" abort (because catching out of
> memory is usually nonsense: you're out of memory).
I'd say that making this error catchable would be quite useful. For example, asm.js applications with a too large heap size could try a smaller heap size or display an error message that there is not enough memory available, as opposed to showing a non-functioning application UI without any hint why it is not working: after all, the web page is still open. I don't see any disadvantage of throwing a catchable exception.
(Assignee)

Updated

3 years ago
Assignee: general → nobody
You need to log in before you can comment on or make changes to this bug.