-
Notifications
You must be signed in to change notification settings - Fork 273
Feature/new instrumentation runtime exceptions #912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/new instrumentation runtime exceptions #912
Conversation
229ddc4
to
e262241
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good - seems to be missing at least a couple of test cases (I think ideally there would also be test cases for when --java-throw-runttime-execptions
isn't enabled as it isn't clear what the expected behaviour is then.
const exprt &class2, | ||
const source_locationt &original_loc) | ||
{ | ||
// TODO: use std::move |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid having to fix this in 4 places - could a helper function get_exception(const irep_idt &exception_type)
handle this logic?
} | ||
else | ||
{ | ||
const typecast_exprt lhs(op[0], pointer_typet(empty_typet())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a suggested change - but I don't really understand what the code looks like if throw_runtime_exceptions
is disabled - perhaps some documentation (or maybe extract this also into a method so you can document in the name?)
check.add_source_location() | ||
.set_property_class("array-create-negative-size"); | ||
checkandcreate.move_to_operands(check); | ||
c=code_blockt(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One letter variable names aren't advised by the coding standard - perhaps something that explains what this code block does? array_index_read_block
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree. However, the c
here is declared much earlier in the function (https://github.com/cristina-david/cbmc/blob/feature/new-instrumentation-runtime-exceptions/src/java_bytecode/java_bytecode_convert_method.cpp#L1454) and used to set the converted instruction. So, I would like to avoid changing it everywhere in this PR.
--java-throw-runtime-exceptions | ||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^VERIFICATION SUCCESSFUL$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if the test could test more than this - I don't know if this is possible on CBMC, but something that actually validates that CBMC has figured out a run time exception should be thrown
const exprt &length, | ||
const source_locationt &original_sloc); | ||
|
||
codet throw_null_dereference_exception( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a test that validates this, unless this test does: NullPointerException1
but this is currently KNOWNBUG
and doesn't enable the --throw-runtime-exceptions`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added NullPointerException2
.
const exprt &expr, | ||
const source_locationt &original_sloc); | ||
|
||
codet throw_class_cast_exception( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also missing a test as far as I can tell.
@@ -61,6 +61,7 @@ class optionst; | |||
"(round-to-nearest)(round-to-plus-inf)(round-to-minus-inf)(round-to-zero)" \ | |||
"(graphml-witness):" \ | |||
"(java-max-vla-length):(java-unwind-enum-static)" \ | |||
"(java-throw-runtime-exceptions)" \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing help documentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some correctness questions
{ | ||
exc_symbol.is_static_lifetime=true; | ||
exc_symbol.base_name="ArrayIndexOutOfBoundsException"; | ||
exc_symbol.name="ArrayIndexOutOfBoundsException"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surely this should have prefix java::java.lang.
const binary_relation_exprt lt_zero(idx, ID_lt, zero); | ||
const member_exprt length_field(array_struct, "length", java_int_type()); | ||
const binary_relation_exprt ge_length(idx, ID_ge, length_field); | ||
const and_exprt and_expr(lt_zero, ge_length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be or_exprt
I think? I believe this is testing for idx < 0 && idx >= arr.length
const source_locationt &original_loc) | ||
{ | ||
symbolt exc_symbol; | ||
if(!symbol_table.has_symbol("NegativeArraySizeException")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar qualifying of the name to above
|
||
code_ifthenelset if_code; | ||
if_code.add_source_location()=original_loc; | ||
if_code.cond()=ge_zero; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to above, this seems to throw if length >= 0?
|
||
code_ifthenelset if_code; | ||
if_code.add_source_location()=original_loc; | ||
if_code.cond()=and_expr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think op != null && op instanceof Target
-> op != null && !op instanceof Target
0df5a69
to
75bdc66
Compare
9bcf8a4
to
d6a4f3a
Compare
d6a4f3a
to
18714d5
Compare
@thk123 I added more regression tests, including some that do not set the |
ed4e2c3
to
20f8791
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just one possible change:
Since the old-style logic now largely duplicates the code in the functions that creates exceptions, could we factor that in? For example, could we rename throw_exception
-> check_condition (bool use_exception, exprt cond)
, where check_condition
either asserts !cond
or generates if(cond) throw ...
depending on the use_exception
parameter?
@cristina-david can this be merged? Already approved by @smowton and @thk123 |
This is now part of #1019 together with more refactoring so I'll close it here. |
This PR introduces the flag --java-throw-runtime-exceptions such that, whenever used, instead of adding runtime exceptions instrumentation in the form of assertions, we actually throw the corresponding exceptions.
The only problem here is that some of the instrumentation for NullPointerException is added in goto_check.cpp, whereas the rest of the instrumentation is added earlier in java_bytecode_convert_method.cpp. In my opinion, we should do all the instrumentation before goto_check.cpp for two reasons: 1. the exceptions to be thrown are language specific; 2. we presumably don't want to instrument all the dereferences given that many are introduced by us, e.g. when accessing array->length, and they shouldn't throw an exception. Therefore, I've added all the exception throwing instrumentation, including that for null dereference, in java_bytecode_convert_method.cpp. For now, I didn't touch the instrumentation in goto_check.cpp, but I think it should be disabled whenever the --java-throw-runtime-exceptions flag is on. Otherwise, we introduce redundant instrumentation.