Closed Bug 514112 Opened 15 years ago Closed 15 years ago

MAX_DSLOTS_LENGTH is *net*, and avoid *size variable names for net lengths or capacities

Categories

(Core :: JavaScript Engine, defect, P2)

defect

Tracking

()

RESOLVED FIXED
Tracking Status
status1.9.2 --- beta1-fixed
blocking1.9.1 --- -
status1.9.1 --- wanted

People

(Reporter: karlt, Assigned: gal)

References

Details

(Whiteboard: fixed-in-tracemonkey [sg:critical?])

Attachments

(2 files)

With gcc -Wtype-limits:

/home/karl/moz/dev/js/src/jsarray.cpp: In function 'JSBool ResizeSlots(JSContext*, JSObject*, uint32, uint32)':
/home/karl/moz/dev/js/src/jsarray.cpp:327: warning: comparison is always false due to limited range of data type

If size == ~(uint32)0, size + 1 will overflow, and if realloc(ptr, 0) chooses
to return non-NULL, the overflow will not be detected.
I don't actually understand the comment for MAX_DSLOTS_LENGTH.  For ILP32, the
value looks like the maximum allocatable size *including* the hidden slot.  I
read bug 489899 comment 13, but that didn't make it seem right.
(At least ResizeSlots() seems to test against the right value for ILP32 systems,
though.)

http://hg.mozilla.org/mozilla-central/annotate/c07eb0b8b0f1/js/src/jsobj.h#l246

For LP64 systems, MAX_DSLOTS_LENGTH looks like a maximum possible total length
that could be passed to realloc, but ResizeSlots() will never pass a length
anything close to this.
Yikes, who reviewed gal's patch? :-P

/*
 * Maximum net gross capacity of the obj->dslots vector, excluding the additional
 * hidden slot used to store the length of the vector.
 */
#define MAX_DSLOTS_LENGTH   (JS_MAX(~(uint32)0, ~(size_t)0) / sizeof(jsval))

"net gross" is an oxymoron. I'm a moron for r+'ing, though.

Karl, thanks for reporting this.

/be
Assignee: general → brendan
Status: NEW → ASSIGNED
OS: Linux → All
Hardware: x86 → All
Attachment #398081 - Attachment is patch: true
Attachment #398081 - Attachment mime type: application/octet-stream → text/plain
Comment on attachment 398081 [details] [diff] [review]
MAX_DSLOTS_LENGTH is *net*, and avoid *size variable names for net lengths or capacities

2nd time is the charm.
Attachment #398081 - Flags: review?(gal) → review+
http://hg.mozilla.org/tracemonkey/rev/ec19fb045976

I'm usually a nut about "length" or "count" vs. (byte) "size", and net vs. gross. I shall redouble my efforts...

/be
Whiteboard: fixed-in-tracemonkey
Comment on attachment 398081 [details] [diff] [review]
MAX_DSLOTS_LENGTH is *net*, and avoid *size variable names for net lengths or capacities

This makes things much easier to understand and deals with most of the issues in comment 1, thanks, but doesn't address comment 0.

Consider either

js_NewUninitializedArray(,, len = 0xFFFFFFFF):
  ResizeSlots(,,, newcap = 0xFFFFFFFF);

or

EnsureCapacity(,, newcap = 0xFFFFFFFF):
  newcap = JS_ROUNDUP(0, CAPACITY_CHUNK) - 1;
  ResizeSlots(,,, newcap = 0xFFFFFFFF);

on LP64 systems such that MAX_DSLOTS_LENGTH = ~(uint64)0 / sizeof(jsval) - 1;
and so 0xFFFFFFFF < MAX_DSLOTS_LENGTH.

ResizeSlots(,,, newcap = 0xFFFFFFFF):
  newslots = cx->realloc(slots, bytes = 0);

http://hg.mozilla.org/mozilla-central/annotate/c07eb0b8b0f1/js/src/jsutil.h#l195

js_realloc(slots, bytes = 0)
  bytes = sizeof(void*);
  return realloc(slots, 8);

=> newslots has 8 bytes set aside for 0xFFFFFFFF slots.
How about this?
Attachment #398107 - Flags: review?(brendan)
Argh, I ignored all the stinking uint32 parameters. Could we not fix this other than by your patch using JS_MIN and uint32(-1), if we just used size_t instead of uint32 for the relevant newlen, etc., params?

/be
Yes.  uint32 -> size_t makes sense to me.
One thing to consider though is whether a minimal patch will be necessary for 1.9.1.
And another is that uint32(-1) * sizeof is already 32GB of memory so allowing for more elements may be early planning for the future.
... sizeof(jsval) ...
Whiteboard: fixed-in-tracemonkey → fixed-in-tracemonkey [sg:critical?]
I am sucking at this -- back to 64-bit school for me. Andreas, can I tag out of the ring and let you hit this with a folding chair? I was your review wrestling partner on the regressing patch, but my bad-review guilt has run out :-P.

/be
Assignee: brendan → gal
http://hg.mozilla.org/mozilla-central/rev/ec19fb045976
Status: ASSIGNED → RESOLVED
Closed: 15 years ago
Resolution: --- → FIXED
Filed bug 517644 on this.
Summary: [LP64] possible overflow in ResizeSlots() → MAX_DSLOTS_LENGTH is *net*, and avoid *size variable names for net lengths or capacities
blocking1.9.1: --- → ?
Flags: wanted1.9.0.x-
Flags: blocking1.9.2?
Depends on: 517644
Flags: blocking1.9.2? → blocking1.9.2+
Priority: -- → P2
So, do we have a patch yet that is 1.9.1 branch worthy?
blocking1.9.1: ? → .5+
Comment on attachment 398107 [details] [diff] [review]
accurate MAX_DSLOTS_LENGTH when uint32(-1) < size_t(-1)

The overflow was fixed in a different way in bug 517644.  MAX_DSLOTS_LENGTH is not used on LP64 systems except in compile-time tests to see whether it is greater than MAX_DSLOTS_LENGTH32.
Attachment #398107 - Flags: review?(brendan)
Does the patch that landed apply to 1.9.1? If so, can you please request approval. If not, please attach one that does. Code freeze is scheduled for November 10 at 11:59pm PDT.
I don't actually understand what this fixes.

The overflow reported in comment 0 was fixed in bug 517644.
... fixed on trunk, i mean.
blocking1.9.1: .6+ → .7+
64 bit Linux isn't a supported platform for Gecko 1.9.1. Drivers would accept a nominated patch (looks like it would be easy) if someone can figure out which of these applies to that branch.
blocking1.9.1: .8+ → -
Group: core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: