Skip to content

Always allocate an exception object at throw site #1193

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added regression/cbmc-java/exceptions21/test.class
Binary file not shown.
11 changes: 11 additions & 0 deletions regression/cbmc-java/exceptions21/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CORE
test.class
--function test.f --java-throw-runtime-exceptions
^EXIT=0$
^SIGNAL=0$
VERIFICATION SUCCESSFUL
--
reference is null in .*: FAILURE
--
This checks that the second use of a particular exception type in a given function is correctly initialised.
In the failing case the #exception_value variable is nondet at the time it is thrown, so cbmc can set it to null and fail an assertion.
24 changes: 24 additions & 0 deletions regression/cbmc-java/exceptions21/test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
public class test {

int field;

public static void f() {

test testinstance = new test();
test testnull = null;
int x = 0;
try {
x = testinstance.field;
}
catch(NullPointerException e) {
x++;
}
try {
x = testnull.field;
}
catch(NullPointerException e) {
x++;
}
}

}
57 changes: 28 additions & 29 deletions src/java_bytecode/java_bytecode_instrument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Date: June 2017
\*******************************************************************/

#include <util/arith_tools.h>
#include <util/fresh_symbol.h>
#include <util/std_code.h>
#include <util/std_expr.h>
#include <util/symbol_table.h>
Expand All @@ -18,7 +19,6 @@ Date: June 2017
#include "java_bytecode_convert_class.h"
#include "java_bytecode_instrument.h"
#include "java_entry_point.h"
#include "java_object_factory.h"
#include "java_root_class.h"
#include "java_types.h"
#include "java_utils.h"
Expand Down Expand Up @@ -90,47 +90,46 @@ codet java_bytecode_instrumentt::throw_exception(
const source_locationt &original_loc,
const irep_idt &exc_name)
{
exprt exc;
code_blockt init_code;
const irep_idt &exc_obj_name=
id2string(goto_functionst::entry_point())+
"::"+id2string(exc_name);
irep_idt exc_class_name("java::"+id2string(exc_name));

if(!symbol_table.has_symbol(exc_obj_name))
if(!symbol_table.has_symbol(exc_class_name))
{
generate_class_stub(
exc_name,
symbol_table,
get_message_handler());
const symbolt &exc_symbol=symbol_table.lookup(
"java::"+id2string(exc_name));

// create the exception object
exc=object_factory(
pointer_typet(exc_symbol.type),
exc_name,
init_code,
false,
symbol_table,
max_array_length,
allocation_typet::LOCAL,
original_loc);
}
else
exc=symbol_table.lookup(exc_obj_name).symbol_expr();

pointer_typet exc_ptr_type;
exc_ptr_type.subtype()=symbol_typet(exc_class_name);

// Allocate and throw an instance of the exception class:

symbolt &new_symbol=
get_fresh_aux_symbol(
exc_ptr_type,
"new_exception",
"new_exception",
original_loc,
ID_java,
symbol_table);

side_effect_exprt new_instance(ID_java_new, exc_ptr_type);
code_assignt assign_new(new_symbol.symbol_expr(), new_instance);

side_effect_expr_throwt throw_expr;
throw_expr.add_source_location()=original_loc;
throw_expr.move_to_operands(exc);
throw_expr.copy_to_operands(new_symbol.symbol_expr());

code_blockt throw_code;
throw_code.move_to_operands(assign_new);
throw_code.copy_to_operands(code_expressiont(throw_expr));
Copy link
Contributor

Choose a reason for hiding this comment

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

Just for my own culture: Why can't we not use move_to_operands here?

Copy link
Contributor Author

@smowton smowton Aug 2, 2017

Choose a reason for hiding this comment

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

Move-to-operands takes a mutable ref (an exprt&), which cannot be taken to an rvalue like this.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK thanks!


code_ifthenelset if_code;
if_code.add_source_location()=original_loc;
if_code.cond()=cond;
if_code.then_case()=code_expressiont(throw_expr);

init_code.move_to_operands(if_code);
if_code.then_case()=throw_code;

return init_code;
return if_code;
}

/// Checks whether the array access array_struct[idx] is out-of-bounds,
Expand Down Expand Up @@ -209,7 +208,7 @@ codet java_bytecode_instrumentt::check_class_cast(
throw_exception(
not_exprt(class_cast_check),
original_loc,
"ClassCastException");
"java.lang.ClassCastException");
}
else
{
Expand Down