Closed Bug 620029 Opened 14 years ago Closed 14 years ago

TM: newArray doesn't catch negative array lengths

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
Tracking Status
blocking2.0 --- beta9+

People

(Reporter: billm, Assigned: billm)

Details

(Whiteboard: fixed-in-tracemonkey)

Attachments

(1 file, 1 obsolete file)

The tracer seems perfectly happy to try to create an array with a negative length. Later on, when we try to do something with the array, it hangs (trying to fill it in?).
Attached patch fix (obsolete) (deleted) — Splinter Review
This just adds a check to ensure the length is non-negative.
Assignee: general → wmccloskey
Status: NEW → ASSIGNED
Attachment #498442 - Flags: review?(nnethercote)
I think this is fallout from bug 620029. Is there a test for this behaviour? I got no failures when I tested before commit? I got this review: <quote> > RecordingStatus > TraceRecorder::newArray(JSObject* ctor, uint32 argc, Value* argv, Value* rval) > { ... >+ } else if (argc == 1 && argv[0].isNumber()) { >+ /* Abort on RangeError if the double doesn't fit in a uint. */ >+ LIns* num_ins; >+ CHECK_STATUS(makeNumberInt32(get(argv), &num_ins)); >+ >+ LIns *args[] = { proto_ins, num_ins, cx_ins }; >+ arr_ins = w.call(&js::NewDenseUnallocatedArray_ci, args); >+ guard(false, w.eqp0(arr_ins), OOM_EXIT); >+ >+ } else { You changed from using d2i to makeNumberInt32, and these don't seem equivalent in this case, particularly in the cases they optimize. If this was unintentional, you can just put it back to: LIns *args[] = { proto_ins, d2i(get(argv)), cx_ins }; </quote> I think the range test was covered in the makeNumberInt32 call that I erroneously removed.
I think the correct fix is to use makeNumberInt32, as that has an optimizing case which won't call the guard. Is that right? billm, this is fallout from my bug, so feel free to assign it to me.
Comment on attachment 498442 [details] [diff] [review] fix d2i() converts a double to an int32, removing any fractional part in the process. makeNumberInt32() converts a double to an int32, but side-exits if the double was not integral (and fits in 32-bits) in the first place. So I think the patch needs to (a) change d2i() to makeNumberInt32() and (b) side-exit if the value is negative. Actually, is the size is interpreted as a uint32? The comment "Abort on RangeError if the double doesn't fit in a uint" implies it is. In which case I think we need a new function makeNumberUint32(). It would call the already-existing d2u(), which is less optimized that d2u() but that shouldn't matter for this case. No negative check would then be needed.
Attachment #498442 - Flags: review?(nnethercote)
Attached patch updated patch (deleted) — Splinter Review
I think this is what you wanted. NewDenseUnallocatedArray does take an unsigned, so I went with the makeNumberUint32 path.
Attachment #498442 - Attachment is obsolete: true
Attachment #499043 - Flags: review?(nnethercote)
Comment on attachment 499043 [details] [diff] [review] updated patch >+ // This means "convert double to int if it's integral, otherwise >+ // exit". We first convert the double to an unsigned int, then Nit: Can you say "convert double to uint"? You should also add a jit-test. r=me with that. Thanks!
Attachment #499043 - Flags: review?(nnethercote) → review+
blocking2.0: --- → ?
blocking2.0: ? → beta9+
blocking2.0: beta9+ → ---
Whiteboard: fixed-in-tracemonkey
blocking2.0: --- → beta9+
Status: ASSIGNED → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: