Browse Source

LibJS: Check for exception after executing (do)while test expression

Otherwise we crash the interpreter when an exception is thrown during
evaluation of the while or do/while test expression - which is easily
caused by a ReferenceError - e.g.:

    while (someUndefinedVariable) {
        // ...
    }
Linus Groh 4 years ago
parent
commit
82ac936a9d

+ 11 - 3
Libraries/LibJS/AST.cpp

@@ -258,9 +258,12 @@ Value IfStatement::execute(Interpreter& interpreter, GlobalObject& global_object
 Value WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
 {
     Value last_value = js_undefined();
-    while (m_test->execute(interpreter, global_object).to_boolean()) {
+    for (;;) {
+        auto test_result = m_test->execute(interpreter, global_object);
         if (interpreter.exception())
             return {};
+        if (!test_result.to_boolean())
+            break;
         last_value = interpreter.execute_statement(global_object, *m_body);
         if (interpreter.exception())
             return {};
@@ -282,7 +285,7 @@ Value WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_obj
 Value DoWhileStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
 {
     Value last_value = js_undefined();
-    do {
+    for (;;) {
         if (interpreter.exception())
             return {};
         last_value = interpreter.execute_statement(global_object, *m_body);
@@ -298,7 +301,12 @@ Value DoWhileStatement::execute(Interpreter& interpreter, GlobalObject& global_o
                 return last_value;
             }
         }
-    } while (m_test->execute(interpreter, global_object).to_boolean());
+        auto test_result = m_test->execute(interpreter, global_object);
+        if (interpreter.exception())
+            return {};
+        if (!test_result.to_boolean())
+            break;
+    }
 
     return last_value;
 }

+ 6 - 0
Libraries/LibJS/Tests/loops/do-while-basic.js

@@ -12,3 +12,9 @@ test("no braces", () => {
     while (number < 3);
     expect(number).toBe(3);
 });
+
+test("exception in test expression", () => {
+    expect(() => {
+        do {} while (foo);
+    }).toThrow(ReferenceError);
+});

+ 6 - 0
Libraries/LibJS/Tests/loops/while-basic.js

@@ -17,3 +17,9 @@ test("does not loop when initially false", () => {
         expect().fail();
     }
 });
+
+test("exception in test expression", () => {
+    expect(() => {
+        while (foo);
+    }).toThrow(ReferenceError);
+});