From f09330e7baf42cb8f7fda2c8fec5fd9be11991df Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 23 Sep 2024 10:41:40 +0100 Subject: [PATCH] First argument of operators is now dereferenced before parsing second argument (fix #2547) --- ChangeLog | 1 + src/jsparse.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index df7e86068..617b27e74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,7 @@ Remove Ctrl-A/D/E/U/W code handling to free up flash space (the IDE/or VT100 terminals all use escape codes) Ensure that 1%0.0===NaN (fix #2556) Ensure Number("1A")==NaN, previously we just parsed the digits we could (fix #2555) + First argument of operators is now dereferenced before parsing second argument (fix #2547) 2v24 : Bangle.js2: Add 'Bangle.touchRd()', 'Bangle.touchWr()' Bangle.js2: After Bangle.showTestScreen, put Bangle.js into a hard off state (not soft off) diff --git a/src/jsparse.c b/src/jsparse.c index 1111a4e74..69e222f5f 100644 --- a/src/jsparse.c +++ b/src/jsparse.c @@ -2036,12 +2036,11 @@ NO_INLINE JsVar *__jspeBinaryExpression(JsVar *a, unsigned int lastPrecedence) { while (precedence && precedence>lastPrecedence) { int op = lex->tk; JSP_ASSERT_MATCH(op); - + JsVar *av = jsvSkipNameAndUnLock(a); // if we have short-circuit ops, then if we know the outcome // we don't bother to execute the other op. Even if not // we need to tell mathsOp it's an & or | if (op==LEX_ANDAND || op==LEX_OROR) { - JsVar *av = jsvSkipNameAndUnLock(a); bool aValue = jsvGetBool(av); if ((!aValue && op==LEX_ANDAND) || (aValue && op==LEX_OROR)) { @@ -2057,13 +2056,12 @@ NO_INLINE JsVar *__jspeBinaryExpression(JsVar *a, unsigned int lastPrecedence) { a = __jspeBinaryExpression(jspeUnaryExpression(),precedence); } } else if (op==LEX_NULLISH){ - JsVar* value = jsvSkipNameAndUnLock(a); - if (jsvIsNullish(value)) { + if (jsvIsNullish(av)) { // use second argument (B) - if (!jsvIsUndefined(value)) jsvUnLock(value); + if (!jsvIsUndefined(av)) jsvUnLock(av); a = __jspeBinaryExpression(jspeUnaryExpression(),precedence); } else { - a = value; + a = av; // use first argument (A) JSP_SAVE_EXECUTE(); jspSetNoExecute(); @@ -2073,13 +2071,13 @@ NO_INLINE JsVar *__jspeBinaryExpression(JsVar *a, unsigned int lastPrecedence) { JsVar *b = __jspeBinaryExpression(jspeUnaryExpression(),precedence); if (JSP_SHOULD_EXECUTE) { if (op==LEX_R_IN) { - JsVar *av = jsvSkipName(a); // needle + // av = needle JsVar *bv = jsvSkipName(b); // haystack if (jsvHasChildren(bv)) { // search keys, NOT values av = jsvAsArrayIndexAndUnLock(av); JsVar *varFound = jspGetVarNamedField( bv, av, true); - jsvUnLock2(a,varFound); a = jsvNewFromBool(varFound!=0); + jsvUnLock(varFound); } else { // else maybe it's a fake object... const JswSymList *syms = jswGetSymbolListForObjectProto(bv); if (syms) { @@ -2088,7 +2086,7 @@ NO_INLINE JsVar *__jspeBinaryExpression(JsVar *a, unsigned int lastPrecedence) { if (jsvGetString(av, nameBuf, sizeof(nameBuf)) < sizeof(nameBuf)) varFound = jswBinarySearch(syms, bv, nameBuf); bool found = varFound!=0; - jsvUnLock2(a, varFound); + jsvUnLock(varFound); if (!found && jsvIsArrayBuffer(bv)) { JsVarFloat f = jsvGetFloat(av); // if not a number this will be NaN, f==floor(f) fails if (f==floor(f) && f>=0 && f