Bug 649939: Prevent crash from too much recursion in Iterator.prototype.next() (r=jwalden)

This commit is contained in:
Paul Biggar 2011-06-16 17:00:31 -07:00
parent de6d0e2330
commit 9fbd2b1e02
4 changed files with 33 additions and 2 deletions

View File

@ -0,0 +1,27 @@
// This was the actual bug
assertRaises(StopIteration, function() {
Iterator.prototype.next();
Iterator.prototype.next();
});
// The error should have triggered here, but was masked by a latent bug
assertRaises(StopIteration, function() {
Iterator.prototype.next();
});
// Found by fuzzing
assertRaises(StopIteration, function() {
(new Iterator({})).__proto__.next();
});
function assertRaises(exc, callback) {
var caught = false;
try {
callback();
} catch (e) {
assertEq(e instanceof InternalError, true);
caught = true;
}
assertEq(caught, true);
}

View File

@ -318,6 +318,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
#if JS_STACK_GROWTH_DIRECTION > 0
cx->stackLimit = (jsuword) -1;
#endif
cx->iterValue.setMagic(JS_NO_ITER_VALUE);
JS_STATIC_ASSERT(JSVERSION_DEFAULT == 0);
JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT);
VOUCH_DOES_NOT_REQUIRE_STACK();

View File

@ -2076,7 +2076,7 @@ static inline bool
IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
{
if (iterobj->getClass() == &js_IteratorClass) {
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
NativeIterator *ni = iterobj->getNativeIterator();
if (ni->isKeyIter()) {
*cond = (ni->props_cursor < ni->props_end);
return true;
@ -2092,7 +2092,7 @@ static inline bool
IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
{
if (iterobj->getClass() == &js_IteratorClass) {
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
NativeIterator *ni = iterobj->getNativeIterator();
if (ni->isKeyIter()) {
JS_ASSERT(ni->props_cursor < ni->props_end);
jsid id = *ni->current();

View File

@ -942,6 +942,9 @@ js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval)
return true;
}
/* We're reentering below and can call anything. */
JS_CHECK_RECURSION(cx, return false);
/* Fetch and cache the next value from the iterator. */
if (!ni) {
jsid id = ATOM_TO_JSID(cx->runtime->atomState.nextAtom);