Skip to content

JBMC report FAILURE on uncaught exception - #2043

Merged
peterschrammel merged 5 commits into
diffblue:developfrom
peterschrammel:fail-on-uncaught-exception
Jun 14, 2018
Merged

JBMC report FAILURE on uncaught exception#2043
peterschrammel merged 5 commits into
diffblue:developfrom
peterschrammel:fail-on-uncaught-exception

Conversation

@peterschrammel

Copy link
Copy Markdown
Member

some more regression tests and other minor fixes

@tautschnig tautschnig left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I'm not a Java expert, but I think this warrants more work as indicated in my comments.
  2. 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?

Comment thread regression/cbmc-java/enum2/test.desc Outdated
--
^warning: ignoring
--
ordinal() not loaded by --lazy-methods

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be an issue for this, or maybe is there one already in some project?

Comment thread regression/cbmc-java/enum3/test.desc Outdated
--
^warning: ignoring
--
ordinal() not loaded by --lazy-methods

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be an issue?

^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
--

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance to note which change/PR/commit has made this work?

Comment thread src/java_bytecode/java_entry_point.cpp Outdated

init_code.move_to_operands(output);

// check that there is no uncaught exception

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

@peterschrammel
peterschrammel force-pushed the fail-on-uncaught-exception branch 2 times, most recently from abfef25 to c0a0a4d Compare April 28, 2018 20:35
@peterschrammel
peterschrammel force-pushed the fail-on-uncaught-exception branch 2 times, most recently from 5a62435 to afcd657 Compare May 30, 2018 10:56
@peterschrammel
peterschrammel force-pushed the fail-on-uncaught-exception branch 2 times, most recently from 570f2a2 to d2fd7da Compare May 30, 2018 15:17
@peterschrammel

Copy link
Copy Markdown
Member Author

@tautschnig, I've refined the behaviour now:

  • Asserting that there is uncaught exception remains the default behaviour because an escaping exception makes the JVM abort; we should replicate that behaviour and report that as a bug. However, the user can now override this behaviour using the --no-uncaught-exception-check option, which might be useful in combination with --function, when thrown exceptions could be considered as part of the 'normal' behaviour.
  • Moreover, I've introduced --propagate-assertion-error which allows to propagate AssertionError as performed in the JVM rather than using a goto ASSERT statement. This flag is turned off by default following the assumption that usually nobody tries to catch AssertionError, and hence reporting a failing assertion at the location where AssertionError is thrown is typically the desired behaviour; if not the flag can be used.

@peterschrammel

Copy link
Copy Markdown
Member Author

TG bump is passing.

@tautschnig tautschnig left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Comment thread jbmc/regression/jbmc/enum2/test.desc Outdated
--
^warning: ignoring
--
ordinal() not loaded by --lazy-methods

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is tracked elsewhere, otherwise might be worth opening an issue.

Comment thread jbmc/regression/jbmc/enum3/test.desc Outdated
--
^warning: ignoring
--
ordinal() not loaded by --lazy-methods

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for the other one: might warrant an issue.

^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
--

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a regression test: when was this an issue, could the commit message maybe say something to that effect?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would require a bisect between now and January.

@tautschnig tautschnig removed their assignment Jun 1, 2018

@thk123 thk123 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, the entire property instrumentation should be moved into a goto-pass.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be that as it may - is that likely to happen in the near future, and if not would decoupling be useful in the meantime?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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" \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be useful. I've created a ticket for it (TG-3893).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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" \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: propagated

@peterschrammel
peterschrammel force-pushed the fail-on-uncaught-exception branch 2 times, most recently from caf3fdb to 49207dd Compare June 9, 2018 21:50
@peterschrammel
peterschrammel force-pushed the fail-on-uncaught-exception branch 2 times, most recently from bb6f859 to 68cde16 Compare June 13, 2018 14:01
@peterschrammel

Copy link
Copy Markdown
Member Author

@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 java.util.AssertionError from analyses and goto-programs.

@smowton smowton left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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));

ghost Jun 13, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure which we prefer of std::move vs. move_to_operands these days, but check

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passed Diffblue compatibility checks (cbmc commit: 68cde16).

@peterschrammel
peterschrammel force-pushed the fail-on-uncaught-exception branch 2 times, most recently from 8007fb4 to a80778d Compare June 13, 2018 22:56
The java files were changed in previous commits,
but the class files were not recompiled, which
caused confusing mismatches in line numbers.

ghost left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just nit picks. Disclaimer: I have not done a technical review of the Java parts, just code reading.

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;

ghost Jun 14, 2018

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there actual value in this temporary?

ghost Jun 14, 2018

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(

ghost Jun 14, 2018

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;

ghost Jun 14, 2018

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

ghost Jun 14, 2018

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this copy good for?

ghost Jun 14, 2018

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we use location as the basis for a modified source location.

ghost Jun 14, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

ghost Jun 14, 2018

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above: why copy?

ghost Jun 14, 2018

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Comment thread src/analyses/goto_check.cpp Outdated
notequal_exprt not_eq_null(
pointer,
null_pointer_exprt(to_pointer_type(pointer.type())));
notequal_exprt not_eq_null(

ghost Jun 14, 2018

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passed Diffblue compatibility checks (cbmc commit: 0b9334d).

Peter Schrammel added 4 commits June 14, 2018 09:46
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.
@peterschrammel
peterschrammel force-pushed the fail-on-uncaught-exception branch from 0b9334d to cd2ef4b Compare June 14, 2018 08:51

ghost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passed Diffblue compatibility checks (cbmc commit: cd2ef4b).

@peterschrammel
peterschrammel merged commit 8e6244c into diffblue:develop Jun 14, 2018
@peterschrammel
peterschrammel deleted the fail-on-uncaught-exception branch June 14, 2018 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants