Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 99e752a

Browse files
committed
Bug 863505 - Disallow unbound name ops in self-hosted code. (r=till)
1 parent 13282d5 commit 99e752a

2 files changed

Lines changed: 25 additions & 5 deletions

File tree

js/src/frontend/BytecodeEmitter.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,12 +1158,12 @@ TryConvertToGname(BytecodeEmitter *bce, ParseNode *pn, JSOp *op)
11581158
}
11591159

11601160
/*
1161-
* BindNameToSlot attempts to optimize name gets and sets to stack slot loads
1162-
* and stores, given the compile-time information in bce and a PNK_NAME node pn.
1163-
* It returns false on error, true on success.
1161+
* BindNameToSlotHelper attempts to optimize name gets and sets to stack slot
1162+
* loads and stores, given the compile-time information in bce and a PNK_NAME
1163+
* node pn. It returns false on error, true on success.
11641164
*
11651165
* The caller can test pn->pn_cookie.isFree() to tell whether optimization
1166-
* occurred, in which case BindNameToSlot also updated pn->pn_op. If
1166+
* occurred, in which case BindNameToSlotHelper also updated pn->pn_op. If
11671167
* pn->pn_cookie.isFree() is still true on return, pn->pn_op still may have
11681168
* been optimized, e.g., from JSOP_NAME to JSOP_CALLEE. Whether or not
11691169
* pn->pn_op was modified, if this function finds an argument or local variable
@@ -1175,7 +1175,7 @@ TryConvertToGname(BytecodeEmitter *bce, ParseNode *pn, JSOp *op)
11751175
* op=, e.g. +=).
11761176
*/
11771177
static bool
1178-
BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
1178+
BindNameToSlotHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
11791179
{
11801180
JS_ASSERT(pn->isKind(PNK_NAME));
11811181

@@ -1411,6 +1411,25 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
14111411
return true;
14121412
}
14131413

1414+
/*
1415+
* Attempts to bind the name, then checks that no dynamic scope lookup ops are
1416+
* emitted in self-hosting mode. NAME ops do lookups off current scope chain,
1417+
* and we do not want to allow self-hosted code to use the dynamic scope.
1418+
*/
1419+
static bool
1420+
BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
1421+
{
1422+
if (!BindNameToSlotHelper(cx, bce, pn))
1423+
return false;
1424+
1425+
if (bce->selfHostingMode && !pn->isBound()) {
1426+
bce->reportError(pn, JSMSG_SELFHOSTED_UNBOUND_NAME);
1427+
return false;
1428+
}
1429+
1430+
return true;
1431+
}
1432+
14141433
/*
14151434
* If pn contains a useful expression, return true with *answer set to true.
14161435
* If pn contains a useless expression, return true with *answer set to false.

js/src/js.msg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,4 @@ MSG_DEF(JSMSG_BAD_ARROW_ARGS, 345, 0, JSEXN_SYNTAXERR, "invalid arrow-fu
399399
MSG_DEF(JSMSG_YIELD_IN_ARROW, 346, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield")
400400
MSG_DEF(JSMSG_WRONG_VALUE, 347, 2, JSEXN_ERR, "expected {0} but found {1}")
401401
MSG_DEF(JSMSG_PAR_ARRAY_SCATTER_BAD_TARGET, 348, 1, JSEXN_ERR, "target for index {0} is not an integer")
402+
MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME,349, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups")

0 commit comments

Comments
 (0)