Closed Bug 441362 Opened 16 years ago Closed 16 years ago

LOCAL_ASSERT causes out: label to be bypassed

Categories

(Core :: JavaScript Engine, defect)

x86
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: taras.mozilla, Unassigned)

References

Details

Attachments

(1 file, 1 obsolete file)

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.
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.
Flags: wanted1.9.1?
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?
No, I'm wrong, it turns into a return; in a release build.
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.
Attached patch Another macro hack to avoid an invisible return (obsolete) (deleted) — Splinter Review
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.
Attached patch avoid invisible return (deleted) — Splinter Review
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 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+
pushed rev c0f37eff7ea6
Status: NEW → RESOLVED
Closed: 16 years ago
Resolution: --- → FIXED
Flags: in-testsuite-
Flags: in-litmus-
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: