Fix crash when out of memory while creating built-in object

Fix continue statement in nested loops (fix #501)
This commit is contained in:
Gordon Williams 2015-03-04 15:15:30 +00:00
parent eb88b79599
commit f07c163fc7
5 changed files with 62 additions and 20 deletions

View File

@ -1,4 +1,6 @@
1v75 : Fixed issue with Pins/Bools as Array indices
Fix crash when out of memory while creating built-in object
Fix continue statement in nested loops (fix #501)
1v74 : On Espruino Board, allow setTime to use full 64 bits so setTime(Date.parse("...")/1000) works
Fixed issues with Waveform after 1v72 update to flat strings

View File

@ -1088,7 +1088,7 @@ NO_INLINE void jspEnsureIsPrototype(JsVar *instanceOf, JsVar *prototypeName) {
jsvUnLock(lastName);
}
JsVar *constructor = jsvFindChildFromString(prototypeVar, JSPARSE_CONSTRUCTOR_VAR, true);
jsvSetValueOfName(constructor, instanceOf);
if (constructor) jsvSetValueOfName(constructor, instanceOf);
jsvUnLock(constructor);
jsvUnLock(prototypeVar);
@ -1686,9 +1686,9 @@ NO_INLINE JsVar *jspeStatementDoOrWhile(bool isWhile) {
jsvUnLock(jspeBlockOrStatement());
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (execInfo.execute == EXEC_CONTINUE)
if (execInfo.execute & EXEC_CONTINUE)
execInfo.execute = EXEC_YES;
if (execInfo.execute == EXEC_BREAK) {
else if (execInfo.execute & EXEC_BREAK) {
execInfo.execute = EXEC_YES;
hasHadBreak = true; // fail loop condition, so we exit
}
@ -1721,9 +1721,9 @@ NO_INLINE JsVar *jspeStatementDoOrWhile(bool isWhile) {
execInfo.execute |= EXEC_IN_LOOP;
jsvUnLock(jspeBlockOrStatement());
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (execInfo.execute == EXEC_CONTINUE)
if (execInfo.execute & EXEC_CONTINUE)
execInfo.execute = EXEC_YES;
if (execInfo.execute == EXEC_BREAK) {
else if (execInfo.execute & EXEC_BREAK) {
execInfo.execute = EXEC_YES;
hasHadBreak = true;
}
@ -1744,6 +1744,7 @@ NO_INLINE JsVar *jspeStatementDoOrWhile(bool isWhile) {
NO_INLINE JsVar *jspeStatementFor() {
JSP_ASSERT_MATCH(LEX_R_FOR);
JSP_MATCH('(');
bool wasInLoop = execInfo.execute&EXEC_IN_LOOP;
execInfo.execute |= EXEC_FOR_INIT;
// initialisation
JsVar *forStatement = 0;
@ -1778,7 +1779,7 @@ NO_INLINE JsVar *jspeStatementFor() {
execInfo.execute |= EXEC_IN_LOOP;
jsvUnLock(jspeBlockOrStatement());
JslCharPos forBodyEnd = jslCharPosClone(&execInfo.lex->tokenStart);
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (!wasInLoop) execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
JSP_RESTORE_EXECUTE();
if (JSP_SHOULD_EXECUTE) {
@ -1812,11 +1813,11 @@ NO_INLINE JsVar *jspeStatementFor() {
jslSeekToP(execInfo.lex, &forBodyStart);
execInfo.execute |= EXEC_IN_LOOP;
jsvUnLock(jspeBlockOrStatement());
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (!wasInLoop) execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (execInfo.execute == EXEC_CONTINUE)
if (execInfo.execute & EXEC_CONTINUE)
execInfo.execute = EXEC_YES;
if (execInfo.execute == EXEC_BREAK) {
else if (execInfo.execute & EXEC_BREAK) {
execInfo.execute = EXEC_YES;
hasHadBreak = true;
}
@ -1878,12 +1879,14 @@ NO_INLINE JsVar *jspeStatementFor() {
execInfo.execute |= EXEC_IN_LOOP;
jsvUnLock(jspeBlockOrStatement());
JslCharPos forBodyEnd = jslCharPosClone(&execInfo.lex->tokenStart);
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (execInfo.execute == EXEC_CONTINUE)
execInfo.execute = EXEC_YES;
if (execInfo.execute == EXEC_BREAK) {
execInfo.execute = EXEC_YES;
hasHadBreak = true;
if (!wasInLoop) execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (loopCond || !JSP_SHOULD_EXECUTE) {
if (execInfo.execute & EXEC_CONTINUE)
execInfo.execute = EXEC_YES;
else if (execInfo.execute & EXEC_BREAK) {
execInfo.execute = EXEC_YES;
hasHadBreak = true;
}
}
if (!loopCond) JSP_RESTORE_EXECUTE();
if (loopCond) {
@ -1908,10 +1911,10 @@ NO_INLINE JsVar *jspeStatementFor() {
jslSeekToP(execInfo.lex, &forBodyStart);
execInfo.execute |= EXEC_IN_LOOP;
jsvUnLock(jspeBlockOrStatement());
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (execInfo.execute == EXEC_CONTINUE)
if (!wasInLoop) execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
if (execInfo.execute & EXEC_CONTINUE)
execInfo.execute = EXEC_YES;
if (execInfo.execute == EXEC_BREAK) {
else if (execInfo.execute & EXEC_BREAK) {
execInfo.execute = EXEC_YES;
hasHadBreak = true;
}
@ -2112,7 +2115,7 @@ NO_INLINE JsVar *jspeStatement() {
if (!(execInfo.execute & EXEC_IN_LOOP))
jsExceptionHere(JSET_SYNTAXERROR, "CONTINUE statement outside of FOR or WHILE loop");
else
execInfo.execute = (execInfo.execute & (JsExecFlags)~EXEC_RUN_MASK) | EXEC_CONTINUE;
execInfo.execute = (execInfo.execute & (JsExecFlags)~EXEC_RUN_MASK) | EXEC_CONTINUE;
}
} else if (execInfo.lex->tk==LEX_R_BREAK) {
JSP_ASSERT_MATCH(LEX_R_BREAK);

View File

@ -105,7 +105,7 @@ typedef enum {
EXEC_RUN_MASK = EXEC_YES|EXEC_BREAK|EXEC_CONTINUE|EXEC_INTERRUPTED|EXEC_EXCEPTION,
EXEC_ERROR_MASK = EXEC_INTERRUPTED|EXEC_ERROR|EXEC_EXCEPTION, // here, we have an error, but unless EXEC_NO_PARSE, we should continue parsing but not executing
EXEC_NO_PARSE_MASK = EXEC_INTERRUPTED|EXEC_ERROR, // in these cases we should exit as fast as possible - skipping out of parsing
EXEC_SAVE_RESTORE_MASK = EXEC_YES|EXEC_IN_LOOP|EXEC_IN_SWITCH | EXEC_ERROR_MASK, // the things JSP_SAVE/RESTORE_EXECUTE should keep track of
EXEC_SAVE_RESTORE_MASK = EXEC_YES|EXEC_IN_LOOP|EXEC_IN_SWITCH|EXEC_CONTINUE|EXEC_BREAK | EXEC_ERROR_MASK, // the things JSP_SAVE/RESTORE_EXECUTE should keep track of
EXEC_CTRL_C_MASK = EXEC_CTRL_C | EXEC_CTRL_C_WAIT, // Ctrl-C was pressed at some point
} JsExecFlags;

20
tests/test_continue_1.js Normal file
View File

@ -0,0 +1,20 @@
// https://github.com/espruino/Espruino/issues/501
// nested continue;
var r = 0;
for (var i=0; i < 10; ++i) {
for (var j=0; j < 10; ++j);
if(i==0) continue;
r++;
}
for (var i=0; i < 10; ++i) {
for (var j=0; j < 10; ++j);
if(i==1) continue;
r++;
}
result = r==18;

17
tests/test_continue_2.js Normal file
View File

@ -0,0 +1,17 @@
// https://github.com/espruino/Espruino/issues/501
var r=0;
for (var i=0; i < 10; ++i) {
if(i==0) continue;
for (var j=0; j < 0; ++j);
r++;
}
for (var i=0; i < 10; ++i) {
if(i==1) continue;
for (var j=0; j < 0; ++j);
r++;
}
result = r==18;