Closed
Bug 441362
Opened 16 years ago
Closed 16 years ago
LOCAL_ASSERT causes out: label to be bypassed
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
RESOLVED
FIXED
People
(Reporter: taras.mozilla, Unassigned)
References
Details
Attachments
(1 file, 1 obsolete file)
(deleted),
patch
|
igor
:
review+
|
Details | Diff | Splinter Review |
js/src/jsopcode.cpp:1624: error:Decompile: Control did not flow through
enterblock_out
cause is that LOCAL_ASSERT for some reason does a return statement.
Comment 1•16 years ago
|
||
I think we need to provide an alternate macro here for LOCAL_ASSERT_RV that jumps to a label. We've used a similar pattern elsewhere.
Updated•16 years ago
|
Flags: wanted1.9.1?
Comment 2•16 years ago
|
||
Crowder points out this is debug-only and should never happen anyway. Might be nice to keep the analysis clean, though.
Flags: wanted1.9.1?
Comment 3•16 years ago
|
||
No, I'm wrong, it turns into a return; in a release build.
Comment 4•16 years ago
|
||
Yeah, sorry if I was unclear. My point is that these should never happen in debug OR in release. In debug, these are crashes. In release, they -should- never happen. They probably do, so we should probably recover correctly, but I don't think the error is a severe one here.
Reporter | ||
Comment 5•16 years ago
|
||
Comment 6•16 years ago
|
||
Comment on attachment 334381 [details] [diff] [review]
Another macro hack to avoid an invisible return
>-#define LOCAL_ASSERT_RV(expr, rv) \
>+#define LOCAL_ASSERT_CUSTOM(expr, BAD_EXIT) \
> JS_BEGIN_MACRO \
> JS_ASSERT(expr); \
>- if (!(expr)) return (rv); \
>+ if (!(expr)) BAD_EXIT; \
^^^^^^
that should be
if (!(expr)) { BAD_EXIT; }
so the following does what it intends:
LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; goto enterblock_out)
IMO from the point of readability using just
LOCAL_ASSERT(condition, return JS_FALSE);
LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; goto enterblock_out);
etc.
without any LOCAL_ASSERT_RV etc. shortcuts would make the purpose of the macro very explicit and exposes for the reader the gotos/returns. But that can be done in another bug.
Reporter | ||
Comment 7•16 years ago
|
||
I agree that it would be helpful to have a policy against returns in macros that don't imply that in the name.
Attachment #334381 -
Attachment is obsolete: true
Attachment #336528 -
Flags: review?(igor)
Comment 8•16 years ago
|
||
Comment on attachment 336528 [details] [diff] [review]
avoid invisible return
>diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp
>--- a/js/src/jsopcode.cpp
>+++ b/js/src/jsopcode.cpp
>@@ -1192,11 +1192,14 @@ DecompileSwitch(SprintStack *ss, TableEn
> return JS_TRUE;
> }
>
>-#define LOCAL_ASSERT_RV(expr, rv) \
>+#define LOCAL_ASSERT_CUSTOM(expr, BAD_EXIT) \
> JS_BEGIN_MACRO \
> JS_ASSERT(expr); \
>- if (!(expr)) return (rv); \
>+ if (!(expr)) { BAD_EXIT; } \
> JS_END_MACRO
>+
>+#define LOCAL_ASSERT_RV(expr, rv) \
>+ LOCAL_ASSERT_CUSTOM(expr, return (rv))
>
> static JSAtom *
> GetArgOrVarAtom(JSPrinter *jp, uintN slot)
>@@ -2544,11 +2547,13 @@ Decompile(SprintStack *ss, jsbytecode *p
>
> /* From here on, control must flow through enterblock_out. */
> MUST_FLOW_THROUGH("enterblock_out");
>+#define LOCAL_ASSERT_OUT(expr) LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; \
>+ goto enterblock_out)
> for (sprop = OBJ_SCOPE(obj)->lastProp; sprop;
> sprop = sprop->parent) {
> if (!(sprop->flags & SPROP_HAS_SHORTID))
> continue;
>- LOCAL_ASSERT(sprop->shortid < argc);
>+ LOCAL_ASSERT_OUT(sprop->shortid < argc);
> atomv[sprop->shortid] = JSID_TO_ATOM(sprop->id);
> }
> ok = JS_TRUE;
>@@ -2584,7 +2589,7 @@ Decompile(SprintStack *ss, jsbytecode *p
>
> pc2 = pc;
> pc += oplen;
>- LOCAL_ASSERT(*pc == JSOP_EXCEPTION);
>+ LOCAL_ASSERT_OUT(*pc == JSOP_EXCEPTION);
> pc += JSOP_EXCEPTION_LENGTH;
> todo = Sprint(&ss->sprinter, exception_cookie);
> if (todo < 0 || !PushOff(ss, todo, JSOP_EXCEPTION)) {
>@@ -2600,7 +2605,7 @@ Decompile(SprintStack *ss, jsbytecode *p
> * It is emitted only when the catch head contains
> * an exception guard.
> */
>- LOCAL_ASSERT(js_GetSrcNoteOffset(sn, 0) != 0);
>+ LOCAL_ASSERT_OUT(js_GetSrcNoteOffset(sn, 0) != 0);
> pc += JSOP_DUP_LENGTH;
> todo = Sprint(&ss->sprinter, exception_cookie);
> if (todo < 0 ||
>@@ -2618,13 +2623,13 @@ Decompile(SprintStack *ss, jsbytecode *p
> ok = JS_FALSE;
> goto enterblock_out;
> }
>- LOCAL_ASSERT(*pc == JSOP_POP);
>+ LOCAL_ASSERT_OUT(*pc == JSOP_POP);
> pc += JSOP_POP_LENGTH;
> lval = PopStr(ss, JSOP_NOP);
> js_puts(jp, lval);
> } else {
> #endif
>- LOCAL_ASSERT(*pc == JSOP_SETLOCALPOP);
>+ LOCAL_ASSERT_OUT(*pc == JSOP_SETLOCALPOP);
> i = GET_SLOTNO(pc) - jp->script->nfixed;
> pc += JSOP_SETLOCALPOP_LENGTH;
> atom = atomv[i - OBJ_BLOCK_DEPTH(cx, obj)];
>@@ -2642,19 +2647,19 @@ Decompile(SprintStack *ss, jsbytecode *p
> * guarded catch head) off the stack now.
> */
> rval = PopStr(ss, JSOP_NOP);
>- LOCAL_ASSERT(strcmp(rval, exception_cookie) == 0);
>+ LOCAL_ASSERT_OUT(strcmp(rval, exception_cookie) == 0);
>
> len = js_GetSrcNoteOffset(sn, 0);
> if (len) {
> len -= PTRDIFF(pc, pc2, jsbytecode);
>- LOCAL_ASSERT(len > 0);
>+ LOCAL_ASSERT_OUT(len > 0);
> js_printf(jp, " if ");
> ok = Decompile(ss, pc, len, JSOP_NOP) != NULL;
> if (!ok)
> goto enterblock_out;
> js_printf(jp, "%s", POP_STR());
> pc += len;
>- LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
>+ LOCAL_ASSERT_OUT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
> pc += js_CodeSpec[*pc].length;
> }
>
>@@ -2668,6 +2673,7 @@ Decompile(SprintStack *ss, jsbytecode *p
>
> todo = -2;
>
>+#undef LOCAL_ASSERT_OUT
> enterblock_out:
> if (atomv != smallv)
> JS_free(cx, atomv);
Attachment #336528 -
Flags: review?(igor) → review+
Reporter | ||
Comment 9•16 years ago
|
||
pushed rev c0f37eff7ea6
Status: NEW → RESOLVED
Closed: 16 years ago
Resolution: --- → FIXED
Updated•16 years ago
|
Flags: in-testsuite-
Flags: in-litmus-
You need to log in
before you can comment on or make changes to this bug.
Description
•