Просмотр исходного кода

[executable semantics] silence known, and detect new, crashes (#312)

* Add assertion to detect UB in interpreter.cpp

This change, applied to 6e5070d ("Adapting jsiek's executable semantics tooling
for commit. (#237)"), causes the if2.6c test to segfault.  Becase the assertion
fires only when `stmt == nullptr` and no code has permission to change `stmt`
(it is `const`) before it is dereferenced in the `switch`, and nothiing in
`PrintStatement` is supposed to exit the program, the assertion is a valid
change that detects a bug.

The crash was originally manifest in 29a5994 ("Executable Semantics: 1st-class
stacks (#296)").

* Temporarily disable the if2 test pending #311

See https://github.com/carbon-language/carbon-lang/issues/311

* [executable semantics] Record exit code on expected error.

This will prevent a final segfault from sneaking by, detected as a passing test.
A more principled follow-up commit would bottleneck detected error exit
reporting and have it write something to std::cerr that can be recognized.
Dave Abrahams 5 лет назад
Родитель
Сommit
2afbfd6146

+ 4 - 2
executable_semantics/BUILD

@@ -81,7 +81,9 @@ EXAMPLES = [
     "fun6_fail_type",
     "funptr1",
     "if1",
-    "if2",
+    # (Temporarily disabled pending
+    # https://github.com/carbon-language/carbon-lang/issues/311)
+    # "if2",
     "if3",
     "match_int_default",
     "match_int",
@@ -107,7 +109,7 @@ EXAMPLES = [
     srcs = ["testdata/%s.6c" % e],
     outs = ["testdata/%s.out" % e],
     # Suppress command errors.
-    cmd = "$(location executable_semantics) $< > $@ 2>&1 || true",
+    cmd = "$(location executable_semantics) $< > $@ 2>&1 || echo EXIT CODE: $$? >> $@",
     tools = [":executable_semantics"],
 ) for e in EXAMPLES]
 

+ 3 - 1
executable_semantics/interpreter/interpreter.cpp

@@ -4,6 +4,7 @@
 
 #include "executable_semantics/interpreter/interpreter.h"
 
+#include <cassert>
 #include <iostream>
 #include <iterator>
 #include <map>
@@ -744,7 +745,8 @@ auto IsBlockAct(Action* act) -> bool {
 void StepStmt() {
   Frame* frame = state->stack.Top();
   Action* act = frame->todo.Top();
-  Statement* stmt = act->u.stmt;
+  Statement* const stmt = act->u.stmt;
+  assert(stmt != nullptr && "null statement!");
   std::cout << "--- step stmt ";
   PrintStatement(stmt, 1);
   std::cout << " --->" << std::endl;

+ 1 - 0
executable_semantics/testdata/choice1.golden

@@ -41,3 +41,4 @@ return n;
 13: type error in call
 expected: Int
 actual: Tuple(0 = Int)
+EXIT CODE: 255

+ 1 - 0
executable_semantics/testdata/fun1.golden

@@ -17,3 +17,4 @@ return f(0 = 1);
 10: type error in call
 expected: Int
 actual: Tuple(0 = Int)
+EXIT CODE: 255

+ 1 - 0
executable_semantics/testdata/fun2.golden

@@ -23,3 +23,4 @@ return b;
 15: type error in call
 expected: Int
 actual: Tuple(0 = Int)
+EXIT CODE: 255

+ 1 - 0
executable_semantics/testdata/fun6_fail_type.golden

@@ -25,3 +25,4 @@ return f(0 = xy);
 10: type error in call
 expected: Tuple(0 = Int, 1 = Int)
 actual: Tuple(0 = Tuple(0 = Int, 1 = Int))
+EXIT CODE: 255

+ 1 - 0
executable_semantics/testdata/fun_recur.golden

@@ -19,3 +19,4 @@ return f(0 = 2);
 9: type error in call
 expected: Int
 actual: Tuple(0 = Int)
+EXIT CODE: 255

+ 1 - 0
executable_semantics/testdata/funptr1.golden

@@ -23,3 +23,4 @@ return f(0 = (- 1));
 11: type error in call
 expected: Int
 actual: Tuple(0 = Int)
+EXIT CODE: 255

+ 1 - 0
executable_semantics/testdata/undef1.golden

@@ -1 +1,2 @@
 executable_semantics/testdata/undef1.6c:8: syntax error
+EXIT CODE: 255

+ 1 - 0
executable_semantics/testdata/undef2.golden

@@ -1,3 +1,4 @@
 ********** source program **********
 ********** type checking **********
 error, program must contain a function named `main`
+EXIT CODE: 255