JBMC report FAILURE on uncaught exception - #2043
Conversation
tautschnig
left a comment
There was a problem hiding this comment.
- I'm not a Java expert, but I think this warrants more work as indicated in my comments.
- As GitHub doesn't allow me to comment on the changes in the last commit ("Recompile regression test class files"): why are these being recompiled?
| -- | ||
| ^warning: ignoring | ||
| -- | ||
| ordinal() not loaded by --lazy-methods |
There was a problem hiding this comment.
Should there be an issue for this, or maybe is there one already in some project?
| -- | ||
| ^warning: ignoring | ||
| -- | ||
| ordinal() not loaded by --lazy-methods |
There was a problem hiding this comment.
Should there be an issue?
| ^EXIT=10$ | ||
| ^SIGNAL=0$ | ||
| ^VERIFICATION FAILED$ | ||
| -- |
There was a problem hiding this comment.
Any chance to note which change/PR/commit has made this work?
|
|
||
| init_code.move_to_operands(output); | ||
|
|
||
| // check that there is no uncaught exception |
There was a problem hiding this comment.
Shouldn't this be done in goto_checkt (in future, the same might be of interest for other languages), and is enforcing without giving any command-line control to the user a good idea?
abfef25 to
c0a0a4d
Compare
5a62435 to
afcd657
Compare
570f2a2 to
d2fd7da
Compare
|
@tautschnig, I've refined the behaviour now:
|
|
TG bump is passing. |
tautschnig
left a comment
There was a problem hiding this comment.
No serious objections from my side (I'm not a Java person anyway), just procedural comments. In addition to the below: "Recompile regression test class files" - why?
| -- | ||
| ^warning: ignoring | ||
| -- | ||
| ordinal() not loaded by --lazy-methods |
There was a problem hiding this comment.
Maybe this is tracked elsewhere, otherwise might be worth opening an issue.
| -- | ||
| ^warning: ignoring | ||
| -- | ||
| ordinal() not loaded by --lazy-methods |
There was a problem hiding this comment.
As for the other one: might warrant an issue.
| ^EXIT=10$ | ||
| ^SIGNAL=0$ | ||
| ^VERIFICATION FAILED$ | ||
| -- |
There was a problem hiding this comment.
Since this is a regression test: when was this an issue, could the commit message maybe say something to that effect?
There was a problem hiding this comment.
Would require a bisect between now and January.
thk123
left a comment
There was a problem hiding this comment.
Probably check at least one of the tests you modified produces the same output with the --no-uncaught-exception-check.
Add test for propagate-assertion-error
| /// Instruments the start function with an assertion that checks whether | ||
| /// an exception has escaped the entry point | ||
| /// \param symbol_table: global symbol table | ||
| void java_bytecode_instrument_uncaught_exceptions(symbol_tablet &symbol_table) |
There was a problem hiding this comment.
Is mutating the entry point a good plan? Might be better for the entry point construction to have a collection of checks that it appends after the return. Can't spot a concrete problem (so feel free to ignore) but I think strongly couples this code with the entry point generation (if the entry point code changes to wrap the whole thing in an if statement for whatever reason, the assert will be in the wrong place).
There was a problem hiding this comment.
In my opinion, the entire property instrumentation should be moved into a goto-pass.
There was a problem hiding this comment.
Be that as it may - is that likely to happen in the near future, and if not would decoupling be useful in the meantime?
There was a problem hiding this comment.
I've added some invariants to check that the entry point looks sane.
| object_factory_parameters, | ||
| get_pointer_type_selector()); | ||
| get_pointer_type_selector())) | ||
| return true; |
There was a problem hiding this comment.
If statement is multiple lines so wrap the body in braces
| "(java-no-load-class):" | ||
|
|
||
| #define JAVA_BYTECODE_LANGUAGE_OPTIONS_HELP /*NOLINT*/ \ | ||
| " --no-uncaught-exception-check ignore uncaught exceptions and errors\n" \ |
There was a problem hiding this comment.
You might consider documenting this feature (and this flag to turn it off) more thoroughly in a markdown file somewhere (jbmc/doc/cl-options.md?)
There was a problem hiding this comment.
This would be useful. I've created a ticket for it (TG-3893).
There was a problem hiding this comment.
Sorry should have pointed this out in first review, but given that the error message is "no uncaught exception", this flag reads a bit like it turns on the "no uncaught exception check", suggest calling this flag: --disable-uncaught-exception-check?
|
|
||
| #define JAVA_BYTECODE_LANGUAGE_OPTIONS_HELP /*NOLINT*/ \ | ||
| " --no-uncaught-exception-check ignore uncaught exceptions and errors\n" \ | ||
| " --propagate-assertion-error propagate java.lang.AssertionError\n" \ |
There was a problem hiding this comment.
Also this as I don't know what this means (propagate to who?)
| // and this may reduce the instrumentation considerably if the programmer | ||
| // used assertions) | ||
| if(assertion_error) | ||
| // we allow AssertionError not to be propgated since |
caf3fdb to
49207dd
Compare
bb6f859 to
68cde16
Compare
|
@smowton, I've implemented your suggestion to clean up the user-defined assertion generation for Java right away. This looks much cleaner now and removes some references to |
smowton
left a comment
There was a problem hiding this comment.
The new way of dealing with throw new AssertionError is much better :D Couple of minor improvements, and I still really dislike hacking __CPROVER__start rather than simply asking java_entry_point to build it correctly the first time.
| code_function_callt assert_call; | ||
| assert_call.function() = | ||
| symbol_exprt(CPROVER_PREFIX "assert", assert_type); | ||
| assert_call.lhs().make_nil(); |
There was a problem hiding this comment.
You can simply use code_assertt and code_assumet instead of going via functions
| c=code_expressiont(throw_expr); | ||
| results[0]=op[0]; | ||
| code_blockt ret_block; | ||
| ret_block.operands().push_back(std::move(assert_call)); |
There was a problem hiding this comment.
Unsure which we prefer of std::move vs. move_to_operands these days, but check
left a comment
There was a problem hiding this comment.
Passed Diffblue compatibility checks (cbmc commit: 68cde16).
8007fb4 to
a80778d
Compare
The java files were changed in previous commits, but the class files were not recompiled, which caused confusing mismatches in line numbers.
a80778d to
0b9334d
Compare
| assert_no_exception.assertion() = equal_exprt( | ||
| exc_symbol.symbol_expr(), | ||
| null_pointer_exprt(to_pointer_type(exc_symbol.type))); | ||
| source_locationt assert_location = source_location; |
There was a problem hiding this comment.
Is there actual value in this temporary?
There was a problem hiding this comment.
It's shorter than assert_no_exception.add_source_location().set_comment("no uncaught exception");
|
|
||
| // generate the test harness in __CPROVER__start and a call the entry point | ||
| return | ||
| if( |
There was a problem hiding this comment.
Why is this return replaced by an if? Unless I'm missing something this code is if(x) return true; return false; - which should be the same as return x;
There was a problem hiding this comment.
That was a leftover from the previous variant where the instrumentation was added from here. Cleaned up.
| // ASSUME false: | ||
| code_assertt assert_code; | ||
| assert_code.assertion() = false_exprt(); | ||
| source_locationt assert_location = location; // copy |
There was a problem hiding this comment.
Because we use location as the basis for a modified source location.
There was a problem hiding this comment.
Nit: either explain that in the comment, or delete the comment (saying copy afterwards just invites the question)
|
|
||
| code_assumet assume_code; | ||
| assume_code.assumption() = false_exprt(); | ||
| source_locationt assume_location = location; // copy |
| notequal_exprt not_eq_null( | ||
| pointer, | ||
| null_pointer_exprt(to_pointer_type(pointer.type()))); | ||
| notequal_exprt not_eq_null( |
left a comment
There was a problem hiding this comment.
Passed Diffblue compatibility checks (cbmc commit: 0b9334d).
That's the default behaviour because an escaping exception makes the JVM abort. The user can override this behaviour using the --disable-uncaught-exception-check option.
Assertions in Java are "throw a;" statements where a is of type java.lang.AssertionError (an exception, or Throwable, to be precise). Sometimes we want to translate it into an ASSERT instruction in the goto program. Special-casing in order to handle that was scattered across multiple classes. In this commit we special-case it only once in the Java frontend and translate it into assert(false); assume(false); which is then correctly handled by later stages of the translation.
The argument of throw might be null even if it is of type java.lang.AssertionError.
Introduces --throw-assertion-error which allows to propgate AssertionError as performed in the JVM rather than using a goto ASSERT statement.
0b9334d to
cd2ef4b
Compare
left a comment
There was a problem hiding this comment.
Passed Diffblue compatibility checks (cbmc commit: cd2ef4b).
some more regression tests and other minor fixes