Bug 352742: Array.filter on object {valueOf: Function} halts JavaScript execution, patch by Brian Crowder <crowder@fiverocks.com>, r=mrbkap

This commit is contained in:
gavin%gavinsharp.com 2006-10-06 12:47:30 +00:00
Родитель 04d0bd03d8
Коммит d1c0eb9bcb
2 изменённых файлов: 113 добавлений и 115 удалений

Просмотреть файл

@ -4529,10 +4529,10 @@ js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
}
if (!ok)
JS_ClearPendingException(cx);
ok = JSVAL_IS_PRIMITIVE(fval) ||
js_InternalCall(cx, obj, fval, argc, argv, rval);
JS_SetErrorReporter(cx, older);
return ok;
return JSVAL_IS_PRIMITIVE(fval) ||
js_InternalCall(cx, obj, fval, argc, argv, rval);
}
#if JS_HAS_XDR

Просмотреть файл

@ -569,127 +569,125 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags,
}
JS_ASSERT(!ts || ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT);
onError = cx->errorReporter;
if (onError) {
/*
* We are typically called with non-null ts and null cg from jsparse.c.
* We can be called with null ts from the regexp compilation functions.
* The code generator (jsemit.c) may pass null ts and non-null cg.
*/
do {
if (ts) {
report->filename = ts->filename;
if (pn) {
report->lineno = pn->pn_pos.begin.lineno;
if (report->lineno != ts->lineno)
break;
}
report->lineno = ts->lineno;
linestr = js_NewStringCopyN(cx, ts->linebuf.base,
PTRDIFF(ts->linebuf.limit,
ts->linebuf.base,
jschar),
0);
report->linebuf = linestr
? JS_GetStringBytes(linestr)
: NULL;
tp = &ts->tokens[(ts->cursor+ts->lookahead) & NTOKENS_MASK].pos;
if (pn)
tp = &pn->pn_pos;
/*
* FIXME: What should instead happen here is that we should
* find error-tokens in userbuf, if !ts->file. That will
* allow us to deliver a more helpful error message, which
* includes all or part of the bad string or bad token. The
* code here yields something that looks truncated.
* See https://bugzilla.mozilla.org/show_bug.cgi?id=352970
*/
index = 0;
if (tp->begin.lineno == tp->end.lineno) {
if (tp->begin.index < ts->linepos)
break;
index = tp->begin.index - ts->linepos;
}
report->tokenptr = linestr ? report->linebuf + index : NULL;
report->uclinebuf = linestr ? JS_GetStringChars(linestr) : NULL;
report->uctokenptr = linestr ? report->uclinebuf + index : NULL;
break;
}
if (cg) {
report->filename = cg->filename;
report->lineno = CG_CURRENT_LINE(cg);
break;
}
/*
* If we can't find out where the error was based on the current
* frame, see if the next frame has a script/pc combo we can use.
*/
for (fp = cx->fp; fp; fp = fp->down) {
if (fp->script && fp->pc) {
report->filename = fp->script->filename;
report->lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
/*
* We are typically called with non-null ts and null cg from jsparse.c.
* We can be called with null ts from the regexp compilation functions.
* The code generator (jsemit.c) may pass null ts and non-null cg.
*/
do {
if (ts) {
report->filename = ts->filename;
if (pn) {
report->lineno = pn->pn_pos.begin.lineno;
if (report->lineno != ts->lineno)
break;
}
}
} while (0);
/*
* If there's a runtime exception type associated with this error
* number, set that as the pending exception. For errors occuring at
* compile time, this is very likely to be a JSEXN_SYNTAXERR.
*
* If an exception is thrown but not caught, the JSREPORT_EXCEPTION
* flag will be set in report.flags. Proper behavior for an error
* reporter is to ignore a report with this flag for all but top-level
* compilation errors. The exception will remain pending, and so long
* as the non-top-level "load", "eval", or "compile" native function
* returns false, the top-level reporter will eventually receive the
* uncaught exception report.
*
* XXX it'd probably be best if there was only one call to this
* function, but there seem to be two error reporter call points.
*/
/*
* Try to raise an exception only if there isn't one already set --
* otherwise the exception will describe the last compile-time error,
* which is likely spurious.
*/
if (!ts || !(ts->flags & TSF_ERROR)) {
if (js_ErrorToException(cx, message, report))
onError = NULL;
}
/*
* Suppress any compile-time errors that don't occur at the top level.
* This may still fail, as interplevel may be zero in contexts where we
* don't really want to call the error reporter, as when js is called
* by other code which could catch the error.
*/
if (cx->interpLevel != 0 && !JSREPORT_IS_WARNING(flags))
onError = NULL;
if (onError) {
JSDebugErrorHook hook = cx->runtime->debugErrorHook;
report->lineno = ts->lineno;
linestr = js_NewStringCopyN(cx, ts->linebuf.base,
PTRDIFF(ts->linebuf.limit,
ts->linebuf.base,
jschar),
0);
report->linebuf = linestr
? JS_GetStringBytes(linestr)
: NULL;
tp = &ts->tokens[(ts->cursor+ts->lookahead) & NTOKENS_MASK].pos;
if (pn)
tp = &pn->pn_pos;
/*
* If debugErrorHook is present then we give it a chance to veto
* sending the error on to the regular error reporter.
* FIXME: What should instead happen here is that we should
* find error-tokens in userbuf, if !ts->file. That will
* allow us to deliver a more helpful error message, which
* includes all or part of the bad string or bad token. The
* code here yields something that looks truncated.
* See https://bugzilla.mozilla.org/show_bug.cgi?id=352970
*/
if (hook && !hook(cx, message, report,
cx->runtime->debugErrorHookData)) {
onError = NULL;
index = 0;
if (tp->begin.lineno == tp->end.lineno) {
if (tp->begin.index < ts->linepos)
break;
index = tp->begin.index - ts->linepos;
}
report->tokenptr = linestr ? report->linebuf + index : NULL;
report->uclinebuf = linestr ? JS_GetStringChars(linestr) : NULL;
report->uctokenptr = linestr ? report->uclinebuf + index : NULL;
break;
}
if (cg) {
report->filename = cg->filename;
report->lineno = CG_CURRENT_LINE(cg);
break;
}
/*
* If we can't find out where the error was based on the current
* frame, see if the next frame has a script/pc combo we can use.
*/
for (fp = cx->fp; fp; fp = fp->down) {
if (fp->script && fp->pc) {
report->filename = fp->script->filename;
report->lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
break;
}
}
if (onError)
(*onError)(cx, message, report);
} while (0);
/*
* If there's a runtime exception type associated with this error
* number, set that as the pending exception. For errors occuring at
* compile time, this is very likely to be a JSEXN_SYNTAXERR.
*
* If an exception is thrown but not caught, the JSREPORT_EXCEPTION
* flag will be set in report.flags. Proper behavior for an error
* reporter is to ignore a report with this flag for all but top-level
* compilation errors. The exception will remain pending, and so long
* as the non-top-level "load", "eval", or "compile" native function
* returns false, the top-level reporter will eventually receive the
* uncaught exception report.
*
* XXX it'd probably be best if there was only one call to this
* function, but there seem to be two error reporter call points.
*/
onError = cx->errorReporter;
/*
* Try to raise an exception only if there isn't one already set --
* otherwise the exception will describe the last compile-time error,
* which is likely spurious.
*/
if (!ts || !(ts->flags & TSF_ERROR)) {
if (js_ErrorToException(cx, message, report))
onError = NULL;
}
/*
* Suppress any compile-time errors that don't occur at the top level.
* This may still fail, as interplevel may be zero in contexts where we
* don't really want to call the error reporter, as when js is called
* by other code which could catch the error.
*/
if (cx->interpLevel != 0 && !JSREPORT_IS_WARNING(flags))
onError = NULL;
if (onError) {
JSDebugErrorHook hook = cx->runtime->debugErrorHook;
/*
* If debugErrorHook is present then we give it a chance to veto
* sending the error on to the regular error reporter.
*/
if (hook && !hook(cx, message, report,
cx->runtime->debugErrorHookData)) {
onError = NULL;
}
}
if (onError)
(*onError)(cx, message, report);
if (message)
JS_free(cx, message);
if (report->ucmessage)