From 15049b78f96f48619b47fdbf75010c3f414d0365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Thu, 3 Nov 2016 17:41:18 +0100 Subject: [PATCH 01/45] restructure expr2java Extract expr2java to a file. --- src/java_bytecode/expr2java.cpp | 74 ++++++++++++++++----------------- src/java_bytecode/expr2java.h | 36 ++++++++++++++++ 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 8cf4cdd1c59..7574c1e4ce9 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -20,40 +20,6 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include "java_types.h" #include "expr2java.h" -class expr2javat:public expr2ct -{ -public: - expr2javat(const namespacet &_ns):expr2ct(_ns) { } - - std::string convert(const exprt &src) override - { - return expr2ct::convert(src); - } - - std::string convert(const typet &src) override - { - return expr2ct::convert(src); - } - -protected: - std::string convert(const exprt &src, unsigned &precedence) override; - std::string convert_java_this(const exprt &src, unsigned precedence); - std::string convert_java_instanceof(const exprt &src, unsigned precedence); - std::string convert_java_new(const exprt &src, unsigned precedence); - std::string convert_code_java_delete(const exprt &src, unsigned precedence); - std::string convert_struct(const exprt &src, unsigned &precedence) override; - std::string convert_code(const codet &src, unsigned indent) override; - std::string convert_constant(const constant_exprt &src, unsigned &precedence) override; - std::string convert_code_function_call(const code_function_callt &src, unsigned indent); - - std::string convert_rec( - const typet &src, - const c_qualifierst &qualifiers, - const std::string &declarator) override; - - typedef std::unordered_set id_sett; -}; - /*******************************************************************\ Function: expr2javat::convert_code_function_call @@ -244,12 +210,12 @@ std::string expr2javat::convert_constant( else if(src.type()==java_char_type()) { std::string dest; - dest.reserve(10); + dest.reserve(char_representation_length); mp_integer int_value; to_integer(src, int_value); - dest+='\''; + dest+="(char)'"; if(int_value>=' ' && int_value<127) dest+=(char)(int_value.to_long()); @@ -265,6 +231,24 @@ std::string expr2javat::convert_constant( dest+='\''; return dest; } + else if(src.type()==java_byte_type()) + { + // No byte-literals in Java, so just cast: + mp_integer int_value; + to_integer(src, int_value); + std::string dest="(byte)"; + dest+=integer2string(int_value); + return dest; + } + else if(src.type()==java_short_type()) + { + // No short-literals in Java, so just cast: + mp_integer int_value; + to_integer(src, int_value); + std::string dest="(short)"; + dest+=integer2string(int_value); + return dest; + } else if(src.type()==java_long_type()) { // long integer literals must have 'L' at the end @@ -319,7 +303,7 @@ std::string expr2javat::convert_rec( else if(src==java_double_type()) return q+"double"+d; else if(src==java_boolean_type()) - return q+"bool"+d; + return q+"boolean"+d; else if(src==java_byte_type()) return q+"byte"+d; else if(src.id()==ID_code) @@ -491,6 +475,7 @@ std::string expr2javat::convert( const exprt &src, unsigned &precedence) { + const typet &type=ns.follow(src.type()); if(src.id()=="java-this") return convert_java_this(src, precedence=15); if(src.id()=="java_instanceof") @@ -509,9 +494,22 @@ std::string expr2javat::convert( else if(src.id()=="pod_constructor") return "pod_constructor"; else if(src.id()==ID_virtual_function) - return convert_function(src, "VIRTUAL_FUNCTION", precedence=16); + { + return "VIRTUAL_FUNCTION(" + + id2string(src.get(ID_C_class)) + + "." + + id2string(src.get(ID_component_name)) + + ")"; + } else if(src.id()==ID_java_string_literal) return '"'+id2string(src.get(ID_value))+'"'; // Todo: add escaping as needed + else if(src.id()==ID_constant && (type.id()==ID_bool || type.id()==ID_c_bool)) + { + if(src.is_true()) + return "true"; + else + return "false"; + } else return expr2ct::convert(src, precedence); } diff --git a/src/java_bytecode/expr2java.h b/src/java_bytecode/expr2java.h index f69563a3697..f4d03084348 100644 --- a/src/java_bytecode/expr2java.h +++ b/src/java_bytecode/expr2java.h @@ -10,11 +10,47 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #define CPROVER_JAVA_BYTECODE_EXPR2JAVA_H #include +#include class exprt; class namespacet; class typet; +class expr2javat:public expr2ct +{ +public: + expr2javat(const namespacet &_ns):expr2ct(_ns) { } + + virtual std::string convert(const exprt &src) + { + return expr2ct::convert(src); + } + + virtual std::string convert(const typet &src) + { + return expr2ct::convert(src); + } + +protected: + virtual std::string convert(const exprt &src, unsigned &precedence); + virtual std::string convert_java_this(const exprt &src, unsigned precedence); + virtual std::string convert_java_instanceof(const exprt &src, unsigned precedence); + virtual std::string convert_java_new(const exprt &src, unsigned precedence); + virtual std::string convert_code_java_delete(const exprt &src, unsigned precedence); + virtual std::string convert_struct(const exprt &src, unsigned &precedence); + virtual std::string convert_code(const codet &src, unsigned indent); + virtual std::string convert_constant(const constant_exprt &src, unsigned &precedence); + virtual std::string convert_code_function_call(const code_function_callt &src, unsigned indent); + + virtual std::string convert_rec( + const typet &src, + const c_qualifierst &qualifiers, + const std::string &declarator); + + // length of string representation of Java Char + const std::size_t char_representation_length=14; +}; + std::string expr2java(const exprt &expr, const namespacet &ns); std::string type2java(const typet &type, const namespacet &ns); From a34def1a0beacd0cb50fe86f5ee76c915c3c41be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 4 Nov 2016 11:12:47 +0100 Subject: [PATCH 02/45] pre-load java.lang.Object / String in class queue java.lang.Object and java.lang.String are added explicitely to the class loading queue to prevent problems with use without having a reference in the class. --- src/java_bytecode/java_class_loader.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/java_bytecode/java_class_loader.cpp b/src/java_bytecode/java_class_loader.cpp index 3d0f8338caf..0eca596149b 100644 --- a/src/java_bytecode/java_class_loader.cpp +++ b/src/java_bytecode/java_class_loader.cpp @@ -35,6 +35,11 @@ java_bytecode_parse_treet &java_class_loadert::operator()( { std::stack queue; + // Always require java.lang.Object, as it is the base of + // internal classes such as array types. + queue.push("java.lang.Object"); + // java.lang.String + queue.push("java.lang.String"); queue.push(class_name); while(!queue.empty()) From 18b259b7e0a0f25df47c97134a2f1fb5a9e30619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Thu, 3 Nov 2016 17:48:09 +0100 Subject: [PATCH 03/45] correct array type for Java Take into account difference between atomic types and refernce types in Java array handling. --- src/java_bytecode/java_types.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/java_bytecode/java_types.cpp b/src/java_bytecode/java_types.cpp index 2e1318df274..37682a99d49 100644 --- a/src/java_bytecode/java_types.cpp +++ b/src/java_bytecode/java_types.cpp @@ -7,6 +7,7 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ #include +#include #include #include @@ -384,9 +385,15 @@ typet java_type_from_string(const std::string &src) case '[': // array type { + // If this is a reference array, we generate a plain array[reference] + // with void* members, but note the real type in ID_C_element_type. if(src.size()<=1) return nil_typet(); + char subtype_letter=src[1]; const typet subtype=java_type_from_string(src.substr(1, std::string::npos)); - typet tmp=java_array_type('a'); + if(subtype_letter=='L' || // [L denotes a reference array of some sort. + subtype_letter=='[') // Array-of-arrays + subtype_letter='A'; + typet tmp=java_array_type((char)tolower(subtype_letter)); tmp.subtype().set(ID_C_element_type, subtype); return tmp; } From 66c760fb1eaf4d08d82906866e2e1d377cec828a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 6 Dec 2016 13:25:25 +0100 Subject: [PATCH 04/45] nondeterministic initialization Treat nondeterministic initialization of objects. --- src/java_bytecode/java_object_factory.cpp | 377 +++++++++++++++++++--- src/java_bytecode/java_object_factory.h | 20 +- 2 files changed, 349 insertions(+), 48 deletions(-) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 6eeba5e23eb..b27797b0416 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -7,14 +7,18 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ #include +#include #include #include #include #include +#include +#include #include #include "java_object_factory.h" +#include "java_types.h" /*******************************************************************\ @@ -28,20 +32,126 @@ Function: gen_nondet_init \*******************************************************************/ -namespace { -void gen_nondet_init( +class gen_nondet_state { + + code_blockt& init_code; + std::set recursion_set; + bool assume_non_null; + int max_nondet_array_length; + symbol_tablet& symbol_table; + namespacet ns; + +public: + + gen_nondet_state(code_blockt& ic, bool ann, int mnal, symbol_tablet& st) : + init_code(ic), + assume_non_null(ann), + max_nondet_array_length(mnal), + symbol_table(st), + ns(st) {} + + exprt allocate_object(const exprt&, const typet&, + const source_locationt &, + bool create_dynamic_objects); + + void gen_nondet_array_init(const exprt &expr, const source_locationt &); + + void gen_nondet_init(const exprt &expr, + bool is_sub, + irep_idt class_identifier, + const source_locationt &loc, + bool skip_classid, + bool create_dynamic_objects, + const typet *override_type = 0); + + +}; + +// Returns false if we can't figure out the size of allocate_type. +// allocate_type may differ from target_expr, e.g. for target_expr having +// type int* and allocate_type being an int[10]. +exprt gen_nondet_state::allocate_object( + const exprt& target_expr, + const typet& allocate_type, + const source_locationt &loc, + bool create_dynamic_objects) +{ + const typet& allocate_type_resolved=ns.follow(allocate_type); + const typet& target_type=ns.follow(target_expr.type().subtype()); + bool cast_needed=allocate_type_resolved!=target_type; + if(!create_dynamic_objects) + { + symbolt &aux_symbol=new_tmp_symbol(symbol_table); + aux_symbol.type=allocate_type; + aux_symbol.is_static_lifetime=true; + + exprt object=aux_symbol.symbol_expr(); + exprt aoe=address_of_exprt(object); + if(cast_needed) + aoe=typecast_exprt(aoe, target_expr.type()); + code_assignt code(target_expr,aoe); + code.add_source_location()=loc; + init_code.copy_to_operands(code); + return aoe; + } + else + { + // build size expression + exprt object_size=size_of_expr(allocate_type, namespacet(symbol_table)); + + if(allocate_type.id()!=ID_empty && !object_size.is_nil()) + { + // malloc expression + exprt malloc_expr = side_effect_exprt(ID_malloc); + malloc_expr.copy_to_operands(object_size); + typet result_type=pointer_typet(allocate_type); + malloc_expr.type()=result_type; + // Create a symbol for the malloc expression so we can initialise + // without having to do it potentially through a double-deref, which + // breaks the to-SSA phase. + symbolt &malloc_sym=new_tmp_symbol(symbol_table,"malloc_site"); + malloc_sym.type=pointer_typet(allocate_type); + code_assignt assign = code_assignt(malloc_sym.symbol_expr(), malloc_expr); + code_assignt &malloc_assign = assign; + malloc_assign.add_source_location() = loc; + init_code.copy_to_operands(malloc_assign); + malloc_expr=malloc_sym.symbol_expr(); + if(cast_needed) + malloc_expr=typecast_exprt(malloc_expr,target_expr.type()); + code_assignt code(target_expr, malloc_expr); + code.add_source_location() = loc; + init_code.copy_to_operands(code); + return malloc_sym.symbol_expr(); + } + else + { + // make null + null_pointer_exprt null_pointer_expr(to_pointer_type(target_expr.type())); + code_assignt code(target_expr, null_pointer_expr); + code.add_source_location() = loc; + init_code.copy_to_operands(code); + return exprt(); + } + } +} + +// Override type says to ignore the LHS' real type, and init it with the given +// type regardless. Used at the moment for reference arrays, which are implemented +// as void* arrays but should be init'd as their true type with appropriate casts. +void gen_nondet_state::gen_nondet_init( const exprt &expr, - code_blockt &init_code, - const namespacet &ns, - std::set &recursion_set, bool is_sub, - irep_idt class_identifier) + irep_idt class_identifier, + const source_locationt &loc, + bool skip_classid, + bool create_dynamic_objects, + const typet *override_type) { - const typet &type=ns.follow(expr.type()); + const typet &type= + override_type ? ns.follow(*override_type) : ns.follow(expr.type()); if(type.id()==ID_pointer) { - #if 0 // dereferenced type const pointer_typet &pointer_type=to_pointer_type(type); const typet &subtype=ns.follow(pointer_type.subtype()); @@ -56,38 +166,72 @@ void gen_nondet_init( // make null null_pointer_exprt null_pointer_expr(pointer_type); code_assignt code(expr, null_pointer_expr); + code.add_source_location() = loc; init_code.copy_to_operands(code); return; } } - // build size expression - exprt object_size=size_of_expr(subtype, ns); - - if(subtype.id()!=ID_empty && !object_size.is_nil()) - { - // malloc expression - side_effect_exprt malloc_expr(ID_malloc); - malloc_expr.copy_to_operands(object_size); - malloc_expr.type()=pointer_type; + code_labelt set_null_label; + code_labelt init_done_label; - code_assignt code(expr, malloc_expr); - init_code.copy_to_operands(code); + static unsigned long synthetic_constructor_count=0; - // dereference expression - dereference_exprt deref_expr(expr, subtype); + if(!assume_non_null) + { + auto returns_null_sym= + new_tmp_symbol(symbol_table,"opaque_returns_null"); + returns_null_sym.type=c_bool_typet(1); + auto returns_null=returns_null_sym.symbol_expr(); + auto assign_returns_null= + code_assignt(returns_null,get_nondet_bool(returns_null_sym.type)); + assign_returns_null.add_source_location() = loc; + init_code.move_to_operands(assign_returns_null); + + auto set_null_inst=code_assignt( + expr,null_pointer_exprt(pointer_type)); + set_null_inst.add_source_location() = loc; + + std::ostringstream fresh_label_oss; + fresh_label_oss<<"post_synthetic_malloc_" + <<(++synthetic_constructor_count); + std::string fresh_label=fresh_label_oss.str(); + set_null_label=code_labelt(fresh_label,set_null_inst); + + init_done_label=code_labelt(fresh_label + "_init_done",code_skipt()); + + code_ifthenelset null_check; + null_check.cond()=notequal_exprt( + returns_null,constant_exprt("0",returns_null_sym.type)); + null_check.then_case()=code_gotot(fresh_label); + init_code.move_to_operands(null_check); + } - gen_nondet_init(deref_expr, init_code, ns, recursion_set, false, ""); + if(subtype.id()==ID_struct && + has_prefix(id2string(to_struct_type(subtype).get_tag()), "java::array[")) + { + gen_nondet_array_init(expr, loc); } - else + else { + exprt allocated=allocate_object(expr,subtype,loc,create_dynamic_objects); + { + exprt init_expr; + if(allocated.id()==ID_address_of) + init_expr=allocated.op0(); + else + init_expr=dereference_exprt(allocated,allocated.type().subtype()); + gen_nondet_init(init_expr,false,"",loc,false,create_dynamic_objects); + } + } + + if(!assume_non_null) { - // make null - null_pointer_exprt null_pointer_expr(pointer_type); - code_assignt code(expr, null_pointer_expr); - init_code.copy_to_operands(code); + init_code.copy_to_operands(code_gotot(init_done_label.get_label())); + init_code.move_to_operands(set_null_label); + init_code.move_to_operands(init_done_label); } - #endif + } else if(type.id()==ID_struct) { @@ -98,6 +242,9 @@ void gen_nondet_init( const componentst &components=struct_type.components(); + if(!is_sub) + class_identifier=struct_tag; + recursion_set.insert(struct_tag); assert(!recursion_set.empty()); @@ -110,15 +257,20 @@ void gen_nondet_init( if(name=="@class_identifier") { + if(skip_classid) + continue; + irep_idt qualified_clsid="java::"+as_string(class_identifier); - constant_exprt ci(qualified_clsid, string_typet()); + constant_exprt ci(qualified_clsid,string_typet()); - code_assignt code(me, ci); - init_code.copy_to_operands(code); + code_assignt code(me, ci); + code.add_source_location() = loc; + init_code.copy_to_operands(code); } else if(name=="@lock") { code_assignt code(me, gen_zero(me.type())); + code.add_source_location() = loc; init_code.copy_to_operands(code); } else @@ -126,14 +278,14 @@ void gen_nondet_init( assert(!name.empty()); bool _is_sub = name[0]=='@'; +#if 0 irep_idt _class_identifier= _is_sub?(class_identifier.empty()?struct_tag:class_identifier):""; +#endif - gen_nondet_init( - me, init_code, ns, recursion_set, _is_sub, _class_identifier); + gen_nondet_init(me, _is_sub, class_identifier, loc, false, create_dynamic_objects); } } - recursion_set.erase(struct_tag); } else @@ -141,11 +293,119 @@ void gen_nondet_init( side_effect_expr_nondett se=side_effect_expr_nondett(type); code_assignt code(expr, se); + code.add_source_location() = loc; init_code.copy_to_operands(code); } } + +// Borrowed from java_bytecode_convert.cpp -- todo find a sensible place to factor this. +static constant_exprt as_number(const mp_integer value, const typet &type) +{ + const unsigned int java_int_width(type.get_unsigned_int(ID_width)); + const std::string significant_bits(integer2string(value, 2)); + std::string binary_width(java_int_width - significant_bits.length(), '0'); + return constant_exprt(binary_width += significant_bits, type); +} + +void gen_nondet_state::gen_nondet_array_init(const exprt &expr, const source_locationt &loc) +{ + assert(expr.type().id()==ID_pointer); + const typet &type=ns.follow(expr.type().subtype()); + const struct_typet &struct_type=to_struct_type(type); + assert(expr.type().subtype().id() == ID_symbol); + const typet &element_type=static_cast(expr.type().subtype().find(ID_C_element_type)); + + auto max_length_expr=as_number(max_nondet_array_length,java_int_type()); + + typet allocate_type; + symbolt &length_sym=new_tmp_symbol(symbol_table,"nondet_array_length"); + length_sym.type=java_int_type(); + const auto &length_sym_expr=length_sym.symbol_expr(); + + // Initialise array with some undetermined length: + gen_nondet_init(length_sym_expr,false,irep_idt(),loc,false,false); + + // Insert assumptions to bound its length: + binary_relation_exprt assume1(length_sym_expr,ID_ge, + as_number(0, java_int_type())); + binary_relation_exprt assume2(length_sym_expr,ID_le, + max_length_expr); + code_assumet assume_inst1(assume1); + code_assumet assume_inst2(assume2); + init_code.move_to_operands(assume_inst1); + init_code.move_to_operands(assume_inst2); + + side_effect_exprt java_new_array(ID_java_new_array,expr.type()); + java_new_array.copy_to_operands(length_sym_expr); + java_new_array.set("skip_initialise",true); + java_new_array.type().subtype().set(ID_C_element_type,element_type); + codet assign = code_assignt(expr,java_new_array); + assign.add_source_location()=loc; + init_code.copy_to_operands(assign); + + exprt init_array_expr=member_exprt(dereference_exprt(expr, expr.type().subtype()), + "data", struct_type.components()[2].type()); + if(init_array_expr.type()!=pointer_typet(element_type)) + init_array_expr=typecast_exprt(init_array_expr,pointer_typet(element_type)); + + // Interpose a new symbol, as the goto-symex stage can't handle array indexing via a cast. + symbolt &array_init_symbol=new_tmp_symbol(symbol_table,"array_data_init"); + array_init_symbol.type=init_array_expr.type(); + const auto &array_init_symexpr=array_init_symbol.symbol_expr(); + codet data_assign = code_assignt(array_init_symexpr,init_array_expr); + data_assign.add_source_location() = loc; + init_code.copy_to_operands(data_assign); + + // Emit init loop for(array_init_iter=0; array_init_iter!=array.length; ++array_init_iter) + // init(array[array_init_iter]); + symbolt &counter=new_tmp_symbol(symbol_table,"array_init_iter"); + counter.type=length_sym_expr.type(); + exprt counter_expr=counter.symbol_expr(); + + init_code.copy_to_operands( + code_assignt(counter_expr,as_number(0, java_int_type()))); + + std::string head_name=as_string(counter.base_name)+"_header"; + code_labelt init_head_label(head_name,code_skipt()); + code_gotot goto_head(head_name); + + init_code.move_to_operands(init_head_label); + + std::string done_name=as_string(counter.base_name)+"_done"; + code_labelt init_done_label(done_name,code_skipt()); + code_gotot goto_done(done_name); + + code_ifthenelset done_test; + done_test.cond()=equal_exprt(counter_expr,length_sym_expr); + done_test.then_case()=goto_done; + + init_code.move_to_operands(done_test); + + // Add a redundant if(counter == max_length) break that is easier for the unwinder to understand. + code_ifthenelset max_test; + max_test.cond()=equal_exprt(counter_expr,max_length_expr); + max_test.then_case()=goto_done; + + init_code.move_to_operands(max_test); + + exprt arraycellref=dereference_exprt( + plus_exprt(array_init_symexpr,counter_expr,array_init_symexpr.type()), + array_init_symexpr.type().subtype()); + + gen_nondet_init(arraycellref,false,irep_idt(),loc,false,true, + /*override_type=*/&element_type); + + code_assignt incr(counter_expr, + plus_exprt(counter_expr, + as_number(1, java_int_type()))); + + init_code.move_to_operands(incr); + init_code.move_to_operands(goto_head); + init_code.move_to_operands(init_done_label); + } + /*******************************************************************\ Function: gen_nondet_init @@ -158,15 +418,19 @@ Function: gen_nondet_init \*******************************************************************/ -namespace { void gen_nondet_init( const exprt &expr, code_blockt &init_code, - const namespacet &ns) + symbol_tablet &symbol_table, + const source_locationt &loc, + bool skip_classid, + bool create_dynamic_objects, + bool assume_non_null, + int max_nondet_array_length) { - std::set recursion_set; - gen_nondet_init(expr, init_code, ns, recursion_set, false, ""); -} + gen_nondet_state state(init_code,assume_non_null,max_nondet_array_length, + symbol_table); + state.gen_nondet_init(expr,false,"",loc,skip_classid,create_dynamic_objects); } /*******************************************************************\ @@ -181,8 +445,7 @@ Function: new_tmp_symbol \*******************************************************************/ -namespace { -symbolt &new_tmp_symbol(symbol_tablet &symbol_table) +symbolt &new_tmp_symbol(symbol_tablet &symbol_table, const std::string& prefix) { static int temporary_counter=0; @@ -198,6 +461,23 @@ symbolt &new_tmp_symbol(symbol_tablet &symbol_table) return *symbol_ptr; } + +/*******************************************************************\ + +Function: get_nondet_bool + + Inputs: Desired type (C_bool or plain bool) + + Outputs: nondet expr of that type + + Purpose: + +\*******************************************************************/ + +exprt get_nondet_bool(const typet& type) { + // We force this to 0 and 1 and won't consider + // other values. + return typecast_exprt(side_effect_expr_nondett(bool_typet()), type); } /*******************************************************************\ @@ -216,27 +496,30 @@ exprt object_factory( const typet &type, code_blockt &init_code, bool allow_null, - symbol_tablet &symbol_table) + symbol_tablet &symbol_table, + int max_nondet_array_length, + const source_locationt &loc) { if(type.id()==ID_pointer) { symbolt &aux_symbol=new_tmp_symbol(symbol_table); - aux_symbol.type=type.subtype(); + aux_symbol.type=type; aux_symbol.is_static_lifetime=true; exprt object=aux_symbol.symbol_expr(); const namespacet ns(symbol_table); - gen_nondet_init(object, init_code, ns); + gen_nondet_init(object, init_code, symbol_table, loc, + false, false, !allow_null, + max_nondet_array_length); - // todo: need to pass null, possibly - return address_of_exprt(object); + return object; } else if(type.id()==ID_c_bool) { // We force this to 0 and 1 and won't consider // other values. - return typecast_exprt(side_effect_expr_nondett(bool_typet()), type); + return get_nondet_bool(type); } else return side_effect_expr_nondett(type); diff --git a/src/java_bytecode/java_object_factory.h b/src/java_bytecode/java_object_factory.h index 5797cb20aed..b86c5d3791c 100644 --- a/src/java_bytecode/java_object_factory.h +++ b/src/java_bytecode/java_object_factory.h @@ -16,6 +16,24 @@ exprt object_factory( const typet &type, code_blockt &init_code, bool allow_null, - symbol_tablet &symbol_table); + symbol_tablet &symbol_table, + int max_nondet_array_length, + const source_locationt &); + +void gen_nondet_init( + const exprt &expr, + code_blockt &init_code, + symbol_tablet &symbol_table, + const source_locationt &, + bool skip_classid = false, + bool create_dynamic_objects = false, + bool assume_non_null = false, + int max_nondet_array_length = 5); + +exprt get_nondet_bool(const typet&); + +symbolt &new_tmp_symbol( + symbol_tablet &symbol_table, + const std::string& prefix = "tmp_object_factory"); #endif // CPROVER_JAVA_BYTECODE_JAVA_OBJECT_FACTORY_H From 6c65dbe2f7729ce4724579e2f30b741a5401d0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 4 Nov 2016 10:01:36 +0100 Subject: [PATCH 05/45] exception table parser Parse the exception table attribute of Java methods. --- src/java_bytecode/java_bytecode_parse_tree.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java_bytecode/java_bytecode_parse_tree.h b/src/java_bytecode/java_bytecode_parse_tree.h index 87b55b27b4a..38a89f87c4a 100644 --- a/src/java_bytecode/java_bytecode_parse_tree.h +++ b/src/java_bytecode/java_bytecode_parse_tree.h @@ -84,6 +84,7 @@ class java_bytecode_parse_treet struct exceptiont { + public: std::size_t start_pc; std::size_t end_pc; std::size_t handler_pc; From 58be145f76583ad6c0aaff6ae2b3eb997c6b0475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 4 Nov 2016 10:01:58 +0100 Subject: [PATCH 06/45] handle java.lang.String literals This patch integrates a first version of handling of Java String Literals. --- src/java_bytecode/java_bytecode_typecheck.h | 3 + .../java_bytecode_typecheck_expr.cpp | 93 ++++++++++++------- 2 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/java_bytecode/java_bytecode_typecheck.h b/src/java_bytecode/java_bytecode_typecheck.h index 56d43c15f02..d1ab4c7848e 100644 --- a/src/java_bytecode/java_bytecode_typecheck.h +++ b/src/java_bytecode/java_bytecode_typecheck.h @@ -10,6 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com #define CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_TYPECHECK_H #include +#include #include #include @@ -63,6 +64,8 @@ class java_bytecode_typecheckt:public typecheckt virtual std::string to_string(const typet &type); std::set already_typechecked; + std::map string_literal_to_symbol_name; + std::map escaped_string_literal_count; }; #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_TYPECHECK_H diff --git a/src/java_bytecode/java_bytecode_typecheck_expr.cpp b/src/java_bytecode/java_bytecode_typecheck_expr.cpp index 48b5f8cc462..d513bf1ebc1 100644 --- a/src/java_bytecode/java_bytecode_typecheck_expr.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_expr.cpp @@ -10,6 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include "java_bytecode_typecheck.h" +#include "java_pointer_casts.h" /*******************************************************************\ @@ -28,6 +29,9 @@ void java_bytecode_typecheckt::typecheck_expr(exprt &expr) if(expr.id()==ID_code) return typecheck_code(to_code(expr)); + if(expr.id()==ID_typecast && expr.type().id()==ID_pointer) + expr=make_clean_pointer_cast(expr,expr.type(),ns); + // do operands recursively Forall_operands(it, expr) typecheck_expr(*it); @@ -86,6 +90,13 @@ void java_bytecode_typecheckt::typecheck_expr_java_new_array(side_effect_exprt & typecheck_type(type); } +static void escape_non_alnum(std::string& toescape) +{ + for(size_t idx=0, lim=toescape.size(); idx!=lim; ++idx) + if(!isalnum(toescape[idx])) + toescape[idx]='_'; +} + /*******************************************************************\ Function: java_bytecode_typecheckt::typecheck_expr_java_string_literal @@ -101,37 +112,45 @@ Function: java_bytecode_typecheckt::typecheck_expr_java_string_literal void java_bytecode_typecheckt::typecheck_expr_java_string_literal(exprt &expr) { const irep_idt value=expr.get(ID_value); - - // we create a symbol for these - const irep_idt identifier="java::java.lang.String.Literal."+ - id2string(value); - - symbol_tablet::symbolst::const_iterator s_it= - symbol_table.symbols.find(identifier); - const symbol_typet string_type("java::java.lang.String"); - if(s_it==symbol_table.symbols.end()) + auto findit=string_literal_to_symbol_name.find(value); + if(findit!=string_literal_to_symbol_name.end()) { - // no, create the symbol - symbolt new_symbol; - new_symbol.name=identifier; - new_symbol.type=string_type; - new_symbol.base_name="Literal"; - new_symbol.pretty_name=value; - new_symbol.mode=ID_java; - new_symbol.is_type=false; - new_symbol.is_lvalue=true; + expr=symbol_exprt(findit->second, pointer_typet(string_type)); + return; + } - if(symbol_table.add(new_symbol)) - { - error() << "failed to add string literal symbol to symbol table" << eom; - throw 0; - } + // Create a new symbol: + std::ostringstream identifier_str; + std::string escaped=id2string(value); + escape_non_alnum(escaped); + identifier_str << "java::java.lang.String.Literal." << escaped; + // Avoid naming clashes by virtue of escaping: + size_t unique_num=++(escaped_string_literal_count[identifier_str.str()]); + if(unique_num!=1) + identifier_str << unique_num; + + irep_idt identifier_id=identifier_str.str(); + string_literal_to_symbol_name.insert(std::make_pair(value,identifier_id)); + + symbolt new_symbol; + new_symbol.name=identifier_id; + new_symbol.type=pointer_typet(string_type); + new_symbol.base_name="Literal"; + new_symbol.pretty_name=value; + new_symbol.mode=ID_java; + new_symbol.is_type=false; + new_symbol.is_lvalue=true; + new_symbol.is_static_lifetime=true; // These are basically const global data. + + if(symbol_table.add(new_symbol)) + { + error() << "failed to add string literal symbol to symbol table" << eom; + throw 0; } - expr=address_of_exprt( - symbol_exprt(identifier, string_type)); + expr=new_symbol.symbol_expr(); } /*******************************************************************\ @@ -208,26 +227,38 @@ Function: java_bytecode_typecheckt::typecheck_expr_symbol void java_bytecode_typecheckt::typecheck_expr_member(member_exprt &expr) { - // The member might be in a parent class, which we resolve here. + // The member might be in a parent class or an opaque class, which we resolve here. const irep_idt component_name=expr.get_component_name(); while(1) { - if(ns.follow(expr.struct_op().type()).id()!=ID_struct) + + typet &base_type = const_cast(ns.follow(expr.struct_op().type())); + + if(base_type.id()!=ID_struct) break; // give up - const struct_typet &struct_type= - to_struct_type(ns.follow(expr.struct_op().type())); + struct_typet &struct_type= + to_struct_type(base_type); if(struct_type.has_component(component_name)) return; // done // look at parent - const struct_typet::componentst &components= + struct_typet::componentst &components= struct_type.components(); + if(struct_type.get_bool(ID_incomplete_class)) { + // Member doesn't exist. In this case struct_type should be an opaque + // stub, and we'll add the member to it. + components.push_back(struct_typet::componentt(component_name, expr.type())); + components.back().set_base_name(component_name); + components.back().set_pretty_name(component_name); + return; + } + if(components.empty()) - break; // give up + break; const struct_typet::componentt &c=components.front(); From 3bcca8540c98a7f3addaa35811ca6646c33a8e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 4 Nov 2016 10:09:26 +0100 Subject: [PATCH 07/45] handle array length and runtime checks for Java This updates the language interface for Java by handling the maximal sizes for arrays in Java and the runtime checks for Java analysis. --- .../java_bytecode_convert_method.cpp | 73 +++++++++++++++++-- src/java_bytecode/java_bytecode_language.cpp | 40 +++++++++- src/java_bytecode/java_bytecode_language.h | 14 +++- 3 files changed, 114 insertions(+), 13 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 854d50ac9ba..9af1aef48dd 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -895,11 +895,23 @@ codet java_bytecode_convert_methodt::convert_instructions( } else if(statement=="checkcast") { - // checkcast throws an exception in case a cast of object - // on stack to given type fails. - // The stack isn't modified. - assert(op.size()==1 && results.size()==1); - results[0]=op[0]; + if(!disable_runtime_checks) + { + // checkcast throws an exception in case a cast of object + // on stack to given type fails. + // The stack isn't modified. + // TODO: convert assertions to exceptions. + assert(op.size()==1 && results.size()==1); + binary_predicate_exprt check(op[0], "java_instanceof", arg0); + c=code_assertt(check); + c.add_source_location().set_comment("Dynamic cast check"); + c.add_source_location().set_property_class("bad-dynamic-cast"); + results[0]=op[0]; + } + else + { + c=code_skipt(); + } } else if(statement=="invokedynamic") { @@ -938,8 +950,17 @@ codet java_bytecode_convert_methodt::convert_instructions( { if(parameters.empty() || !parameters[0].get_this()) { - const empty_typet empty; - pointer_typet object_ref_type(empty); + irep_idt classname = arg0.get(ID_C_class); + typet thistype = symbol_typet(classname); + // Note invokespecial is used for super-method calls as well as constructors. + if(statement=="invokespecial") + { + if(as_string(arg0.get(ID_identifier)).find("")!=std::string::npos) + code_type.set(ID_constructor, true); + else + code_type.set("java_super_method_call", true); + } + pointer_typet object_ref_type(thistype); code_typet::parametert this_p(object_ref_type); this_p.set_this(); this_p.set_base_name("this"); @@ -1055,7 +1076,18 @@ codet java_bytecode_convert_methodt::convert_instructions( typet element_type=data_ptr.type().subtype(); const dereference_exprt element(data_plus_offset, element_type); - c=code_assignt(element, op[2]); + code_blockt assert_and_put; + if(!disable_runtime_checks) + { + codet bounds_check=get_array_bounds_check(deref,op[1],i_it->source_location); + bounds_check.add_source_location()=i_it->source_location; + assert_and_put.move_to_operands(bounds_check); + } + code_assignt array_put(element, op[2]); + array_put.add_source_location()=i_it->source_location; + assert_and_put.move_to_operands(array_put); + c=std::move(assert_and_put); + c.add_source_location()=i_it->source_location; } else if(statement==patternt("?store")) { @@ -1088,6 +1120,12 @@ codet java_bytecode_convert_methodt::convert_instructions( typet element_type=data_ptr.type().subtype(); dereference_exprt element(data_plus_offset, element_type); + if(!disable_runtime_checks) + { + codet bounds_check=get_array_bounds_check(deref,op[1],i_it->source_location); + bounds_check.add_source_location()=i_it->source_location; + c=std::move(bounds_check); + } results[0]=java_bytecode_promotion(element); } else if(statement==patternt("?load")) @@ -1613,6 +1651,25 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!i_it->source_location.get_line().empty()) java_new_array.add_source_location()=i_it->source_location; + code_blockt checkandcreate; + if(!disable_runtime_checks) + { + // TODO make this throw NegativeArrayIndexException instead. + constant_exprt intzero=as_number(0,java_int_type()); + binary_relation_exprt gezero(op[0],ID_ge,intzero); + code_assertt check(gezero); + check.add_source_location().set_comment("Array size < 0"); + check.add_source_location().set_property_class("array-create-negative-size"); + checkandcreate.move_to_operands(check); + + if(max_array_length!=0) + { + constant_exprt size_limit=as_number(max_array_length,java_int_type()); + binary_relation_exprt le_max_size(op[0],ID_le,size_limit); + code_assumet assume_le_max_size(le_max_size); + checkandcreate.move_to_operands(assume_le_max_size); + } + } const exprt tmp=tmp_variable("newarray", ref_type); c=code_assignt(tmp, java_new_array); results[0]=tmp; diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index a015f928115..12851d186e4 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -9,6 +9,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include +#include #include "java_bytecode_language.h" #include "java_bytecode_convert_class.h" @@ -22,6 +24,28 @@ Author: Daniel Kroening, kroening@kroening.com /*******************************************************************\ +Function: java_bytecode_languaget::get_language_options + + Inputs: Command-line options + + Outputs: None + + Purpose: Consume options that are java bytecode specific. + +\*******************************************************************/ + +void java_bytecode_languaget::get_language_options(const cmdlinet& cmd) +{ + disable_runtime_checks=cmd.isset("disable-runtime-check"); + assume_inputs_non_null=cmd.isset("java-assume-inputs-non-null"); + if(cmd.isset("java-max-input-array-length")) + max_nondet_array_length=safe_string2int(cmd.get_value("java-max-input-array-length")); + if(cmd.isset("java-max-vla-length")) + max_user_array_length=safe_string2int(cmd.get_value("java-max-vla-length")); +} + +/*******************************************************************\ + Function: java_bytecode_languaget::extensions Inputs: @@ -169,7 +193,11 @@ bool java_bytecode_languaget::typecheck( debug() << "Converting class " << c_it->first << eom; if(java_bytecode_convert_class( - c_it->second, symbol_table, get_message_handler())) + c_it->second, + disable_runtime_checks, + symbol_table, + get_message_handler(), + max_user_array_length)) return true; } @@ -200,7 +228,15 @@ bool java_bytecode_languaget::final(symbol_tablet &symbol_table) */ java_internal_additions(symbol_table); - if(java_entry_point(symbol_table, main_class, get_message_handler())) + + std::tuple t = get_main_symbol(symbol_table, main_class, get_message_handler()); + if(std::get<2>(t)) + return std::get<1>(t); + + symbolt entry = std::get<0>(t); + + if(java_entry_point(symbol_table,main_class,get_message_handler(), + assume_inputs_non_null,max_nondet_array_length)) return true; return false; diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index a6b5dd6d56b..f94f2890ba9 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -10,13 +10,17 @@ Author: Daniel Kroening, kroening@kroening.com #define CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_LANGUAGE_H #include +#include #include "java_class_loader.h" class java_bytecode_languaget:public languaget { public: - bool preprocess( + + virtual void get_language_options(const cmdlinet&); + + virtual bool preprocess( std::istream &instream, const std::string &path, std::ostream &outstream) override; @@ -34,8 +38,8 @@ class java_bytecode_languaget:public languaget void show_parse(std::ostream &out) override; - ~java_bytecode_languaget() override; - java_bytecode_languaget() { } + virtual ~java_bytecode_languaget(); + java_bytecode_languaget() : max_nondet_array_length(5), max_user_array_length(0) { } bool from_expr( const exprt &expr, @@ -65,6 +69,10 @@ class java_bytecode_languaget:public languaget protected: irep_idt main_class; java_class_loadert java_class_loader; + bool assume_inputs_non_null; + bool disable_runtime_checks; + int max_nondet_array_length; + int max_user_array_length; }; languaget *new_java_bytecode_language(); From ac295b20e2c20ef94ebd1386df64227f88630e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 4 Nov 2016 10:37:31 +0100 Subject: [PATCH 08/45] Java assertion handling Handle Java internal assertions which is triggered by the global `assertionsDisabled` Boolean variable. --- .../java_bytecode_convert_method.cpp | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 9af1aef48dd..4cbea1f5bca 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -887,11 +887,21 @@ codet java_bytecode_convert_methodt::convert_instructions( else if(statement=="athrow") { assert(op.size()==1 && results.size()==1); - side_effect_expr_throwt throw_expr; - throw_expr.add_source_location()=i_it->source_location; - throw_expr.copy_to_operands(op[0]); - c=code_expressiont(throw_expr); - results[0]=op[0]; + if(!assertion_failure) + { + side_effect_expr_throwt throw_expr; + throw_expr.add_source_location()=i_it->source_location; + throw_expr.copy_to_operands(op[0]); + c=code_expressiont(throw_expr); + results[0]=op[0]; + } + else + { + // TODO: this can be removed once we properly handle throw + // if this athrow is generated by an assertion, then skip it + c=code_skipt(); + assertion_failure=false; + } } else if(statement=="checkcast") { @@ -939,7 +949,13 @@ codet java_bytecode_convert_methodt::convert_instructions( statement=="invokevirtual" || statement=="invokestatic") { - const bool use_this(statement!="invokestatic"); + // Remember that this is triggered by an assertion + if(statement=="invokespecial" && + as_string(arg0.get(ID_identifier)).find("AssertionError")!=std::string::npos) + { + assertion_failure=true; + } + const bool use_this(statement != "invokestatic"); const bool is_virtual( statement=="invokevirtual" || statement=="invokeinterface"); @@ -951,7 +967,7 @@ codet java_bytecode_convert_methodt::convert_instructions( if(parameters.empty() || !parameters[0].get_this()) { irep_idt classname = arg0.get(ID_C_class); - typet thistype = symbol_typet(classname); + typet thistype = symbol_typet(classname); // Note invokespecial is used for super-method calls as well as constructors. if(statement=="invokespecial") { @@ -1553,6 +1569,15 @@ codet java_bytecode_convert_methodt::convert_instructions( symbol_expr.set_identifier( arg0.get_string(ID_class)+"."+arg0.get_string(ID_component_name)); results[0]=java_bytecode_promotion(symbol_expr); + + // set $assertionDisabled to false + if(fieldname.find("$assertionsDisabled")!=std::string::npos) + { + exprt e; + e.make_false(); + c=code_assignt(symbol_expr, e); + } + } else if(statement=="putfield") { @@ -1659,7 +1684,7 @@ codet java_bytecode_convert_methodt::convert_instructions( binary_relation_exprt gezero(op[0],ID_ge,intzero); code_assertt check(gezero); check.add_source_location().set_comment("Array size < 0"); - check.add_source_location().set_property_class("array-create-negative-size"); + check.add_source_location().set_property_class("array-create-negative-size"); checkandcreate.move_to_operands(check); if(max_array_length!=0) From beec7210283ec96f5c5baa90d82efc037b0b5a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 4 Nov 2016 10:40:37 +0100 Subject: [PATCH 09/45] class conversion runtime checks / array handling --- .../java_bytecode_convert_class.cpp | 40 ++++++++++++++++--- .../java_bytecode_convert_class.h | 4 +- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 2db872c3f45..b65ee545cb4 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -26,9 +26,13 @@ class java_bytecode_convert_classt:public messaget public: java_bytecode_convert_classt( symbol_tablet &_symbol_table, - message_handlert &_message_handler): + message_handlert &_message_handler, + const bool &_disable_runtime_checks, + int _max_array_length): messaget(_message_handler), - symbol_table(_symbol_table) + symbol_table(_symbol_table), + disable_runtime_checks(_disable_runtime_checks), + max_array_length(_max_array_length) { } @@ -47,6 +51,8 @@ class java_bytecode_convert_classt:public messaget protected: symbol_tablet &symbol_table; + const bool &disable_runtime_checks; + int max_array_length; // conversion void convert(const classt &c); @@ -121,7 +127,8 @@ void java_bytecode_convert_classt::convert(const classt &c) // now do methods for(const auto &method : c.methods) java_bytecode_convert_method( - *class_symbol, method, symbol_table, get_message_handler()); + *class_symbol, method, symbol_table, get_message_handler(), + disable_runtime_checks, max_array_length); // is this a root class? if(c.extends.empty()) @@ -207,6 +214,11 @@ void java_bytecode_convert_classt::convert( new_symbol.is_type=false; new_symbol.value=gen_zero(field_type); + // Do we have the static field symbol already? + const auto s_it=symbol_table.symbols.find(new_symbol.name); + if(s_it!=symbol_table.symbols.end()) + symbol_table.symbols.erase(s_it); // erase, we stubbed it + if(symbol_table.add(new_symbol)) { error() << "failed to add static field symbol" << eom; @@ -259,6 +271,7 @@ void java_bytecode_convert_classt::add_array_types() // we have the base class, java.lang.Object, length and data // of appropriate type struct_type.set_tag(symbol_type.get_identifier()); +<<<<<<< d8b7f7885387d26f7031f56b237aa96e25733f6d struct_type.components().reserve(3); struct_typet::componentt @@ -271,6 +284,18 @@ void java_bytecode_convert_classt::add_array_types() struct_typet::componentt comp2("data", pointer_typet(java_type_from_char(l))); struct_type.components().push_back(comp2); +======= + struct_type.components().resize(3); + struct_type.components()[0].set_name("@java.lang.Object"); + struct_type.components()[0].type()=symbol_typet("java::java.lang.Object"); + struct_type.components()[1].set_name("length"); + struct_type.components()[1].set_pretty_name("length"); + struct_type.components()[1].type()=java_int_type(); + struct_type.components()[2].set_name("data"); + struct_type.components()[2].set_pretty_name("data"); + struct_type.components()[2].type()= + pointer_typet(java_type_from_char(letters[i])); +>>>>>>> class conversion runtime checks / array handling symbolt symbol; symbol.name=symbol_type.get_identifier(); @@ -295,11 +320,16 @@ Function: java_bytecode_convert_class bool java_bytecode_convert_class( const java_bytecode_parse_treet &parse_tree, + const bool &disable_runtime_checks, symbol_tablet &symbol_table, - message_handlert &message_handler) + message_handlert &message_handler, + int max_array_length) { java_bytecode_convert_classt java_bytecode_convert_class( - symbol_table, message_handler); + symbol_table, + message_handler, + disable_runtime_checks, + max_array_length); try { diff --git a/src/java_bytecode/java_bytecode_convert_class.h b/src/java_bytecode/java_bytecode_convert_class.h index cae00f571d0..30737fa79d0 100644 --- a/src/java_bytecode/java_bytecode_convert_class.h +++ b/src/java_bytecode/java_bytecode_convert_class.h @@ -16,7 +16,9 @@ Author: Daniel Kroening, kroening@kroening.com bool java_bytecode_convert_class( const java_bytecode_parse_treet &parse_tree, + const bool &disable_runtime_checks, symbol_tablet &symbol_table, - message_handlert &message_handler); + message_handlert &message_handler, + int max_array_length); #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_CLASS_H From 02caf23aa96c08022c78d67fbe85aa4957f579e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 4 Nov 2016 10:47:20 +0100 Subject: [PATCH 10/45] java bytecode index in source location This adds bytecode index to source location and completes source location information. It also completes JSON output for Java source location information. JSON output for Java --- .../java_bytecode_convert_method.cpp | 17 +++++++++++++---- src/java_bytecode/java_bytecode_parse_tree.h | 1 + src/java_bytecode/java_bytecode_parser.cpp | 10 ++++++++++ src/java_bytecode/java_entry_point.cpp | 17 ++++++++++++----- src/util/irep_ids.txt | 1 + src/util/json_expr.cpp | 7 +++++-- src/util/source_location.cpp | 2 ++ src/util/source_location.h | 10 ++++++++++ 8 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 4cbea1f5bca..5c3eb8b43f4 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -336,8 +336,8 @@ void java_bytecode_convert_methodt::convert( method_symbol.name=method.get_name(); method_symbol.base_name=method.get_base_name(); method_symbol.mode=ID_java; - method_symbol.name=method.get_name(); - method_symbol.base_name=method.get_base_name(); + method_symbol.location=m.source_location; + method_symbol.location.set_function(method_identifier); if(method.get_base_name()=="") method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ @@ -985,7 +985,12 @@ codet java_bytecode_convert_methodt::convert_instructions( } code_function_callt call; - call.add_source_location()=i_it->source_location; + source_locationt loc; + loc=i_it->source_location; + loc.set_function(method_id); + source_locationt &dloc = loc; + + call.add_source_location()=dloc; call.arguments()=pop(parameters.size()); // double-check a bit @@ -1057,7 +1062,7 @@ codet java_bytecode_convert_methodt::convert_instructions( call.function()=symbol_exprt(arg0.get(ID_identifier), arg0.type()); } - call.function().add_source_location()=i_it->source_location; + call.function().add_source_location()=dloc; c=call; } else if(statement=="return") @@ -1292,6 +1297,7 @@ codet java_bytecode_convert_methodt::convert_instructions( cast_if_necessary(condition); code_branch.cond()=condition; + code_branch.cond().add_source_location()=i_it->source_location; code_branch.then_case()=code_gotot(label(number)); code_branch.then_case().add_source_location()=i_it->source_location; code_branch.add_source_location()=i_it->source_location; @@ -1316,9 +1322,12 @@ codet java_bytecode_convert_methodt::convert_instructions( code_branch.cond()= binary_relation_exprt(op[0], id, gen_zero(op[0].type())); code_branch.cond().add_source_location()=i_it->source_location; + code_branch.cond().add_source_location().set_function(method_id); code_branch.then_case()=code_gotot(label(number)); code_branch.then_case().add_source_location()=i_it->source_location; + code_branch.then_case().add_source_location().set_function(method_id); code_branch.add_source_location()=i_it->source_location; + code_branch.add_source_location().set_function(method_id); c=code_branch; } diff --git a/src/java_bytecode/java_bytecode_parse_tree.h b/src/java_bytecode/java_bytecode_parse_tree.h index 38a89f87c4a..398e3959d1a 100644 --- a/src/java_bytecode/java_bytecode_parse_tree.h +++ b/src/java_bytecode/java_bytecode_parse_tree.h @@ -72,6 +72,7 @@ class java_bytecode_parse_treet public: irep_idt base_name; bool is_native, is_abstract, is_synchronized; + source_locationt source_location; typedef std::vector instructionst; instructionst instructions; diff --git a/src/java_bytecode/java_bytecode_parser.cpp b/src/java_bytecode/java_bytecode_parser.cpp index 8a6483abef1..b78afc6c062 100644 --- a/src/java_bytecode/java_bytecode_parser.cpp +++ b/src/java_bytecode/java_bytecode_parser.cpp @@ -746,6 +746,7 @@ void java_bytecode_parsert::rbytecode( instructiont &instruction=instructions.back(); instruction.statement=bytecodes[bytecode].mnemonic; instruction.address=start_of_instruction; + instruction.source_location.set_java_bytecode_index(std::to_string(bytecodeIndex)); switch(bytecodes[bytecode].format) { @@ -1001,8 +1002,16 @@ void java_bytecode_parsert::rmethod_attribute(methodt &method) line_number=it->source_location.get_line(); else if(!line_number.empty()) it->source_location.set_line(line_number); + it->source_location.set_function("java::"+ + id2string(parse_tree.parsed_class.name)+"."+ + id2string(method.name)+":"+ + method.signature); } + // line number of method + if(!method.instructions.empty()) + method.source_location.set_line( + method.instructions.begin()->source_location.get_line()); } else if(attribute_name=="RuntimeInvisibleAnnotations" || attribute_name=="RuntimeVisibleAnnotations") @@ -1416,6 +1425,7 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class) m_it!=parsed_class.methods.end(); m_it++) { + m_it->source_location.set_file(sourcefile_name); for(instructionst::iterator i_it=m_it->instructions.begin(); i_it!=m_it->instructions.end(); i_it++) diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index ee0c0c1c2ae..ecfb8ebc99e 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -123,6 +123,7 @@ bool java_static_lifetime_init( code_function_callt function_call; function_call.lhs()=nil_exprt(); function_call.function()=it->second.symbol_expr(); + function_call.add_source_location()=source_location; code_block.add(function_call); } } @@ -176,7 +177,7 @@ exprt::operandst java_build_arguments( index_exprt(string_constantt(p_symbol.base_name), gen_zero(index_type()))); input.op1()=main_arguments[param_number]; - input.add_source_location()=parameters[param_number].source_location(); + input.add_source_location()=function.location; init_code.move_to_operands(input); } @@ -223,8 +224,7 @@ void java_record_outputs( index_exprt(string_constantt(return_symbol.base_name), gen_zero(index_type()))); output.op1()=return_symbol.symbol_expr(); - output.add_source_location()= - function.value.operands().back().source_location(); + output.add_source_location()=function.location; init_code.move_to_operands(output); } @@ -245,7 +245,7 @@ void java_record_outputs( index_exprt(string_constantt(p_symbol.base_name), gen_zero(index_type()))); output.op1()=main_arguments[param_number]; - output.add_source_location()=parameters[param_number].source_location(); + output.add_source_location()=function.location; init_code.move_to_operands(output); } @@ -437,8 +437,15 @@ bool java_entry_point( // build call to the main method code_function_callt call_main; - call_main.add_source_location()=symbol.location; + + source_locationt loc = symbol.location; + loc.set_function(symbol.name); + source_locationt &dloc = loc; + + call_main.add_source_location()=dloc; call_main.function()=symbol.symbol_expr(); + call_main.function().add_source_location()=dloc; + if(to_code_type(symbol.type).return_type()!=empty_typet()) { auxiliary_symbolt return_symbol; diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index 82ff934bd2f..95cb32a2480 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -733,3 +733,4 @@ verilog_array low high bswap +java_bytecode_index diff --git a/src/util/json_expr.cpp b/src/util/json_expr.cpp index ab03dc33a60..5fbb4325607 100644 --- a/src/util/json_expr.cpp +++ b/src/util/json_expr.cpp @@ -16,7 +16,7 @@ Author: Peter Schrammel #include "config.h" #include "json_expr.h" - +#include /*******************************************************************\ Function: json @@ -45,6 +45,9 @@ json_objectt json(const source_locationt &location) if(!location.get_function().empty()) result["function"]=json_stringt(id2string(location.get_function())); + if(!location.get_java_bytecode_index().empty()) + result["bytecode_index"]=json_stringt(id2string(location.get_java_bytecode_index())); + return result; } @@ -259,7 +262,7 @@ json_objectt json( if(expr.get(ID_value)==ID_NULL) result["data"]=json_stringt("NULL"); } - else if(type.id()==ID_bool) + else if(type.id()==ID_bool || type.id()==ID_c_bool) { result["name"]=json_stringt("boolean"); result["binary"]=json_stringt(expr.is_true()?"1":"0"); diff --git a/src/util/source_location.cpp b/src/util/source_location.cpp index 9406fd61011..8f8b16e3970 100644 --- a/src/util/source_location.cpp +++ b/src/util/source_location.cpp @@ -31,6 +31,7 @@ std::string source_locationt::as_string(bool print_cwd) const const irep_idt &line=get_line(); const irep_idt &column=get_column(); const irep_idt &function=get_function(); + const irep_idt &bytecode=get_java_bytecode_index(); if(!file.empty()) { @@ -45,6 +46,7 @@ std::string source_locationt::as_string(bool print_cwd) const if(!line.empty()) { if(dest!="") dest+=' '; dest+="line "+id2string(line); } if(!column.empty()) { if(dest!="") dest+=' '; dest+="column "+id2string(column); } if(!function.empty()) { if(dest!="") dest+=' '; dest+="function "+id2string(function); } + if(!bytecode.empty()) { if(dest!="") dest+=' '; dest+="bytecode_index "+id2string(bytecode); } return dest; } diff --git a/src/util/source_location.h b/src/util/source_location.h index c34cfb5f9d2..83a79a8f03d 100644 --- a/src/util/source_location.h +++ b/src/util/source_location.h @@ -68,6 +68,11 @@ class source_locationt:public irept return get(ID_comment); } + inline const irep_idt &get_java_bytecode_index() const + { + return get(ID_java_bytecode_index); + } + inline void set_file(const irep_idt &file) { set(ID_file, file); @@ -118,6 +123,11 @@ class source_locationt:public irept set(ID_comment, comment); } + inline void set_java_bytecode_index(const irep_idt &index) + { + set(ID_java_bytecode_index, index); + } + inline void set_hide() { set(ID_hide, true); From e629e13e7137dfd83ccabb4bb195a93ffe1404c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 4 Nov 2016 10:45:02 +0100 Subject: [PATCH 11/45] Correct parsing / generation of source filename --- src/java_bytecode/java_bytecode_parser.cpp | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/java_bytecode/java_bytecode_parser.cpp b/src/java_bytecode/java_bytecode_parser.cpp index b78afc6c062..f0f87644263 100644 --- a/src/java_bytecode/java_bytecode_parser.cpp +++ b/src/java_bytecode/java_bytecode_parser.cpp @@ -6,8 +6,10 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ +#include #include #include +#include #include #include @@ -136,10 +138,10 @@ class java_bytecode_parsert:public parsert } } - u8 read_bytes(unsigned bytes) + u8 read_bytes(size_t bytes) { u8 result=0; - for(unsigned i=0; i Date: Wed, 11 Jan 2017 15:48:22 +0100 Subject: [PATCH 12/45] Clean up Java pointer cast handling --- src/java_bytecode/Makefile | 3 +- src/java_bytecode/java_pointer_casts.cpp | 150 +++++++++++++++++++++++ src/java_bytecode/java_pointer_casts.h | 24 ++++ 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 src/java_bytecode/java_pointer_casts.cpp create mode 100644 src/java_bytecode/java_pointer_casts.h diff --git a/src/java_bytecode/Makefile b/src/java_bytecode/Makefile index f13c327ef77..66ad1003cac 100644 --- a/src/java_bytecode/Makefile +++ b/src/java_bytecode/Makefile @@ -5,7 +5,8 @@ SRC = java_bytecode_language.cpp java_bytecode_parse_tree.cpp \ java_bytecode_typecheck_type.cpp java_bytecode_internal_additions.cpp \ java_root_class.cpp java_bytecode_parser.cpp bytecode_info.cpp \ java_class_loader.cpp jar_file.cpp java_object_factory.cpp \ - java_bytecode_convert_method.cpp java_local_variable_table.cpp + java_bytecode_convert_method.cpp java_local_variable_table.cpp \ + java_pointer_casts.cpp INCLUDES= -I .. diff --git a/src/java_bytecode/java_pointer_casts.cpp b/src/java_bytecode/java_pointer_casts.cpp new file mode 100644 index 00000000000..30bce554248 --- /dev/null +++ b/src/java_bytecode/java_pointer_casts.cpp @@ -0,0 +1,150 @@ + +#include +#include +#include + +#include "java_pointer_casts.h" + +/*******************************************************************\ + +Function: clean_deref + + Inputs: pointer + + Outputs: dereferenced pointer + + Purpose: dereference pointer expression + +\*******************************************************************/ + +exprt clean_deref(const exprt ptr) +{ + return ptr.id()==ID_address_of + ? ptr.op0() + : dereference_exprt(ptr, ptr.type().subtype()); +} + +/*******************************************************************\ + +Function: find_superclass_with_type + + Inputs: pointer + target type to search + + Outputs: true iff a super class with target type is found + + Purpose: + +\*******************************************************************/ + + +bool find_superclass_with_type(exprt &ptr,const typet &target_type, + const namespacet &ns) +{ + + while(true) + { + + const typet ptr_base=ns.follow(ptr.type().subtype()); + + if(ptr_base.id()!=ID_struct) + return false; + + const struct_typet &base_struct=to_struct_type(ptr_base); + + if(base_struct.components().size()==0) + return false; + + const typet &first_field_type= + ns.follow(base_struct.components()[0].type()); + ptr=clean_deref(ptr); + ptr=member_exprt(ptr,base_struct.components()[0].get_name(), + first_field_type); + ptr=address_of_exprt(ptr); + + if(first_field_type==target_type) + return true; + } +} + + +/*******************************************************************\ + +Function: look_through_casts + + Inputs: input expression + + Outputs: recursively search target of typecast + + Purpose: + +\*******************************************************************/ + +static const exprt& look_through_casts(const exprt& in) +{ + if(in.id()==ID_typecast) + { + assert(in.type().id()==ID_pointer); + return look_through_casts(in.op0()); + } + else { + return in; + } +} + + +/*******************************************************************\ + +Function: make_clean_pointer_cast + + Inputs: raw pointer + target type + namespace + + Outputs: cleaned up typecast expression + + Purpose: + +\*******************************************************************/ + +exprt make_clean_pointer_cast(const exprt &rawptr,const typet &target_type, + const namespacet &ns) +{ + + assert(target_type.id()==ID_pointer && + "Non-pointer target in make_clean_pointer_cast?"); + + const exprt &ptr=look_through_casts(rawptr); + + if(ptr.type()==target_type) + return ptr; + + if(ptr.type().subtype()==empty_typet() || + target_type.subtype()==empty_typet()) + return typecast_exprt(ptr,target_type); + + const typet &target_base=ns.follow(target_type.subtype()); + + exprt bare_ptr=ptr; + while(bare_ptr.id()==ID_typecast) + { + assert(bare_ptr.type().id()==ID_pointer && + "Non-pointer in make_clean_pointer_cast?"); + if(bare_ptr.type().subtype()==empty_typet()) + bare_ptr=bare_ptr.op0(); + } + + assert(bare_ptr.type().id()==ID_pointer && + "Non-pointer in make_clean_pointer_cast?"); + + if(bare_ptr.type()==target_type) + return bare_ptr; + + exprt superclass_ptr=bare_ptr; + if(find_superclass_with_type(superclass_ptr,target_base,ns)) + return superclass_ptr; + + return typecast_exprt(bare_ptr,target_type); +} + + diff --git a/src/java_bytecode/java_pointer_casts.h b/src/java_bytecode/java_pointer_casts.h new file mode 100644 index 00000000000..c07492b3db2 --- /dev/null +++ b/src/java_bytecode/java_pointer_casts.h @@ -0,0 +1,24 @@ +/*******************************************************************\ + +Module: JAVA Pointer Casts + +Author: DiffBlue + +\*******************************************************************/ + +#ifndef CPROVER_JAVA_BYTECODE_JAVA_POINTER_CASTS_H +#define CPROVER_JAVA_BYTECODE_JAVA_POINTER_CASTS_H + +exprt clean_deref(const exprt ptr); + +bool find_superclass_with_type( + exprt &ptr, + const typet &target_type, + const namespacet &ns); + +exprt make_clean_pointer_cast( + const exprt &ptr, + const typet &target_type, + const namespacet &ns); + +#endif // CPROVER_JAVA_BYTECODE_JAVA_POINTER_CASTS_H From 7fee670c572cece50b8609eb3b5cb03deeee7668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 11 Nov 2016 12:17:33 +0100 Subject: [PATCH 13/45] extract java bytecode convert method class This extracts the convert method class into an extra file. --- .../java_bytecode_convert_class.cpp | 43 +-- .../java_bytecode_convert_class.h | 4 +- .../java_bytecode_convert_method.cpp | 326 ++++++++++++++++-- .../java_bytecode_convert_method.h | 4 +- src/java_bytecode/java_bytecode_language.cpp | 10 +- src/java_bytecode/java_pointer_casts.cpp | 11 +- 6 files changed, 340 insertions(+), 58 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index b65ee545cb4..5d3fd7213f4 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -27,8 +27,8 @@ class java_bytecode_convert_classt:public messaget java_bytecode_convert_classt( symbol_tablet &_symbol_table, message_handlert &_message_handler, - const bool &_disable_runtime_checks, - int _max_array_length): + const bool _disable_runtime_checks, + size_t _max_array_length): messaget(_message_handler), symbol_table(_symbol_table), disable_runtime_checks(_disable_runtime_checks), @@ -51,8 +51,8 @@ class java_bytecode_convert_classt:public messaget protected: symbol_tablet &symbol_table; - const bool &disable_runtime_checks; - int max_array_length; + const bool disable_runtime_checks; + size_t max_array_length; // conversion void convert(const classt &c); @@ -127,8 +127,12 @@ void java_bytecode_convert_classt::convert(const classt &c) // now do methods for(const auto &method : c.methods) java_bytecode_convert_method( - *class_symbol, method, symbol_table, get_message_handler(), - disable_runtime_checks, max_array_length); + *class_symbol, + method, + symbol_table, + get_message_handler(), + disable_runtime_checks, + max_array_length); // is this a root class? if(c.extends.empty()) @@ -271,9 +275,6 @@ void java_bytecode_convert_classt::add_array_types() // we have the base class, java.lang.Object, length and data // of appropriate type struct_type.set_tag(symbol_type.get_identifier()); -<<<<<<< d8b7f7885387d26f7031f56b237aa96e25733f6d - - struct_type.components().reserve(3); struct_typet::componentt comp0("@java.lang.Object", symbol_typet("java::java.lang.Object")); struct_type.components().push_back(comp0); @@ -284,18 +285,6 @@ void java_bytecode_convert_classt::add_array_types() struct_typet::componentt comp2("data", pointer_typet(java_type_from_char(l))); struct_type.components().push_back(comp2); -======= - struct_type.components().resize(3); - struct_type.components()[0].set_name("@java.lang.Object"); - struct_type.components()[0].type()=symbol_typet("java::java.lang.Object"); - struct_type.components()[1].set_name("length"); - struct_type.components()[1].set_pretty_name("length"); - struct_type.components()[1].type()=java_int_type(); - struct_type.components()[2].set_name("data"); - struct_type.components()[2].set_pretty_name("data"); - struct_type.components()[2].type()= - pointer_typet(java_type_from_char(letters[i])); ->>>>>>> class conversion runtime checks / array handling symbolt symbol; symbol.name=symbol_type.get_identifier(); @@ -320,16 +309,16 @@ Function: java_bytecode_convert_class bool java_bytecode_convert_class( const java_bytecode_parse_treet &parse_tree, - const bool &disable_runtime_checks, symbol_tablet &symbol_table, message_handlert &message_handler, - int max_array_length) + const bool disable_runtime_checks, + size_t max_array_length) { java_bytecode_convert_classt java_bytecode_convert_class( - symbol_table, - message_handler, - disable_runtime_checks, - max_array_length); + symbol_table, + message_handler, + disable_runtime_checks, + max_array_length); try { diff --git a/src/java_bytecode/java_bytecode_convert_class.h b/src/java_bytecode/java_bytecode_convert_class.h index 30737fa79d0..264df6ca9df 100644 --- a/src/java_bytecode/java_bytecode_convert_class.h +++ b/src/java_bytecode/java_bytecode_convert_class.h @@ -16,9 +16,9 @@ Author: Daniel Kroening, kroening@kroening.com bool java_bytecode_convert_class( const java_bytecode_parse_treet &parse_tree, - const bool &disable_runtime_checks, symbol_tablet &symbol_table, message_handlert &message_handler, - int max_array_length); + const bool disable_runtime_checks, + size_t max_array_length); #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_CLASS_H diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 5c3eb8b43f4..70bdc4f86c0 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -55,6 +55,245 @@ class patternt const char *p; }; +class java_bytecode_convert_methodt:public messaget +{ +public: + java_bytecode_convert_methodt( + symbol_tablet &_symbol_table, + message_handlert &_message_handler, + bool _disable_runtime_checks, + size_t _max_array_length): + messaget(_message_handler), + symbol_table(_symbol_table), + disable_runtime_checks(_disable_runtime_checks), + max_array_length(_max_array_length) + { + } + + typedef java_bytecode_parse_treet::methodt methodt; + typedef java_bytecode_parse_treet::instructiont instructiont; + typedef methodt::instructionst instructionst; + + void operator()(const symbolt &class_symbol, const methodt &method) + { + convert(class_symbol, method); + } + +protected: + symbol_tablet &symbol_table; + const bool disable_runtime_checks; + size_t max_array_length; + + irep_idt method_id; + irep_idt current_method; + typet method_return_type; + + class variablet + { + public: + symbol_exprt symbol_expr; + size_t start_pc; + size_t length; + bool is_parameter=false; + }; + + typedef std::vector variablest; + expanding_vector variables; + std::set used_local_names; + bool method_has_this; + + typedef enum instruction_sizet + { + INST_INDEX=2, + INST_INDEX_CONST=3 + } instruction_sizet; + + // return corresponding reference of variable + const variablet &find_variable_for_slot( + size_t address, + variablest &var_list, + instruction_sizet inst_size) + { + for(const variablet &var : var_list) + { + size_t start_pc=var.start_pc; + size_t length=var.length; + if(address+(size_t)inst_size>=start_pc && + address::max(); + return var_list[list_length]; + } + + // JVM local variables + enum variable_cast_argumentt + { + CAST_AS_NEEDED, + NO_CAST + }; + + const exprt variable( + const exprt &arg, + char type_char, + size_t address, + instruction_sizet inst_size, + variable_cast_argumentt do_cast) + { + irep_idt number=to_constant_expr(arg).get_value(); + + std::size_t number_int=safe_string2size_t(id2string(number)); + typet t=java_type_from_char(type_char); + variablest &var_list=variables[number_int]; + + // search variable in list for correct frame / address if necessary + const variablet &var= + find_variable_for_slot(address, var_list, inst_size); + + if(var.symbol_expr.get_identifier().empty()) + { + // an un-named local variable + irep_idt base_name="anonlocal::"+id2string(number)+type_char; + irep_idt identifier=id2string(current_method)+"::"+id2string(base_name); + + symbol_exprt result(identifier, t); + result.set(ID_C_base_name, base_name); + used_local_names.insert(result); + + return result; + } + else + { + exprt result=var.symbol_expr; + if(do_cast==CAST_AS_NEEDED && t!=result.type()) + result=typecast_exprt(result, t); + return result; + } + } + + // temporary variables + std::list tmp_vars; + + symbol_exprt tmp_variable(const std::string &prefix, const typet &type) + { + irep_idt base_name=prefix+"_tmp"+std::to_string(tmp_vars.size()); + irep_idt identifier=id2string(current_method)+"::"+id2string(base_name); + + auxiliary_symbolt tmp_symbol; + tmp_symbol.base_name=base_name; + tmp_symbol.is_static_lifetime=false; + tmp_symbol.mode=ID_java; + tmp_symbol.name=identifier; + tmp_symbol.type=type; + symbol_table.add(tmp_symbol); + + symbol_exprt result(identifier, type); + result.set(ID_C_base_name, base_name); + tmp_vars.push_back(result); + + return result; + } + + // JVM program locations + irep_idt label(const irep_idt &address) + { + return "pc"+id2string(address); + } + + // JVM Stack + typedef std::vector stackt; + stackt stack; + + exprt::operandst pop(std::size_t n) + { + if(stack.size() successors; + std::set predecessors; + codet code; + stackt stack; + bool done; + }; + + typedef std::map address_mapt; + + struct block_tree_nodet + { + bool leaf; + std::vector branch_addresses; + std::vector branch; + block_tree_nodet():leaf(false) {} + explicit block_tree_nodet(bool l):leaf(l) {} + static block_tree_nodet get_leaf() { return block_tree_nodet(true); } + }; + + static void replace_goto_target( + codet &repl, + const irep_idt &old_label, + const irep_idt &new_label); + + code_blockt &get_block_for_pcrange( + block_tree_nodet &tree, + code_blockt &this_block, + unsigned address_start, + unsigned address_limit, + unsigned next_block_start_address); + + code_blockt &get_or_create_block_for_pcrange( + block_tree_nodet &tree, + code_blockt &this_block, + unsigned address_start, + unsigned address_limit, + unsigned next_block_start_address, + const address_mapt &amap, + bool allow_merge=true); + + // conversion + void convert(const symbolt &class_symbol, const methodt &); + void convert(const instructiont &); + + codet convert_instructions( + const instructionst &, const code_typet &); + + const bytecode_infot &get_bytecode_info(const irep_idt &statement); +}; + const size_t SLOTS_PER_INTEGER(1u); const size_t INTEGER_WIDTH(64u); static size_t count_slots( @@ -302,6 +541,7 @@ void java_bytecode_convert_methodt::convert( // add as a JVM variable std::size_t slots=get_variable_slots(param); variables[param_index][0].symbol_expr=parameter_symbol.symbol_expr(); + variables[param_index][0].is_parameter=true; variables[param_index][0].start_pc=0; variables[param_index][0].length=std::numeric_limits::max(); variables[param_index][0].is_parameter=true; @@ -347,6 +587,8 @@ void java_bytecode_convert_methodt::convert( id2string(method.get_base_name())+"()"; method_symbol.type=member_type; + if(is_constructor(method)) + method_symbol.type.set(ID_constructor,true); current_method=method_symbol.name; method_has_this=code_type.has_this(); @@ -418,6 +660,27 @@ static member_exprt to_member(const exprt &pointer, const exprt &fieldref) obj_deref, fieldref.get(ID_component_name), fieldref.type()); } +codet get_array_bounds_check(const exprt &arraystruct, const exprt &idx, const source_locationt& original_sloc) +{ + constant_exprt intzero=as_number(0,java_int_type()); + binary_relation_exprt gezero(idx,ID_ge,intzero); + const member_exprt length_field( + arraystruct, "length", java_int_type()); + binary_relation_exprt ltlength(idx,ID_lt,length_field); + code_blockt boundschecks; + boundschecks.add(code_assertt(gezero)); + boundschecks.operands().back().add_source_location()=original_sloc; + boundschecks.operands().back().add_source_location().set_comment("Array index < 0"); + boundschecks.operands().back().add_source_location().set_property_class("array-index-oob-low"); + boundschecks.add(code_assertt(ltlength)); + boundschecks.operands().back().add_source_location()=original_sloc; + boundschecks.operands().back().add_source_location().set_comment("Array index >= length"); + boundschecks.operands().back().add_source_location().set_property_class("array-index-oob-high"); + + // TODO make this throw ArrayIndexOutOfBoundsException instead of asserting. + return boundschecks; +} + /*******************************************************************\ Function: replace_goto_target @@ -834,6 +1097,8 @@ codet java_bytecode_convert_methodt::convert_instructions( setup_local_variables(method,address_map); std::set working_set; + bool assertion_failure = false; + if(!instructions.empty()) working_set.insert(instructions.front().address); @@ -919,9 +1184,7 @@ codet java_bytecode_convert_methodt::convert_instructions( results[0]=op[0]; } else - { c=code_skipt(); - } } else if(statement=="invokedynamic") { @@ -988,10 +1251,10 @@ codet java_bytecode_convert_methodt::convert_instructions( source_locationt loc; loc=i_it->source_location; loc.set_function(method_id); - source_locationt &dloc = loc; + source_locationt &source_loc=loc; - call.add_source_location()=dloc; - call.arguments()=pop(parameters.size()); + call.add_source_location()=source_loc; + call.arguments() = pop(parameters.size()); // double-check a bit if(use_this) @@ -1037,6 +1300,7 @@ codet java_bytecode_convert_methodt::convert_instructions( // does the function symbol exist? irep_idt id=arg0.get(ID_identifier); + if(symbol_table.symbols.find(id)==symbol_table.symbols.end()) { // no, create stub @@ -1062,8 +1326,8 @@ codet java_bytecode_convert_methodt::convert_instructions( call.function()=symbol_exprt(arg0.get(ID_identifier), arg0.type()); } - call.function().add_source_location()=dloc; - c=call; + call.function().add_source_location()=source_loc; + c = call; } else if(statement=="return") { @@ -1275,7 +1539,7 @@ codet java_bytecode_convert_methodt::convert_instructions( } else { - const unsigned int value(arg0.get_unsigned_int(ID_value)); + const size_t value(arg0.get_unsigned_int(ID_value)); const typet type=java_type_from_char(statement[0]); results[0]=as_number(value, type); } @@ -1404,7 +1668,7 @@ codet java_bytecode_convert_methodt::convert_instructions( const typecast_exprt lhs(op[0], target); const typecast_exprt rhs(op[1], target); - results[0]=lshr_exprt(lhs, rhs); + results[0]=typecast_exprt(lshr_exprt(lhs, rhs),op[0].type()); } else if(statement==patternt("?add")) { @@ -1575,8 +1839,8 @@ codet java_bytecode_convert_methodt::convert_instructions( { assert(op.empty() && results.size()==1); symbol_exprt symbol_expr(arg0.type()); - symbol_expr.set_identifier( - arg0.get_string(ID_class)+"."+arg0.get_string(ID_component_name)); + const auto& fieldname=arg0.get_string(ID_component_name); + symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+fieldname); results[0]=java_bytecode_promotion(symbol_expr); // set $assertionDisabled to false @@ -1586,7 +1850,6 @@ codet java_bytecode_convert_methodt::convert_instructions( e.make_false(); c=code_assignt(symbol_expr, e); } - } else if(statement=="putfield") { @@ -1597,8 +1860,8 @@ codet java_bytecode_convert_methodt::convert_instructions( { assert(op.size()==1 && results.empty()); symbol_exprt symbol_expr(arg0.type()); - symbol_expr.set_identifier( - arg0.get_string(ID_class)+"."+arg0.get_string(ID_component_name)); + const auto& fieldname=arg0.get_string(ID_component_name); + symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+fieldname); c=code_assignt(symbol_expr, op[0]); } else if(statement==patternt("?2?")) // i2c etc. @@ -1662,13 +1925,32 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!i_it->source_location.get_line().empty()) java_new_array.add_source_location()=i_it->source_location; + code_blockt checkandcreate; + if(!disable_runtime_checks) + { + // TODO make this throw NegativeArrayIndexException instead. + constant_exprt intzero=as_number(0,java_int_type()); + binary_relation_exprt gezero(op[0],ID_ge,intzero); + code_assertt check(gezero); + check.add_source_location().set_comment("Array size < 0"); + check.add_source_location().set_property_class("array-create-negative-size"); + checkandcreate.move_to_operands(check); + } + if(max_array_length!=0) + { + constant_exprt size_limit=as_number(max_array_length,java_int_type()); + binary_relation_exprt le_max_size(op[0],ID_le,size_limit); + code_assumet assume_le_max_size(le_max_size); + checkandcreate.move_to_operands(assume_le_max_size); + } const exprt tmp=tmp_variable("newarray", ref_type); - c=code_assignt(tmp, java_new_array); + checkandcreate.copy_to_operands(code_assignt(tmp, java_new_array)); + c=std::move(checkandcreate); results[0]=tmp; } else if(statement=="multianewarray") { - // The first argument is the type, the second argument is the dimension. + // The first argument is the type, the second argument is the number of dimensions. // The size of each dimension is on the stack. irep_idt number=to_constant_expr(arg1).get_value(); std::size_t dimension=safe_string2size_t(id2string(number)); @@ -1676,8 +1958,7 @@ codet java_bytecode_convert_methodt::convert_instructions( op=pop(dimension); assert(results.size()==1); - // arg0.type() - const pointer_typet ref_type=java_array_type('a'); + const pointer_typet ref_type=pointer_typet(arg0.type()); side_effect_exprt java_new_array(ID_java_new_array, ref_type); java_new_array.operands()=op; @@ -2028,10 +2309,15 @@ void java_bytecode_convert_method( const symbolt &class_symbol, const java_bytecode_parse_treet::methodt &method, symbol_tablet &symbol_table, - message_handlert &message_handler) + message_handlert &message_handler, + bool disable_runtime_checks, + size_t max_array_length) { java_bytecode_convert_methodt java_bytecode_convert_method( - symbol_table, message_handler); + symbol_table, + message_handler, + disable_runtime_checks, + max_array_length); java_bytecode_convert_method(class_symbol, method); } diff --git a/src/java_bytecode/java_bytecode_convert_method.h b/src/java_bytecode/java_bytecode_convert_method.h index ff652b3fe91..8945af95bd1 100644 --- a/src/java_bytecode/java_bytecode_convert_method.h +++ b/src/java_bytecode/java_bytecode_convert_method.h @@ -18,6 +18,8 @@ void java_bytecode_convert_method( const symbolt &class_symbol, const java_bytecode_parse_treet::methodt &, symbol_tablet &symbol_table, - message_handlert &message_handler); + message_handlert &message_handler, + bool disable_runtime_checks, + size_t max_array_length); #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_H diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 12851d186e4..afbf40d93b2 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -193,11 +193,11 @@ bool java_bytecode_languaget::typecheck( debug() << "Converting class " << c_it->first << eom; if(java_bytecode_convert_class( - c_it->second, - disable_runtime_checks, - symbol_table, - get_message_handler(), - max_user_array_length)) + c_it->second, + symbol_table, + get_message_handler(), + disable_runtime_checks, + max_user_array_length)) return true; } diff --git a/src/java_bytecode/java_pointer_casts.cpp b/src/java_bytecode/java_pointer_casts.cpp index 30bce554248..483e0287467 100644 --- a/src/java_bytecode/java_pointer_casts.cpp +++ b/src/java_bytecode/java_pointer_casts.cpp @@ -1,3 +1,10 @@ +/*******************************************************************\ + +Module: JAVA Pointer Casts + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ #include #include @@ -115,7 +122,7 @@ exprt make_clean_pointer_cast(const exprt &rawptr,const typet &target_type, "Non-pointer target in make_clean_pointer_cast?"); const exprt &ptr=look_through_casts(rawptr); - + if(ptr.type()==target_type) return ptr; @@ -146,5 +153,3 @@ exprt make_clean_pointer_cast(const exprt &rawptr,const typet &target_type, return typecast_exprt(bare_ptr,target_type); } - - From f0cb8ce38c73d7d856ec2f2a0556412879509a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Wed, 11 Jan 2017 16:44:03 +0100 Subject: [PATCH 14/45] Java entry point / main function Restructure finding of the entry point of the Java function or the main function of the program. --- src/java_bytecode/java_bytecode_language.cpp | 15 +- src/java_bytecode/java_bytecode_language.h | 13 +- src/java_bytecode/java_entry_point.cpp | 221 +++++++++++++++---- src/java_bytecode/java_entry_point.h | 16 +- src/java_bytecode/java_object_factory.cpp | 12 +- src/java_bytecode/java_object_factory.h | 4 +- src/java_bytecode/java_types.cpp | 4 +- 7 files changed, 215 insertions(+), 70 deletions(-) diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index afbf40d93b2..3bf20193698 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -6,6 +6,8 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ +#include + #include #include #include @@ -39,9 +41,9 @@ void java_bytecode_languaget::get_language_options(const cmdlinet& cmd) disable_runtime_checks=cmd.isset("disable-runtime-check"); assume_inputs_non_null=cmd.isset("java-assume-inputs-non-null"); if(cmd.isset("java-max-input-array-length")) - max_nondet_array_length=safe_string2int(cmd.get_value("java-max-input-array-length")); + max_nondet_array_length=std::stoi(cmd.get_value("java-max-input-array-length")); if(cmd.isset("java-max-vla-length")) - max_user_array_length=safe_string2int(cmd.get_value("java-max-vla-length")); + max_user_array_length=std::stoi(cmd.get_value("java-max-vla-length")); } /*******************************************************************\ @@ -229,11 +231,12 @@ bool java_bytecode_languaget::final(symbol_tablet &symbol_table) java_internal_additions(symbol_table); - std::tuple t = get_main_symbol(symbol_table, main_class, get_message_handler()); - if(std::get<2>(t)) - return std::get<1>(t); + main_function_resultt res= + get_main_symbol(symbol_table, main_class, get_message_handler()); + if(res.stop_convert) + return res.error_found; - symbolt entry = std::get<0>(t); + symbolt entry=res.main_function; if(java_entry_point(symbol_table,main_class,get_message_handler(), assume_inputs_non_null,max_nondet_array_length)) diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index f94f2890ba9..7fef0f68c97 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -69,10 +69,15 @@ class java_bytecode_languaget:public languaget protected: irep_idt main_class; java_class_loadert java_class_loader; - bool assume_inputs_non_null; - bool disable_runtime_checks; - int max_nondet_array_length; - int max_user_array_length; + bool assume_inputs_non_null; // assume inputs variables to be non-null + + bool disable_runtime_checks; // disable run-time checks for java, i.e., + // ASSERTS for + // - checkcast / instanceof + // - array bounds check + // - array size for newarray + size_t max_nondet_array_length; // maximal length for non-det array creation + size_t max_user_array_length; // max size for user supplied arrays }; languaget *new_java_bytecode_language(); diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index ecfb8ebc99e..d5f44931b9a 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -21,6 +21,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include #include @@ -28,6 +29,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_entry_point.h" #include "java_object_factory.h" +#include "java_types.h" #define INITIALIZE CPROVER_PREFIX "initialize" @@ -82,30 +84,75 @@ Function: java_static_lifetime_init \*******************************************************************/ +static bool should_init_symbol(const symbolt& sym) +{ + if(sym.type.id()!=ID_code && + sym.is_lvalue && + sym.is_state_var && + sym.is_static_lifetime && + sym.mode==ID_java) + return true; + + if(has_prefix(id2string(sym.name),"java::java.lang.String.Literal")) + return true; + + return false; +} + bool java_static_lifetime_init( symbol_tablet &symbol_table, const source_locationt &source_location, - message_handlert &message_handler) + message_handlert &message_handler, + bool assume_init_pointers_not_null, + unsigned max_nondet_array_length) { symbolt &initialize_symbol=symbol_table.lookup(INITIALIZE); code_blockt &code_block=to_code_block(to_code(initialize_symbol.value)); - // we need to zero out all static variables + // we need to zero out all static variables, or nondet-initialize if they're external. + // Iterate over a copy of the symtab, as its iterators are invalidated by object_factory: - for(symbol_tablet::symbolst::const_iterator - it=symbol_table.symbols.begin(); - it!=symbol_table.symbols.end(); - it++) + std::vector symnames; + symnames.reserve(symbol_table.symbols.size()); + for(const auto& entry : symbol_table.symbols) + symnames.push_back(entry.first); + + for(const auto& symname : symnames) { - if(it->second.type.id()!=ID_code && - it->second.is_lvalue && - it->second.is_state_var && - it->second.is_static_lifetime && - it->second.value.is_not_nil() && - it->second.mode==ID_java) + const symbolt& sym=symbol_table.lookup(symname); + if(should_init_symbol(sym)) { - code_assignt assignment(it->second.symbol_expr(), it->second.value); - code_block.add(assignment); + if(sym.value.is_nil() && sym.type!=empty_typet()) + { + bool allow_null=!assume_init_pointers_not_null; + if(allow_null) + { + std::string namestr=id2string(sym.symbol_expr().get_identifier()); + const std::string suffix="@class_model"; + // Static '.class' fields are always non-null. + if(namestr.size()>=suffix.size() && + namestr.substr(namestr.size()-suffix.size())==suffix) + allow_null=false; + if(allow_null && has_prefix( + namestr, + "java::java.lang.String.Literal")) + allow_null=false; + } + auto newsym=object_factory(sym.type, + code_block, + allow_null, + symbol_table, + max_nondet_array_length, + source_location); + code_assignt assignment(sym.symbol_expr(), newsym); + code_block.add(assignment); + } + else if(sym.value.is_not_nil()) + { + code_assignt assignment(sym.symbol_expr(), sym.value); + assignment.add_source_location()=source_location; + code_block.add(assignment); + } } } @@ -131,6 +178,11 @@ bool java_static_lifetime_init( return false; } +static bool is_string_array(const typet& t) +{ + typet compare_to=java_type_from_string("[Ljava.lang.String;"); + return full_eq(t,compare_to); +} /*******************************************************************\ @@ -147,7 +199,9 @@ Function: java_build_arguments exprt::operandst java_build_arguments( const symbolt &function, code_blockt &init_code, - symbol_tablet &symbol_table) + symbol_tablet &symbol_table, + bool assume_init_pointers_not_null, + unsigned max_nondet_array_length) { const code_typet::parameterst ¶meters= to_code_type(function.type).parameters(); @@ -159,13 +213,28 @@ exprt::operandst java_build_arguments( param_numbersecond; @@ -341,7 +402,10 @@ bool java_entry_point( { message.error() << "main symbol `" << config.main << "' not a function" << messaget::eom; - return true; + res.main_function=symbol; + res.error_found=true; + res.stop_convert=true; + return res; } // check if it has a body @@ -349,7 +413,10 @@ bool java_entry_point( { message.error() << "main method `" << main_class << "' has no body" << messaget::eom; - return true; + res.main_function=symbol; + res.error_found=true; + res.stop_convert=true; + return res; } } else @@ -359,7 +426,12 @@ bool java_entry_point( // are we given a main class? if(main_class.empty()) - return false; // silently ignore + { + res.main_function=symbol; + res.error_found=false; + res.stop_convert=true; + return res; // silently ignore + } std::string entry_method= id2string(main_class)+".main"; @@ -382,14 +454,20 @@ bool java_entry_point( if(matches.empty()) { // Not found, silently ignore - return false; + res.main_function=symbol; + res.error_found=false; + res.stop_convert=true; + return res; } if(matches.size()>=2) { message.error() << "main method in `" << main_class << "' is ambiguous" << messaget::eom; - return true; // give up with error, no main + res.main_function=symbol; + res.error_found=true; + res.stop_convert=true; + return res; // give up with error, no main } // function symbol @@ -400,16 +478,59 @@ bool java_entry_point( { message.error() << "main method `" << main_class << "' has no body" << messaget::eom; - return true; // give up with error + res.main_function=symbol; + res.error_found=true; + res.stop_convert=true; + return res; // give up with error } } + res.main_function=symbol; + res.error_found=false; + res.stop_convert=false; + return res; // give up with error +} + +/*******************************************************************\ + +Function: java_entry_point + + Inputs: symbol_table + main class + message_handler + allow pointers in initialization code to be null + + Outputs: true if error occurred on entry point search + + Purpose: find entry point and create initialization code for function + +\*******************************************************************/ + +bool java_entry_point( + symbol_tablet &symbol_table, + const irep_idt &main_class, + message_handlert &message_handler, + bool assume_init_pointers_not_null, + size_t max_nondet_array_length) +{ + // check if the entry point is already there + if(symbol_table.symbols.find(goto_functionst::entry_point())!= + symbol_table.symbols.end()) + return false; // silently ignore + + messaget message(message_handler); + main_function_resultt res = get_main_symbol(symbol_table, main_class, message_handler); + if(res.stop_convert) + return res.stop_convert; + symbolt symbol = res.main_function; + assert(!symbol.value.is_nil()); assert(symbol.type.id()==ID_code); create_initialize(symbol_table); - if(java_static_lifetime_init(symbol_table, symbol.location, message_handler)) + if(java_static_lifetime_init(symbol_table, symbol.location, message_handler, + assume_init_pointers_not_null, max_nondet_array_length)) return true; code_blockt init_code; @@ -460,7 +581,9 @@ bool java_entry_point( } exprt::operandst main_arguments= - java_build_arguments(symbol, init_code, symbol_table); + java_build_arguments(symbol, init_code, symbol_table, + assume_init_pointers_not_null, + max_nondet_array_length); call_main.arguments()=main_arguments; init_code.move_to_operands(call_main); diff --git a/src/java_bytecode/java_entry_point.h b/src/java_bytecode/java_entry_point.h index 5cbee65febb..7fa562de89a 100644 --- a/src/java_bytecode/java_entry_point.h +++ b/src/java_bytecode/java_entry_point.h @@ -14,6 +14,20 @@ Author: Daniel Kroening, kroening@kroening.com bool java_entry_point( class symbol_tablet &symbol_table, const irep_idt &main_class, - class message_handlert &message_handler); + class message_handlert &message_handler, + bool assume_init_pointers_not_null, + size_t max_nondet_array_length); + +typedef struct +{ + symbolt main_function; + bool error_found; + bool stop_convert; +} main_function_resultt; + +main_function_resultt get_main_symbol( + symbol_tablet &symbol_table, + const irep_idt &main_class, + message_handlert &); #endif // CPROVER_JAVA_BYTECODE_JAVA_ENTRY_POINT_H diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index b27797b0416..766d2202358 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -37,13 +37,13 @@ class gen_nondet_state { code_blockt& init_code; std::set recursion_set; bool assume_non_null; - int max_nondet_array_length; + size_t max_nondet_array_length; symbol_tablet& symbol_table; namespacet ns; public: - gen_nondet_state(code_blockt& ic, bool ann, int mnal, symbol_tablet& st) : + gen_nondet_state(code_blockt& ic, bool ann, size_t mnal, symbol_tablet& st) : init_code(ic), assume_non_null(ann), max_nondet_array_length(mnal), @@ -301,7 +301,7 @@ void gen_nondet_state::gen_nondet_init( // Borrowed from java_bytecode_convert.cpp -- todo find a sensible place to factor this. static constant_exprt as_number(const mp_integer value, const typet &type) { - const unsigned int java_int_width(type.get_unsigned_int(ID_width)); + const size_t java_int_width(type.get_unsigned_int(ID_width)); const std::string significant_bits(integer2string(value, 2)); std::string binary_width(java_int_width - significant_bits.length(), '0'); return constant_exprt(binary_width += significant_bits, type); @@ -426,7 +426,7 @@ void gen_nondet_init( bool skip_classid, bool create_dynamic_objects, bool assume_non_null, - int max_nondet_array_length) + size_t max_nondet_array_length) { gen_nondet_state state(init_code,assume_non_null,max_nondet_array_length, symbol_table); @@ -447,7 +447,7 @@ Function: new_tmp_symbol symbolt &new_tmp_symbol(symbol_tablet &symbol_table, const std::string& prefix) { - static int temporary_counter=0; + static size_t temporary_counter=0; auxiliary_symbolt new_symbol; symbolt *symbol_ptr; @@ -497,7 +497,7 @@ exprt object_factory( code_blockt &init_code, bool allow_null, symbol_tablet &symbol_table, - int max_nondet_array_length, + size_t max_nondet_array_length, const source_locationt &loc) { if(type.id()==ID_pointer) diff --git a/src/java_bytecode/java_object_factory.h b/src/java_bytecode/java_object_factory.h index b86c5d3791c..5e8d4417ad5 100644 --- a/src/java_bytecode/java_object_factory.h +++ b/src/java_bytecode/java_object_factory.h @@ -17,7 +17,7 @@ exprt object_factory( code_blockt &init_code, bool allow_null, symbol_tablet &symbol_table, - int max_nondet_array_length, + size_t max_nondet_array_length, const source_locationt &); void gen_nondet_init( @@ -28,7 +28,7 @@ void gen_nondet_init( bool skip_classid = false, bool create_dynamic_objects = false, bool assume_non_null = false, - int max_nondet_array_length = 5); + size_t max_nondet_array_length = 5); exprt get_nondet_bool(const typet&); diff --git a/src/java_bytecode/java_types.cpp b/src/java_bytecode/java_types.cpp index 37682a99d49..5b19db8e581 100644 --- a/src/java_bytecode/java_types.cpp +++ b/src/java_bytecode/java_types.cpp @@ -448,7 +448,7 @@ char java_char_from_type(const typet &type) if(id==ID_signedbv) { - const unsigned int width(type.get_unsigned_int(ID_width)); + const size_t width(type.get_unsigned_int(ID_width)); if(java_int_type().get_unsigned_int(ID_width) == width) return 'i'; else if(java_long_type().get_unsigned_int(ID_width) == width) @@ -462,7 +462,7 @@ char java_char_from_type(const typet &type) return 'c'; else if(id==ID_floatbv) { - const unsigned int width(type.get_unsigned_int(ID_width)); + const size_t width(type.get_unsigned_int(ID_width)); if(java_float_type().get_unsigned_int(ID_width) == width) return 'f'; else if(java_double_type().get_unsigned_int(ID_width) == width) From c1a34930effd3c9886ab20055787fe75d44d6d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 19 Dec 2016 12:51:15 +0100 Subject: [PATCH 15/45] Correct java type width handling Use `.get_width()` instead of `ID_width` and split a complex statement in Java typecheck. --- .../java_bytecode_typecheck_expr.cpp | 3 ++- src/java_bytecode/java_types.cpp | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/java_bytecode/java_bytecode_typecheck_expr.cpp b/src/java_bytecode/java_bytecode_typecheck_expr.cpp index d513bf1ebc1..fd60c72b7dc 100644 --- a/src/java_bytecode/java_bytecode_typecheck_expr.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_expr.cpp @@ -127,7 +127,8 @@ void java_bytecode_typecheckt::typecheck_expr_java_string_literal(exprt &expr) escape_non_alnum(escaped); identifier_str << "java::java.lang.String.Literal." << escaped; // Avoid naming clashes by virtue of escaping: - size_t unique_num=++(escaped_string_literal_count[identifier_str.str()]); + size_t unique_num=escaped_string_literal_count[identifier_str.str()]; + unique_num++; if(unique_num!=1) identifier_str << unique_num; diff --git a/src/java_bytecode/java_types.cpp b/src/java_bytecode/java_types.cpp index 5b19db8e581..88fc91d1587 100644 --- a/src/java_bytecode/java_types.cpp +++ b/src/java_bytecode/java_types.cpp @@ -448,24 +448,24 @@ char java_char_from_type(const typet &type) if(id==ID_signedbv) { - const size_t width(type.get_unsigned_int(ID_width)); - if(java_int_type().get_unsigned_int(ID_width) == width) + const size_t width=to_signedbv_type(type).get_width(); + if(to_signedbv_type(java_int_type()).get_width()==width) return 'i'; - else if(java_long_type().get_unsigned_int(ID_width) == width) + else if(to_signedbv_type(java_long_type()).get_width()==width) return 'l'; - else if(java_short_type().get_unsigned_int(ID_width) == width) + else if(to_signedbv_type(java_short_type()).get_width()==width) return 's'; - else if(java_byte_type().get_unsigned_int(ID_width) == width) + else if(to_signedbv_type(java_byte_type()).get_width()==width) return 'b'; } else if(id==ID_unsignedbv) return 'c'; else if(id==ID_floatbv) { - const size_t width(type.get_unsigned_int(ID_width)); - if(java_float_type().get_unsigned_int(ID_width) == width) + const size_t width(to_floatbv_type(type).get_width()); + if(to_floatbv_type(java_float_type()).get_width()==width) return 'f'; - else if(java_double_type().get_unsigned_int(ID_width) == width) + else if(to_floatbv_type(java_double_type()).get_width()==width) return 'd'; } else if(id==ID_c_bool) From dfe795a22f707e61134a28f4bde5ce1f705cef4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 13 Jan 2017 16:47:22 +0100 Subject: [PATCH 16/45] pacify cpplint --- src/java_bytecode/expr2java.cpp | 12 +- src/java_bytecode/expr2java.h | 18 +- .../java_bytecode_convert_class.cpp | 11 +- .../java_bytecode_convert_method.cpp | 181 +++++++----- src/java_bytecode/java_bytecode_language.cpp | 11 +- src/java_bytecode/java_bytecode_language.h | 5 +- src/java_bytecode/java_bytecode_parser.cpp | 148 +++++----- src/java_bytecode/java_bytecode_typecheck.h | 4 +- .../java_bytecode_typecheck_expr.cpp | 21 +- src/java_bytecode/java_class_loader.cpp | 8 +- src/java_bytecode/java_entry_point.cpp | 93 +++--- src/java_bytecode/java_object_factory.cpp | 264 ++++++++++-------- src/java_bytecode/java_object_factory.h | 10 +- src/java_bytecode/java_pointer_casts.cpp | 45 +-- src/util/json_expr.cpp | 12 +- src/util/source_location.cpp | 40 ++- src/util/source_location.h | 3 - 17 files changed, 532 insertions(+), 354 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 7574c1e4ce9..47e21d2f9c7 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -90,7 +90,10 @@ std::string expr2javat::convert_code_function_call( unsigned p; std::string arg_str=convert(*it, p); - if(first) first=false; else dest+=", "; + if(first) + first=false; + else + dest+=", "; // TODO: ggf. Klammern je nach p dest+=arg_str; } @@ -218,7 +221,7 @@ std::string expr2javat::convert_constant( dest+="(char)'"; if(int_value>=' ' && int_value<127) - dest+=(char)(int_value.to_long()); + dest+=static_cast(int_value.to_long()); else { std::string hex=integer2string(int_value, 16); @@ -332,7 +335,8 @@ std::string expr2javat::convert_rec( if(code_type.has_ellipsis()) { - if(!parameters.empty()) dest+=", "; + if(!parameters.empty()) + dest+=", "; dest+="..."; } @@ -534,7 +538,7 @@ std::string expr2javat::convert_code( if(statement==ID_java_new || statement==ID_java_new_array) - return convert_java_new(src,indent); + return convert_java_new(src, indent); if(statement==ID_function_call) return convert_code_function_call(to_code_function_call(src), indent); diff --git a/src/java_bytecode/expr2java.h b/src/java_bytecode/expr2java.h index f4d03084348..a304f077288 100644 --- a/src/java_bytecode/expr2java.h +++ b/src/java_bytecode/expr2java.h @@ -19,7 +19,7 @@ class typet; class expr2javat:public expr2ct { public: - expr2javat(const namespacet &_ns):expr2ct(_ns) { } + explicit expr2javat(const namespacet &_ns):expr2ct(_ns) { } virtual std::string convert(const exprt &src) { @@ -34,13 +34,21 @@ class expr2javat:public expr2ct protected: virtual std::string convert(const exprt &src, unsigned &precedence); virtual std::string convert_java_this(const exprt &src, unsigned precedence); - virtual std::string convert_java_instanceof(const exprt &src, unsigned precedence); + virtual std::string convert_java_instanceof( + const exprt &src, + unsigned precedence); virtual std::string convert_java_new(const exprt &src, unsigned precedence); - virtual std::string convert_code_java_delete(const exprt &src, unsigned precedence); + virtual std::string convert_code_java_delete( + const exprt &src, + unsigned precedence); virtual std::string convert_struct(const exprt &src, unsigned &precedence); virtual std::string convert_code(const codet &src, unsigned indent); - virtual std::string convert_constant(const constant_exprt &src, unsigned &precedence); - virtual std::string convert_code_function_call(const code_function_callt &src, unsigned indent); + virtual std::string convert_constant( + const constant_exprt &src, + unsigned &precedence); + virtual std::string convert_code_function_call( + const code_function_callt &src, + unsigned indent); virtual std::string convert_rec( const typet &src, diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 5d3fd7213f4..295d7bfb367 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -20,7 +20,6 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -namespace { class java_bytecode_convert_classt:public messaget { public: @@ -61,7 +60,6 @@ class java_bytecode_convert_classt:public messaget void generate_class_stub(const irep_idt &class_name); void add_array_types(); }; -} /*******************************************************************\ @@ -151,7 +149,8 @@ Function: java_bytecode_convert_classt::generate_class_stub \*******************************************************************/ -void java_bytecode_convert_classt::generate_class_stub(const irep_idt &class_name) +void java_bytecode_convert_classt::generate_class_stub( + const irep_idt &class_name) { class_typet class_type; @@ -174,7 +173,8 @@ void java_bytecode_convert_classt::generate_class_stub(const irep_idt &class_nam if(symbol_table.move(new_symbol, class_symbol)) { - warning() << "stub class symbol "+id2string(new_symbol.name)+" already exists"; + warning() << "stub class symbol "+ + id2string(new_symbol.name)+" already exists"; } else { @@ -213,7 +213,8 @@ void java_bytecode_convert_classt::convert( new_symbol.name=id2string(class_symbol.name)+"."+id2string(f.name); new_symbol.base_name=f.name; new_symbol.type=field_type; - new_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+id2string(f.name); + new_symbol.pretty_name=id2string(class_symbol.pretty_name)+ + "."+id2string(f.name); new_symbol.mode=ID_java; new_symbol.is_type=false; new_symbol.value=gen_zero(field_type); diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 70bdc4f86c0..c54f4f235f8 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -172,6 +172,8 @@ class java_bytecode_convert_methodt:public messaget else { exprt result=var.symbol_expr; + if(!var.is_parameter) + used_local_names.insert(to_symbol_expr(result)); if(do_cast==CAST_AS_NEEDED && t!=result.type()) result=typecast_exprt(result, t); return result; @@ -289,7 +291,8 @@ class java_bytecode_convert_methodt:public messaget void convert(const instructiont &); codet convert_instructions( - const instructionst &, const code_typet &); + const instructionst &, + const code_typet &); const bytecode_infot &get_bytecode_info(const irep_idt &statement); }; @@ -588,7 +591,7 @@ void java_bytecode_convert_methodt::convert( method_symbol.type=member_type; if(is_constructor(method)) - method_symbol.type.set(ID_constructor,true); + method_symbol.type.set(ID_constructor, true); current_method=method_symbol.name; method_has_this=code_type.has_this(); @@ -620,7 +623,8 @@ const bytecode_infot &java_bytecode_convert_methodt::get_bytecode_info( const irep_idt &statement) { for(const bytecode_infot *p=bytecode_info; p->mnemonic!=0; p++) - if(statement==p->mnemonic) return *p; + if(statement==p->mnemonic) + return *p; error() << "failed to find bytecode mnemonic `" << statement << '\'' << eom; @@ -629,14 +633,20 @@ const bytecode_infot &java_bytecode_convert_methodt::get_bytecode_info( static irep_idt get_if_cmp_operator(const irep_idt &stmt) { - if(stmt==patternt("if_?cmplt")) return ID_lt; - if(stmt==patternt("if_?cmple")) return ID_le; - if(stmt==patternt("if_?cmpgt")) return ID_gt; - if(stmt==patternt("if_?cmpge")) return ID_ge; - if(stmt==patternt("if_?cmpeq")) return ID_equal; - if(stmt==patternt("if_?cmpne")) return ID_notequal; - - throw "Unhandled java comparison instruction"; + if(stmt==patternt("if_?cmplt")) + return ID_lt; + if(stmt==patternt("if_?cmple")) + return ID_le; + if(stmt==patternt("if_?cmpgt")) + return ID_gt; + if(stmt==patternt("if_?cmpge")) + return ID_ge; + if(stmt==patternt("if_?cmpeq")) + return ID_equal; + if(stmt==patternt("if_?cmpne")) + return ID_notequal; + + throw "unhandled java comparison instruction"; } static constant_exprt as_number(const mp_integer value, const typet &type) @@ -657,25 +667,33 @@ static member_exprt to_member(const exprt &pointer, const exprt &fieldref) const dereference_exprt obj_deref(pointer2, class_type); return member_exprt( - obj_deref, fieldref.get(ID_component_name), fieldref.type()); + obj_deref, + fieldref.get(ID_component_name), + fieldref.type()); } -codet get_array_bounds_check(const exprt &arraystruct, const exprt &idx, const source_locationt& original_sloc) +codet get_array_bounds_check( + const exprt &arraystruct, + const exprt &idx, + const source_locationt& original_sloc) { - constant_exprt intzero=as_number(0,java_int_type()); - binary_relation_exprt gezero(idx,ID_ge,intzero); - const member_exprt length_field( - arraystruct, "length", java_int_type()); - binary_relation_exprt ltlength(idx,ID_lt,length_field); + constant_exprt intzero=as_number(0, java_int_type()); + binary_relation_exprt gezero(idx, ID_ge, intzero); + const member_exprt length_field(arraystruct, "length", java_int_type()); + binary_relation_exprt ltlength(idx, ID_lt, length_field); code_blockt boundschecks; boundschecks.add(code_assertt(gezero)); boundschecks.operands().back().add_source_location()=original_sloc; - boundschecks.operands().back().add_source_location().set_comment("Array index < 0"); - boundschecks.operands().back().add_source_location().set_property_class("array-index-oob-low"); + boundschecks.operands().back().add_source_location() + .set_comment("Array index < 0"); + boundschecks.operands().back().add_source_location() + .set_property_class("array-index-oob-low"); boundschecks.add(code_assertt(ltlength)); boundschecks.operands().back().add_source_location()=original_sloc; - boundschecks.operands().back().add_source_location().set_comment("Array index >= length"); - boundschecks.operands().back().add_source_location().set_property_class("array-index-oob-high"); + boundschecks.operands().back().add_source_location() + .set_comment("Array index >= length"); + boundschecks.operands().back().add_source_location() + .set_property_class("array-index-oob-high"); // TODO make this throw ArrayIndexOutOfBoundsException instead of asserting. return boundschecks; @@ -1000,9 +1018,10 @@ codet java_bytecode_convert_methodt::convert_instructions( i_it++) { std::pair a_entry= - address_map.insert(std::make_pair( - i_it->address, - converted_instructiont(i_it, code_skipt()))); + address_map.insert( + std::make_pair( + i_it->address, + converted_instructiont(i_it, code_skipt()))); assert(a_entry.second); // addresses are strictly increasing, hence we must have inserted // a new maximal key @@ -1097,7 +1116,7 @@ codet java_bytecode_convert_methodt::convert_instructions( setup_local_variables(method,address_map); std::set working_set; - bool assertion_failure = false; + bool assertion_failure=false; if(!instructions.empty()) working_set.insert(instructions.front().address); @@ -1109,19 +1128,22 @@ codet java_bytecode_convert_methodt::convert_instructions( assert(a_it!=address_map.end()); working_set.erase(cur); - if(a_it->second.done) continue; - working_set.insert(a_it->second.successors.begin(), - a_it->second.successors.end()); + if(a_it->second.done) + continue; + working_set + .insert(a_it->second.successors.begin(), a_it->second.successors.end()); instructionst::const_iterator i_it=a_it->second.source; stack.swap(a_it->second.stack); a_it->second.stack.clear(); codet &c=a_it->second.code; - assert(stack.empty() || - a_it->second.predecessors.size()<=1 || - has_prefix(stack.front().get_string(ID_C_base_name), - "$stack")); + assert( + stack.empty() || + a_it->second.predecessors.size()<=1 || + has_prefix( + stack.front().get_string(ID_C_base_name), + "$stack")); irep_idt statement=i_it->statement; exprt arg0=i_it->args.size()>=1?i_it->args[0]:nil_exprt(); @@ -1214,11 +1236,12 @@ codet java_bytecode_convert_methodt::convert_instructions( { // Remember that this is triggered by an assertion if(statement=="invokespecial" && - as_string(arg0.get(ID_identifier)).find("AssertionError")!=std::string::npos) + as_string(arg0.get(ID_identifier)) + .find("AssertionError")!=std::string::npos) { assertion_failure=true; } - const bool use_this(statement != "invokestatic"); + const bool use_this(statement!="invokestatic"); const bool is_virtual( statement=="invokevirtual" || statement=="invokeinterface"); @@ -1229,12 +1252,14 @@ codet java_bytecode_convert_methodt::convert_instructions( { if(parameters.empty() || !parameters[0].get_this()) { - irep_idt classname = arg0.get(ID_C_class); - typet thistype = symbol_typet(classname); - // Note invokespecial is used for super-method calls as well as constructors. + irep_idt classname=arg0.get(ID_C_class); + typet thistype=symbol_typet(classname); + // Note invokespecial is used for super-method calls as well as + // constructors. if(statement=="invokespecial") { - if(as_string(arg0.get(ID_identifier)).find("")!=std::string::npos) + if(as_string(arg0.get(ID_identifier)) + .find("")!=std::string::npos) code_type.set(ID_constructor, true); else code_type.set("java_super_method_call", true); @@ -1254,7 +1279,7 @@ codet java_bytecode_convert_methodt::convert_instructions( source_locationt &source_loc=loc; call.add_source_location()=source_loc; - call.arguments() = pop(parameters.size()); + call.arguments()=pop(parameters.size()); // double-check a bit if(use_this) @@ -1327,7 +1352,7 @@ codet java_bytecode_convert_methodt::convert_instructions( } call.function().add_source_location()=source_loc; - c = call; + c=call; } else if(statement=="return") { @@ -1340,7 +1365,8 @@ codet java_bytecode_convert_methodt::convert_instructions( // conversion. assert(op.size()==1 && results.empty()); exprt r=op[0]; - if(r.type()!=method_return_type) r=typecast_exprt(r, method_return_type); + if(r.type()!=method_return_type) + r=typecast_exprt(r, method_return_type); c=code_returnt(r); } else if(statement==patternt("?astore")) @@ -1355,7 +1381,9 @@ codet java_bytecode_convert_methodt::convert_instructions( const dereference_exprt deref(pointer, pointer.type().subtype()); const member_exprt data_ptr( - deref, "data", pointer_typet(java_type_from_char(type_char))); + deref, + "data", + pointer_typet(java_type_from_char(type_char))); plus_exprt data_plus_offset(data_ptr, op[1], data_ptr.type()); typet element_type=data_ptr.type().subtype(); @@ -1364,7 +1392,8 @@ codet java_bytecode_convert_methodt::convert_instructions( code_blockt assert_and_put; if(!disable_runtime_checks) { - codet bounds_check=get_array_bounds_check(deref,op[1],i_it->source_location); + codet bounds_check= + get_array_bounds_check(deref, op[1], i_it->source_location); bounds_check.add_source_location()=i_it->source_location; assert_and_put.move_to_operands(bounds_check); } @@ -1379,7 +1408,8 @@ codet java_bytecode_convert_methodt::convert_instructions( // store value into some local variable assert(op.size()==1 && results.empty()); - exprt var=variable(arg0, statement[0], i_it->address, NO_CAST); + exprt var= + variable(arg0, statement[0], i_it->address, INST_INDEX, NO_CAST); exprt toassign=op[0]; if('a'==statement[0] && toassign.type()!=var.type()) @@ -1399,7 +1429,9 @@ codet java_bytecode_convert_methodt::convert_instructions( const dereference_exprt deref(pointer, pointer.type().subtype()); const member_exprt data_ptr( - deref, "data", pointer_typet(java_type_from_char(type_char))); + deref, + "data", + pointer_typet(java_type_from_char(type_char))); plus_exprt data_plus_offset(data_ptr, op[1], data_ptr.type()); typet element_type=data_ptr.type().subtype(); @@ -1407,7 +1439,8 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!disable_runtime_checks) { - codet bounds_check=get_array_bounds_check(deref,op[1],i_it->source_location); + codet bounds_check= + get_array_bounds_check(deref, op[1], i_it->source_location); bounds_check.add_source_location()=i_it->source_location; c=std::move(bounds_check); } @@ -1416,7 +1449,8 @@ codet java_bytecode_convert_methodt::convert_instructions( else if(statement==patternt("?load")) { // load a value from a local variable - results[0]=variable(arg0, statement[0], i_it->address, CAST_AS_NEEDED); + results[0]= + variable(arg0, statement[0], i_it->address, INST_INDEX, CAST_AS_NEEDED); } else if(statement=="ldc" || statement=="ldc_w" || statement=="ldc2" || statement=="ldc2_w") @@ -1524,9 +1558,9 @@ codet java_bytecode_convert_methodt::convert_instructions( if(is_double || is_float) { const ieee_float_spect spec( - is_float ? - ieee_float_spect::single_precision() : - ieee_float_spect::double_precision()); + is_float? + ieee_float_spect::single_precision(): + ieee_float_spect::double_precision()); ieee_floatt value(spec); const typet &arg_type(arg0.type()); @@ -1554,7 +1588,8 @@ codet java_bytecode_convert_methodt::convert_instructions( irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==2 && results.empty()); - code_ifthenelset code_branch; + code_ifthenelset + code_branch; const irep_idt cmp_op=get_if_cmp_operator(statement); binary_relation_exprt condition(op[0], cmp_op, op[1]); @@ -1582,7 +1617,8 @@ codet java_bytecode_convert_methodt::convert_instructions( irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==1 && results.empty()); - code_ifthenelset code_branch; + code_ifthenelset + code_branch; code_branch.cond()= binary_relation_exprt(op[0], id, gen_zero(op[0].type())); code_branch.cond().add_source_location()=i_it->source_location; @@ -1599,7 +1635,8 @@ codet java_bytecode_convert_methodt::convert_instructions( { irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==1 && results.empty()); - code_ifthenelset code_branch; + code_ifthenelset + code_branch; const typecast_exprt lhs(op[0], pointer_typet(empty_typet())); const exprt rhs(gen_zero(lhs.type())); code_branch.cond()=binary_relation_exprt(lhs, ID_notequal, rhs); @@ -1613,7 +1650,8 @@ codet java_bytecode_convert_methodt::convert_instructions( { assert(op.size()==1 && results.empty()); irep_idt number=to_constant_expr(arg0).get_value(); - code_ifthenelset code_branch; + code_ifthenelset + code_branch; const typecast_exprt lhs(op[0], pointer_typet(empty_typet())); const exprt rhs(gen_zero(lhs.type())); code_branch.cond()=binary_relation_exprt(lhs, ID_equal, rhs); @@ -1626,7 +1664,8 @@ codet java_bytecode_convert_methodt::convert_instructions( else if(statement=="iinc") { code_assignt code_assign; - code_assign.lhs()=variable(arg0, 'i', i_it->address, NO_CAST); + code_assign.lhs()= + variable(arg0, 'i', i_it->address, INST_INDEX_CONST, NO_CAST); code_assign.rhs()=plus_exprt( variable(arg0, 'i', i_it->address, CAST_AS_NEEDED), typecast_exprt(arg1, java_int_type())); @@ -1668,7 +1707,7 @@ codet java_bytecode_convert_methodt::convert_instructions( const typecast_exprt lhs(op[0], target); const typecast_exprt rhs(op[1], target); - results[0]=typecast_exprt(lshr_exprt(lhs, rhs),op[0].type()); + results[0]=typecast_exprt(lshr_exprt(lhs, rhs), op[0].type()); } else if(statement==patternt("?add")) { @@ -1715,9 +1754,13 @@ codet java_bytecode_convert_methodt::convert_instructions( const typet t=java_int_type(); results[0]= - if_exprt(binary_relation_exprt(op[0], ID_equal, op[1]), gen_zero(t), - if_exprt(binary_relation_exprt(op[0], ID_gt, op[1]), from_integer(1, t), - from_integer(-1, t))); + if_exprt( + binary_relation_exprt(op[0], ID_equal, op[1]), + gen_zero(t), + if_exprt( + binary_relation_exprt(op[0], ID_gt, op[1]), + from_integer(1, t), + from_integer(-1, t))); } else if(statement==patternt("?cmp?")) { @@ -1929,17 +1972,18 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!disable_runtime_checks) { // TODO make this throw NegativeArrayIndexException instead. - constant_exprt intzero=as_number(0,java_int_type()); - binary_relation_exprt gezero(op[0],ID_ge,intzero); + constant_exprt intzero=as_number(0, java_int_type()); + binary_relation_exprt gezero(op[0], ID_ge, intzero); code_assertt check(gezero); check.add_source_location().set_comment("Array size < 0"); - check.add_source_location().set_property_class("array-create-negative-size"); + check.add_source_location() + .set_property_class("array-create-negative-size"); checkandcreate.move_to_operands(check); } if(max_array_length!=0) { - constant_exprt size_limit=as_number(max_array_length,java_int_type()); - binary_relation_exprt le_max_size(op[0],ID_le,size_limit); + constant_exprt size_limit=as_number(max_array_length, java_int_type()); + binary_relation_exprt le_max_size(op[0], ID_le, size_limit); code_assumet assume_le_max_size(le_max_size); checkandcreate.move_to_operands(assume_le_max_size); } @@ -1950,8 +1994,8 @@ codet java_bytecode_convert_methodt::convert_instructions( } else if(statement=="multianewarray") { - // The first argument is the type, the second argument is the number of dimensions. - // The size of each dimension is on the stack. + // The first argument is the type, the second argument is the number of + // dimensions. The size of each dimension is on the stack. irep_idt number=to_constant_expr(arg1).get_value(); std::size_t dimension=safe_string2size_t(id2string(number)); @@ -2138,8 +2182,7 @@ codet java_bytecode_convert_methodt::convert_instructions( stackt::const_iterator os_it=a_it2->second.stack.begin(); for(auto &expr : stack) { - assert(has_prefix(os_it->get_string(ID_C_base_name), - "$stack")); + assert(has_prefix(os_it->get_string(ID_C_base_name), "$stack")); symbol_exprt lhs=to_symbol_expr(*os_it); code_assignt a(lhs, expr); more_code.copy_to_operands(a); diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 3bf20193698..20b996999d5 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -41,7 +41,8 @@ void java_bytecode_languaget::get_language_options(const cmdlinet& cmd) disable_runtime_checks=cmd.isset("disable-runtime-check"); assume_inputs_non_null=cmd.isset("java-assume-inputs-non-null"); if(cmd.isset("java-max-input-array-length")) - max_nondet_array_length=std::stoi(cmd.get_value("java-max-input-array-length")); + max_nondet_array_length= + std::stoi(cmd.get_value("java-max-input-array-length")); if(cmd.isset("java-max-vla-length")) max_user_array_length=std::stoi(cmd.get_value("java-max-vla-length")); } @@ -238,8 +239,12 @@ bool java_bytecode_languaget::final(symbol_tablet &symbol_table) symbolt entry=res.main_function; - if(java_entry_point(symbol_table,main_class,get_message_handler(), - assume_inputs_non_null,max_nondet_array_length)) + if(java_entry_point( + symbol_table, + main_class, + get_message_handler(), + assume_inputs_non_null, + max_nondet_array_length)) return true; return false; diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index 7fef0f68c97..dbbc945ccaf 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -17,7 +17,6 @@ Author: Daniel Kroening, kroening@kroening.com class java_bytecode_languaget:public languaget { public: - virtual void get_language_options(const cmdlinet&); virtual bool preprocess( @@ -39,7 +38,9 @@ class java_bytecode_languaget:public languaget void show_parse(std::ostream &out) override; virtual ~java_bytecode_languaget(); - java_bytecode_languaget() : max_nondet_array_length(5), max_user_array_length(0) { } + java_bytecode_languaget(): + max_nondet_array_length(5), + max_user_array_length(0) { } bool from_expr( const exprt &expr, diff --git a/src/java_bytecode/java_bytecode_parser.cpp b/src/java_bytecode/java_bytecode_parser.cpp index f0f87644263..f2e14888d10 100644 --- a/src/java_bytecode/java_bytecode_parser.cpp +++ b/src/java_bytecode/java_bytecode_parser.cpp @@ -352,7 +352,7 @@ void java_bytecode_parsert::get_class_refs() } break; - default:; + default:{}; } } @@ -447,7 +447,8 @@ void java_bytecode_parsert::rconstant_pool() it++) { // the first entry isn't used - if(it==constant_pool.begin()) continue; + if(it==constant_pool.begin()) + continue; it->tag=read_u1(); @@ -520,7 +521,8 @@ void java_bytecode_parsert::rconstant_pool() it++) { // the first entry isn't used - if(it==constant_pool.begin()) continue; + if(it==constant_pool.begin()) + continue; switch(it->tag) { @@ -637,13 +639,12 @@ void java_bytecode_parsert::rconstant_pool() { it->expr.id("invokedynamic"); const pool_entryt &nameandtype_entry=pool_entry(it->ref2); - //const pool_entryt &name_entry=pool_entry(nameandtype_entry.ref1); typet type=type_entry(nameandtype_entry.ref2); it->expr.type()=type; } break; - default:; + default:{}; } } } @@ -665,7 +666,8 @@ void java_bytecode_parsert::rinterfaces(classt &parsed_class) u2 interfaces_count=read_u2(); for(std::size_t i=0; isource_location.get_line(); else if(!line_number.empty()) it->source_location.set_line(line_number); - it->source_location.set_function("java::"+ - id2string(parse_tree.parsed_class.name)+"."+ - id2string(method.name)+":"+ - method.signature); + it->source_location + .set_function( + "java::"+id2string(parse_tree.parsed_class.name)+"."+ + id2string(method.name)+":"+method.signature); } // line number of method @@ -1078,7 +1088,8 @@ void java_bytecode_parsert::rcode_attribute(methodt &method) if(attribute_name=="LineNumberTable") { // address -> instructiont - typedef std::map instruction_mapt; + typedef std::map instruction_mapt; instruction_mapt instruction_map; for(methodt::instructionst::iterator @@ -1120,7 +1131,8 @@ void java_bytecode_parsert::rcode_attribute(methodt &method) method.local_variable_table[i].index=index; method.local_variable_table[i].name=pool_entry(name_index).s; - method.local_variable_table[i].signature=id2string(pool_entry(descriptor_index).s); + method.local_variable_table[i].signature= + id2string(pool_entry(descriptor_index).s); method.local_variable_table[i].start_pc=start_pc; method.local_variable_table[i].length=length; } @@ -1134,96 +1146,106 @@ void java_bytecode_parsert::rcode_attribute(methodt &method) for(size_t i=0; i already_typechecked; - std::map string_literal_to_symbol_name; - std::map escaped_string_literal_count; + std::map string_literal_to_symbol_name; + std::map escaped_string_literal_count; }; #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_TYPECHECK_H diff --git a/src/java_bytecode/java_bytecode_typecheck_expr.cpp b/src/java_bytecode/java_bytecode_typecheck_expr.cpp index fd60c72b7dc..d1bb21eea0d 100644 --- a/src/java_bytecode/java_bytecode_typecheck_expr.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_expr.cpp @@ -30,7 +30,7 @@ void java_bytecode_typecheckt::typecheck_expr(exprt &expr) return typecheck_code(to_code(expr)); if(expr.id()==ID_typecast && expr.type().id()==ID_pointer) - expr=make_clean_pointer_cast(expr,expr.type(),ns); + expr=make_clean_pointer_cast(expr, expr.type(), ns); // do operands recursively Forall_operands(it, expr) @@ -83,7 +83,8 @@ Function: java_bytecode_typecheckt::typecheck_expr_java_new_array \*******************************************************************/ -void java_bytecode_typecheckt::typecheck_expr_java_new_array(side_effect_exprt &expr) +void java_bytecode_typecheckt::typecheck_expr_java_new_array( + side_effect_exprt &expr) { assert(expr.operands().size()>=1); // one per dimension typet &type=expr.type(); @@ -133,7 +134,7 @@ void java_bytecode_typecheckt::typecheck_expr_java_string_literal(exprt &expr) identifier_str << unique_num; irep_idt identifier_id=identifier_str.str(); - string_literal_to_symbol_name.insert(std::make_pair(value,identifier_id)); + string_literal_to_symbol_name.insert(std::make_pair(value, identifier_id)); symbolt new_symbol; new_symbol.name=identifier_id; @@ -228,13 +229,13 @@ Function: java_bytecode_typecheckt::typecheck_expr_symbol void java_bytecode_typecheckt::typecheck_expr_member(member_exprt &expr) { - // The member might be in a parent class or an opaque class, which we resolve here. + // The member might be in a parent class or an opaque class, which we resolve + // here. const irep_idt component_name=expr.get_component_name(); while(1) { - - typet &base_type = const_cast(ns.follow(expr.struct_op().type())); + typet &base_type=const_cast(ns.follow(expr.struct_op().type())); if(base_type.id()!=ID_struct) break; // give up @@ -249,10 +250,12 @@ void java_bytecode_typecheckt::typecheck_expr_member(member_exprt &expr) struct_typet::componentst &components= struct_type.components(); - if(struct_type.get_bool(ID_incomplete_class)) { - // Member doesn't exist. In this case struct_type should be an opaque + if(struct_type.get_bool(ID_incomplete_class)) + { + // member doesn't exist. In this case struct_type should be an opaque // stub, and we'll add the member to it. - components.push_back(struct_typet::componentt(component_name, expr.type())); + components + .push_back(struct_typet::componentt(component_name, expr.type())); components.back().set_base_name(component_name); components.back().set_pretty_name(component_name); return; diff --git a/src/java_bytecode/java_class_loader.cpp b/src/java_bytecode/java_class_loader.cpp index 0eca596149b..541faf6828d 100644 --- a/src/java_bytecode/java_class_loader.cpp +++ b/src/java_bytecode/java_class_loader.cpp @@ -209,7 +209,8 @@ Function: java_class_loadert::read_jar_file void java_class_loadert::read_jar_file(const irep_idt &file) { // done already? - if(jar_map.find(file)!=jar_map.end()) return; + if(jar_map.find(file)!=jar_map.end()) + return; #ifndef HAVE_LIBZIP error() << "no support for reading JAR files configured" << eom; @@ -277,7 +278,8 @@ std::string java_class_loadert::file_to_class_name(const std::string &file) // slash to dot for(std::string::iterator it=result.begin(); it!=result.end(); it++) - if(*it=='/') *it='.'; + if(*it=='/') + *it='.'; return result; } @@ -301,11 +303,13 @@ std::string java_class_loadert::class_name_to_file(const irep_idt &class_name) // dots (package name separators) to slash, depending on OS for(std::string::iterator it=result.begin(); it!=result.end(); it++) if(*it=='.') + { #ifdef _WIN32 *it='\\'; #else *it='/'; #endif + } // add .class suffix result+=".class"; diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index d5f44931b9a..e828b898d5f 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -20,7 +20,6 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include -#include #include #include #include @@ -93,7 +92,7 @@ static bool should_init_symbol(const symbolt& sym) sym.mode==ID_java) return true; - if(has_prefix(id2string(sym.name),"java::java.lang.String.Literal")) + if(has_prefix(id2string(sym.name), "java::java.lang.String.Literal")) return true; return false; @@ -109,8 +108,9 @@ bool java_static_lifetime_init( symbolt &initialize_symbol=symbol_table.lookup(INITIALIZE); code_blockt &code_block=to_code_block(to_code(initialize_symbol.value)); - // we need to zero out all static variables, or nondet-initialize if they're external. - // Iterate over a copy of the symtab, as its iterators are invalidated by object_factory: + // W need to zero out all static variables, or nondet-initialize if they're + // external. Iterate over a copy of the symtab, as its iterators are + // invalidated by object_factory: std::vector symnames; symnames.reserve(symbol_table.symbols.size()); @@ -138,20 +138,21 @@ bool java_static_lifetime_init( "java::java.lang.String.Literal")) allow_null=false; } - auto newsym=object_factory(sym.type, - code_block, - allow_null, - symbol_table, - max_nondet_array_length, - source_location); - code_assignt assignment(sym.symbol_expr(), newsym); - code_block.add(assignment); + auto newsym=object_factory( + sym.type, + code_block, + allow_null, + symbol_table, + max_nondet_array_length, + source_location); + code_assignt assignment(sym.symbol_expr(), newsym); + code_block.add(assignment); } else if(sym.value.is_not_nil()) { - code_assignt assignment(sym.symbol_expr(), sym.value); - assignment.add_source_location()=source_location; - code_block.add(assignment); + code_assignt assignment(sym.symbol_expr(), sym.value); + assignment.add_source_location()=source_location; + code_block.add(assignment); } } } @@ -181,7 +182,7 @@ bool java_static_lifetime_init( static bool is_string_array(const typet& t) { typet compare_to=java_type_from_string("[Ljava.lang.String;"); - return full_eq(t,compare_to); + return full_eq(t, compare_to); } /*******************************************************************\ @@ -219,7 +220,7 @@ exprt::operandst java_build_arguments( bool is_main=is_default_entry_point; if(!is_main) { - bool named_main=has_suffix(config.main,".main"); + bool named_main=has_suffix(config.main, ".main"); bool has_correct_type= to_code_type(function.type).return_type().id()==ID_empty && (!to_code_type(function.type).has_this()) && @@ -231,10 +232,13 @@ exprt::operandst java_build_arguments( bool allow_null=(!is_main) && (!is_this) && !assume_init_pointers_not_null; main_arguments[param_number]= - object_factory(parameters[param_number].type(), - init_code, allow_null, symbol_table, - max_nondet_array_length, - function.location); + object_factory( + parameters[param_number].type(), + init_code, + allow_null, + symbol_table, + max_nondet_array_length, + function.location); const symbolt &p_symbol= symbol_table.lookup(parameters[param_number].get_identifier()); @@ -243,8 +247,9 @@ exprt::operandst java_build_arguments( codet input(ID_input); input.operands().resize(2); input.op0()=address_of_exprt( - index_exprt(string_constantt(p_symbol.base_name), - gen_zero(index_type()))); + index_exprt( + string_constantt(p_symbol.base_name), + gen_zero(index_type()))); input.op1()=main_arguments[param_number]; input.add_source_location()=function.location; @@ -289,9 +294,11 @@ void java_record_outputs( const symbolt &return_symbol=symbol_table.lookup("return'"); - output.op0()=address_of_exprt( - index_exprt(string_constantt(return_symbol.base_name), - gen_zero(index_type()))); + output.op0()= + address_of_exprt( + index_exprt( + string_constantt(return_symbol.base_name), + gen_zero(index_type()))); output.op1()=return_symbol.symbol_expr(); output.add_source_location()=function.location; @@ -310,9 +317,11 @@ void java_record_outputs( // record as an output codet output(ID_output); output.operands().resize(2); - output.op0()=address_of_exprt( - index_exprt(string_constantt(p_symbol.base_name), - gen_zero(index_type()))); + output.op0()= + address_of_exprt( + index_exprt( + string_constantt(p_symbol.base_name), + gen_zero(index_type()))); output.op1()=main_arguments[param_number]; output.add_source_location()=function.location; @@ -519,18 +528,23 @@ bool java_entry_point( return false; // silently ignore messaget message(message_handler); - main_function_resultt res = get_main_symbol(symbol_table, main_class, message_handler); + main_function_resultt res= + get_main_symbol(symbol_table, main_class, message_handler); if(res.stop_convert) return res.stop_convert; - symbolt symbol = res.main_function; + symbolt symbol=res.main_function; assert(!symbol.value.is_nil()); assert(symbol.type.id()==ID_code); create_initialize(symbol_table); - if(java_static_lifetime_init(symbol_table, symbol.location, message_handler, - assume_init_pointers_not_null, max_nondet_array_length)) + if(java_static_lifetime_init( + symbol_table, + symbol.location, + message_handler, + assume_init_pointers_not_null, + max_nondet_array_length)) return true; code_blockt init_code; @@ -559,9 +573,9 @@ bool java_entry_point( code_function_callt call_main; - source_locationt loc = symbol.location; + source_locationt loc=symbol.location; loc.set_function(symbol.name); - source_locationt &dloc = loc; + source_locationt &dloc=loc; call_main.add_source_location()=dloc; call_main.function()=symbol.symbol_expr(); @@ -581,9 +595,12 @@ bool java_entry_point( } exprt::operandst main_arguments= - java_build_arguments(symbol, init_code, symbol_table, - assume_init_pointers_not_null, - max_nondet_array_length); + java_build_arguments( + symbol, + init_code, + symbol_table, + assume_init_pointers_not_null, + max_nondet_array_length); call_main.arguments()=main_arguments; init_code.move_to_operands(call_main); diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 766d2202358..2935a411dd1 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -32,45 +32,45 @@ Function: gen_nondet_init \*******************************************************************/ -class gen_nondet_state { - - code_blockt& init_code; +class gen_nondet_statet +{ + code_blockt &init_code; std::set recursion_set; bool assume_non_null; size_t max_nondet_array_length; - symbol_tablet& symbol_table; + symbol_tablet &symbol_table; namespacet ns; public: - - gen_nondet_state(code_blockt& ic, bool ann, size_t mnal, symbol_tablet& st) : + gen_nondet_statet(code_blockt& ic, bool ann, size_t mnal, symbol_tablet& st) : init_code(ic), assume_non_null(ann), max_nondet_array_length(mnal), symbol_table(st), ns(st) {} - exprt allocate_object(const exprt&, const typet&, - const source_locationt &, - bool create_dynamic_objects); + exprt allocate_object( + const exprt&, + const typet&, + const source_locationt &, + bool create_dynamic_objects); void gen_nondet_array_init(const exprt &expr, const source_locationt &); - void gen_nondet_init(const exprt &expr, - bool is_sub, - irep_idt class_identifier, - const source_locationt &loc, - bool skip_classid, - bool create_dynamic_objects, - const typet *override_type = 0); - - + void gen_nondet_init( + const exprt &expr, + bool is_sub, + irep_idt class_identifier, + const source_locationt &loc, + bool skip_classid, + bool create_dynamic_objects, + const typet *override_type=0); }; // Returns false if we can't figure out the size of allocate_type. // allocate_type may differ from target_expr, e.g. for target_expr having // type int* and allocate_type being an int[10]. -exprt gen_nondet_state::allocate_object( +exprt gen_nondet_statet::allocate_object( const exprt& target_expr, const typet& allocate_type, const source_locationt &loc, @@ -89,7 +89,7 @@ exprt gen_nondet_state::allocate_object( exprt aoe=address_of_exprt(object); if(cast_needed) aoe=typecast_exprt(aoe, target_expr.type()); - code_assignt code(target_expr,aoe); + code_assignt code(target_expr, aoe); code.add_source_location()=loc; init_code.copy_to_operands(code); return aoe; @@ -102,24 +102,24 @@ exprt gen_nondet_state::allocate_object( if(allocate_type.id()!=ID_empty && !object_size.is_nil()) { // malloc expression - exprt malloc_expr = side_effect_exprt(ID_malloc); + exprt malloc_expr=side_effect_exprt(ID_malloc); malloc_expr.copy_to_operands(object_size); typet result_type=pointer_typet(allocate_type); malloc_expr.type()=result_type; // Create a symbol for the malloc expression so we can initialise // without having to do it potentially through a double-deref, which // breaks the to-SSA phase. - symbolt &malloc_sym=new_tmp_symbol(symbol_table,"malloc_site"); + symbolt &malloc_sym=new_tmp_symbol(symbol_table, "malloc_site"); malloc_sym.type=pointer_typet(allocate_type); - code_assignt assign = code_assignt(malloc_sym.symbol_expr(), malloc_expr); - code_assignt &malloc_assign = assign; - malloc_assign.add_source_location() = loc; + code_assignt assign=code_assignt(malloc_sym.symbol_expr(), malloc_expr); + code_assignt &malloc_assign=assign; + malloc_assign.add_source_location()=loc; init_code.copy_to_operands(malloc_assign); malloc_expr=malloc_sym.symbol_expr(); if(cast_needed) - malloc_expr=typecast_exprt(malloc_expr,target_expr.type()); + malloc_expr=typecast_exprt(malloc_expr, target_expr.type()); code_assignt code(target_expr, malloc_expr); - code.add_source_location() = loc; + code.add_source_location()=loc; init_code.copy_to_operands(code); return malloc_sym.symbol_expr(); } @@ -128,7 +128,7 @@ exprt gen_nondet_state::allocate_object( // make null null_pointer_exprt null_pointer_expr(to_pointer_type(target_expr.type())); code_assignt code(target_expr, null_pointer_expr); - code.add_source_location() = loc; + code.add_source_location()=loc; init_code.copy_to_operands(code); return exprt(); } @@ -136,9 +136,10 @@ exprt gen_nondet_state::allocate_object( } // Override type says to ignore the LHS' real type, and init it with the given -// type regardless. Used at the moment for reference arrays, which are implemented -// as void* arrays but should be init'd as their true type with appropriate casts. -void gen_nondet_state::gen_nondet_init( +// type regardless. Used at the moment for reference arrays, which are +// implemented as void* arrays but should be init'd as their true type with +// appropriate casts. +void gen_nondet_statet::gen_nondet_init( const exprt &expr, bool is_sub, irep_idt class_identifier, @@ -166,7 +167,7 @@ void gen_nondet_state::gen_nondet_init( // make null null_pointer_exprt null_pointer_expr(pointer_type); code_assignt code(expr, null_pointer_expr); - code.add_source_location() = loc; + code.add_source_location()=loc; init_code.copy_to_operands(code); return; @@ -181,29 +182,32 @@ void gen_nondet_state::gen_nondet_init( if(!assume_non_null) { auto returns_null_sym= - new_tmp_symbol(symbol_table,"opaque_returns_null"); + new_tmp_symbol(symbol_table, "opaque_returns_null"); returns_null_sym.type=c_bool_typet(1); auto returns_null=returns_null_sym.symbol_expr(); auto assign_returns_null= - code_assignt(returns_null,get_nondet_bool(returns_null_sym.type)); - assign_returns_null.add_source_location() = loc; + code_assignt(returns_null, get_nondet_bool(returns_null_sym.type)); + assign_returns_null.add_source_location()=loc; init_code.move_to_operands(assign_returns_null); - auto set_null_inst=code_assignt( - expr,null_pointer_exprt(pointer_type)); - set_null_inst.add_source_location() = loc; + auto set_null_inst= + code_assignt(expr, null_pointer_exprt(pointer_type)); + set_null_inst.add_source_location()=loc; std::ostringstream fresh_label_oss; fresh_label_oss<<"post_synthetic_malloc_" <<(++synthetic_constructor_count); std::string fresh_label=fresh_label_oss.str(); - set_null_label=code_labelt(fresh_label,set_null_inst); + set_null_label=code_labelt(fresh_label, set_null_inst); - init_done_label=code_labelt(fresh_label + "_init_done",code_skipt()); + init_done_label=code_labelt(fresh_label+"_init_done", code_skipt()); - code_ifthenelset null_check; - null_check.cond()=notequal_exprt( - returns_null,constant_exprt("0",returns_null_sym.type)); + code_ifthenelset + null_check; + null_check.cond()= + notequal_exprt( + returns_null, + constant_exprt("0", returns_null_sym.type)); null_check.then_case()=code_gotot(fresh_label); init_code.move_to_operands(null_check); } @@ -213,15 +217,23 @@ void gen_nondet_state::gen_nondet_init( { gen_nondet_array_init(expr, loc); } - else { - exprt allocated=allocate_object(expr,subtype,loc,create_dynamic_objects); + else + { + exprt allocated= + allocate_object(expr, subtype, loc, create_dynamic_objects); { exprt init_expr; if(allocated.id()==ID_address_of) init_expr=allocated.op0(); else - init_expr=dereference_exprt(allocated,allocated.type().subtype()); - gen_nondet_init(init_expr,false,"",loc,false,create_dynamic_objects); + init_expr=dereference_exprt(allocated, allocated.type().subtype()); + gen_nondet_init( + init_expr, + false, + "", + loc, + false, + create_dynamic_objects); } } @@ -231,7 +243,6 @@ void gen_nondet_state::gen_nondet_init( init_code.move_to_operands(set_null_label); init_code.move_to_operands(init_done_label); } - } else if(type.id()==ID_struct) { @@ -257,33 +268,38 @@ void gen_nondet_state::gen_nondet_init( if(name=="@class_identifier") { - if(skip_classid) - continue; + if(skip_classid) + continue; irep_idt qualified_clsid="java::"+as_string(class_identifier); - constant_exprt ci(qualified_clsid,string_typet()); - - code_assignt code(me, ci); - code.add_source_location() = loc; - init_code.copy_to_operands(code); + constant_exprt ci(qualified_clsid, string_typet()); + code_assignt code(me, ci); + code.add_source_location()=loc; + init_code.copy_to_operands(code); } else if(name=="@lock") { code_assignt code(me, gen_zero(me.type())); - code.add_source_location() = loc; + code.add_source_location()=loc; init_code.copy_to_operands(code); } else { assert(!name.empty()); - bool _is_sub = name[0]=='@'; + bool _is_sub=name[0]=='@'; #if 0 irep_idt _class_identifier= _is_sub?(class_identifier.empty()?struct_tag:class_identifier):""; #endif - gen_nondet_init(me, _is_sub, class_identifier, loc, false, create_dynamic_objects); + gen_nondet_init( + me, + _is_sub, + class_identifier, + loc, + false, + create_dynamic_objects); } } recursion_set.erase(struct_tag); @@ -293,116 +309,133 @@ void gen_nondet_state::gen_nondet_init( side_effect_expr_nondett se=side_effect_expr_nondett(type); code_assignt code(expr, se); - code.add_source_location() = loc; + code.add_source_location()=loc; init_code.copy_to_operands(code); } } -// Borrowed from java_bytecode_convert.cpp -- todo find a sensible place to factor this. +// Borrowed from java_bytecode_convert.cpp -- todo find a sensible place to +// factor this. static constant_exprt as_number(const mp_integer value, const typet &type) { const size_t java_int_width(type.get_unsigned_int(ID_width)); const std::string significant_bits(integer2string(value, 2)); - std::string binary_width(java_int_width - significant_bits.length(), '0'); - return constant_exprt(binary_width += significant_bits, type); + std::string binary_width(java_int_width-significant_bits.length(), '0'); + return constant_exprt(binary_width+significant_bits, type); } -void gen_nondet_state::gen_nondet_array_init(const exprt &expr, const source_locationt &loc) +void gen_nondet_statet::gen_nondet_array_init( + const exprt &expr, + const source_locationt &loc) { assert(expr.type().id()==ID_pointer); const typet &type=ns.follow(expr.type().subtype()); const struct_typet &struct_type=to_struct_type(type); - assert(expr.type().subtype().id() == ID_symbol); - const typet &element_type=static_cast(expr.type().subtype().find(ID_C_element_type)); + assert(expr.type().subtype().id()==ID_symbol); + const typet &element_type= + static_cast(expr.type().subtype().find(ID_C_element_type)); - auto max_length_expr=as_number(max_nondet_array_length,java_int_type()); + auto max_length_expr=as_number(max_nondet_array_length, java_int_type()); typet allocate_type; - symbolt &length_sym=new_tmp_symbol(symbol_table,"nondet_array_length"); + symbolt &length_sym=new_tmp_symbol(symbol_table, "nondet_array_length"); length_sym.type=java_int_type(); const auto &length_sym_expr=length_sym.symbol_expr(); // Initialise array with some undetermined length: - gen_nondet_init(length_sym_expr,false,irep_idt(),loc,false,false); + gen_nondet_init(length_sym_expr, false, irep_idt(), loc, false, false); // Insert assumptions to bound its length: - binary_relation_exprt assume1(length_sym_expr,ID_ge, - as_number(0, java_int_type())); - binary_relation_exprt assume2(length_sym_expr,ID_le, - max_length_expr); + binary_relation_exprt + assume1(length_sym_expr, ID_ge, as_number(0, java_int_type())); + binary_relation_exprt + assume2(length_sym_expr, ID_le, max_length_expr); code_assumet assume_inst1(assume1); code_assumet assume_inst2(assume2); init_code.move_to_operands(assume_inst1); init_code.move_to_operands(assume_inst2); - side_effect_exprt java_new_array(ID_java_new_array,expr.type()); + side_effect_exprt java_new_array(ID_java_new_array, expr.type()); java_new_array.copy_to_operands(length_sym_expr); - java_new_array.set("skip_initialise",true); - java_new_array.type().subtype().set(ID_C_element_type,element_type); - codet assign = code_assignt(expr,java_new_array); + java_new_array.set("skip_initialise", true); + java_new_array.type().subtype().set(ID_C_element_type, element_type); + codet assign=code_assignt(expr, java_new_array); assign.add_source_location()=loc; init_code.copy_to_operands(assign); - exprt init_array_expr=member_exprt(dereference_exprt(expr, expr.type().subtype()), - "data", struct_type.components()[2].type()); + exprt init_array_expr= + member_exprt( + dereference_exprt(expr, expr.type().subtype()), + "data", + struct_type.components()[2].type()); if(init_array_expr.type()!=pointer_typet(element_type)) - init_array_expr=typecast_exprt(init_array_expr,pointer_typet(element_type)); + init_array_expr= + typecast_exprt(init_array_expr, pointer_typet(element_type)); - // Interpose a new symbol, as the goto-symex stage can't handle array indexing via a cast. - symbolt &array_init_symbol=new_tmp_symbol(symbol_table,"array_data_init"); + // Interpose a new symbol, as the goto-symex stage can't handle array indexing + // via a cast. + symbolt &array_init_symbol=new_tmp_symbol(symbol_table, "array_data_init"); array_init_symbol.type=init_array_expr.type(); const auto &array_init_symexpr=array_init_symbol.symbol_expr(); - codet data_assign = code_assignt(array_init_symexpr,init_array_expr); - data_assign.add_source_location() = loc; + codet data_assign=code_assignt(array_init_symexpr, init_array_expr); + data_assign.add_source_location()=loc; init_code.copy_to_operands(data_assign); - // Emit init loop for(array_init_iter=0; array_init_iter!=array.length; ++array_init_iter) - // init(array[array_init_iter]); - symbolt &counter=new_tmp_symbol(symbol_table,"array_init_iter"); + // Emit init loop for(array_init_iter=0; array_init_iter!=array.length; + // ++array_init_iter) init(array[array_init_iter]); + symbolt &counter=new_tmp_symbol(symbol_table, "array_init_iter"); counter.type=length_sym_expr.type(); exprt counter_expr=counter.symbol_expr(); init_code.copy_to_operands( - code_assignt(counter_expr,as_number(0, java_int_type()))); + code_assignt(counter_expr, as_number(0, java_int_type()))); std::string head_name=as_string(counter.base_name)+"_header"; - code_labelt init_head_label(head_name,code_skipt()); + code_labelt init_head_label(head_name, code_skipt()); code_gotot goto_head(head_name); init_code.move_to_operands(init_head_label); std::string done_name=as_string(counter.base_name)+"_done"; - code_labelt init_done_label(done_name,code_skipt()); + code_labelt init_done_label(done_name, code_skipt()); code_gotot goto_done(done_name); - code_ifthenelset done_test; - done_test.cond()=equal_exprt(counter_expr,length_sym_expr); + code_ifthenelset + done_test; + done_test.cond()=equal_exprt(counter_expr, length_sym_expr); done_test.then_case()=goto_done; init_code.move_to_operands(done_test); - // Add a redundant if(counter == max_length) break that is easier for the unwinder to understand. - code_ifthenelset max_test; - max_test.cond()=equal_exprt(counter_expr,max_length_expr); + // Add a redundant if(counter == max_length) break that is easier for the + // unwinder to understand. + code_ifthenelset + max_test; + max_test.cond()=equal_exprt(counter_expr, max_length_expr); max_test.then_case()=goto_done; init_code.move_to_operands(max_test); exprt arraycellref=dereference_exprt( - plus_exprt(array_init_symexpr,counter_expr,array_init_symexpr.type()), + plus_exprt(array_init_symexpr, counter_expr, array_init_symexpr.type()), array_init_symexpr.type().subtype()); - gen_nondet_init(arraycellref,false,irep_idt(),loc,false,true, - /*override_type=*/&element_type); + gen_nondet_init( + arraycellref, + false, + irep_idt(), + loc, + false, + true, + /*override_type=*/&element_type); - code_assignt incr(counter_expr, - plus_exprt(counter_expr, - as_number(1, java_int_type()))); + code_assignt incr( + counter_expr, + plus_exprt(counter_expr, as_number(1, java_int_type()))); init_code.move_to_operands(incr); init_code.move_to_operands(goto_head); init_code.move_to_operands(init_done_label); - } @@ -424,13 +457,16 @@ void gen_nondet_init( symbol_tablet &symbol_table, const source_locationt &loc, bool skip_classid, - bool create_dynamic_objects, + bool create_dyn_objs, bool assume_non_null, size_t max_nondet_array_length) { - gen_nondet_state state(init_code,assume_non_null,max_nondet_array_length, - symbol_table); - state.gen_nondet_init(expr,false,"",loc,skip_classid,create_dynamic_objects); + gen_nondet_statet state( + init_code, + assume_non_null, + max_nondet_array_length, + symbol_table); + state.gen_nondet_init(expr, false, "", loc, skip_classid, create_dyn_objs); } /*******************************************************************\ @@ -457,7 +493,8 @@ symbolt &new_tmp_symbol(symbol_tablet &symbol_table, const std::string& prefix) new_symbol.name="tmp_object_factory$"+std::to_string(++temporary_counter); new_symbol.base_name=new_symbol.name; new_symbol.mode=ID_java; - } while(symbol_table.move(new_symbol, symbol_ptr)); + } + while(symbol_table.move(new_symbol, symbol_ptr)); return *symbol_ptr; } @@ -474,7 +511,8 @@ Function: get_nondet_bool \*******************************************************************/ -exprt get_nondet_bool(const typet& type) { +exprt get_nondet_bool(const typet& type) +{ // We force this to 0 and 1 and won't consider // other values. return typecast_exprt(side_effect_expr_nondett(bool_typet()), type); @@ -509,9 +547,15 @@ exprt object_factory( exprt object=aux_symbol.symbol_expr(); const namespacet ns(symbol_table); - gen_nondet_init(object, init_code, symbol_table, loc, - false, false, !allow_null, - max_nondet_array_length); + gen_nondet_init( + object, + init_code, + symbol_table, + loc, + false, + false, + !allow_null, + max_nondet_array_length); return object; } diff --git a/src/java_bytecode/java_object_factory.h b/src/java_bytecode/java_object_factory.h index 5e8d4417ad5..a868a2ae200 100644 --- a/src/java_bytecode/java_object_factory.h +++ b/src/java_bytecode/java_object_factory.h @@ -25,15 +25,15 @@ void gen_nondet_init( code_blockt &init_code, symbol_tablet &symbol_table, const source_locationt &, - bool skip_classid = false, - bool create_dynamic_objects = false, - bool assume_non_null = false, - size_t max_nondet_array_length = 5); + bool skip_classid=false, + bool create_dynamic_objects=false, + bool assume_non_null=false, + size_t max_nondet_array_length=5); exprt get_nondet_bool(const typet&); symbolt &new_tmp_symbol( symbol_tablet &symbol_table, - const std::string& prefix = "tmp_object_factory"); + const std::string& prefix="tmp_object_factory"); #endif // CPROVER_JAVA_BYTECODE_JAVA_OBJECT_FACTORY_H diff --git a/src/java_bytecode/java_pointer_casts.cpp b/src/java_bytecode/java_pointer_casts.cpp index 483e0287467..b8a569f55f4 100644 --- a/src/java_bytecode/java_pointer_casts.cpp +++ b/src/java_bytecode/java_pointer_casts.cpp @@ -45,13 +45,13 @@ Function: find_superclass_with_type \*******************************************************************/ -bool find_superclass_with_type(exprt &ptr,const typet &target_type, - const namespacet &ns) +bool find_superclass_with_type( + exprt &ptr, + const typet &target_type, + const namespacet &ns) { - while(true) { - const typet ptr_base=ns.follow(ptr.type().subtype()); if(ptr_base.id()!=ID_struct) @@ -65,8 +65,10 @@ bool find_superclass_with_type(exprt &ptr,const typet &target_type, const typet &first_field_type= ns.follow(base_struct.components()[0].type()); ptr=clean_deref(ptr); - ptr=member_exprt(ptr,base_struct.components()[0].get_name(), - first_field_type); + ptr=member_exprt( + ptr, + base_struct.components()[0].get_name(), + first_field_type); ptr=address_of_exprt(ptr); if(first_field_type==target_type) @@ -94,9 +96,8 @@ static const exprt& look_through_casts(const exprt& in) assert(in.type().id()==ID_pointer); return look_through_casts(in.op0()); } - else { + else return in; - } } @@ -114,12 +115,14 @@ Function: make_clean_pointer_cast \*******************************************************************/ -exprt make_clean_pointer_cast(const exprt &rawptr,const typet &target_type, - const namespacet &ns) +exprt make_clean_pointer_cast( + const exprt &rawptr, + const typet &target_type, + const namespacet &ns) { - - assert(target_type.id()==ID_pointer && - "Non-pointer target in make_clean_pointer_cast?"); + assert( + target_type.id()==ID_pointer && + "Non-pointer target in make_clean_pointer_cast?"); const exprt &ptr=look_through_casts(rawptr); @@ -128,28 +131,30 @@ exprt make_clean_pointer_cast(const exprt &rawptr,const typet &target_type, if(ptr.type().subtype()==empty_typet() || target_type.subtype()==empty_typet()) - return typecast_exprt(ptr,target_type); + return typecast_exprt(ptr, target_type); const typet &target_base=ns.follow(target_type.subtype()); exprt bare_ptr=ptr; while(bare_ptr.id()==ID_typecast) { - assert(bare_ptr.type().id()==ID_pointer && - "Non-pointer in make_clean_pointer_cast?"); + assert( + bare_ptr.type().id()==ID_pointer && + "Non-pointer in make_clean_pointer_cast?"); if(bare_ptr.type().subtype()==empty_typet()) bare_ptr=bare_ptr.op0(); } - assert(bare_ptr.type().id()==ID_pointer && - "Non-pointer in make_clean_pointer_cast?"); + assert( + bare_ptr.type().id()==ID_pointer && + "Non-pointer in make_clean_pointer_cast?"); if(bare_ptr.type()==target_type) return bare_ptr; exprt superclass_ptr=bare_ptr; - if(find_superclass_with_type(superclass_ptr,target_base,ns)) + if(find_superclass_with_type(superclass_ptr, target_base, ns)) return superclass_ptr; - return typecast_exprt(bare_ptr,target_type); + return typecast_exprt(bare_ptr, target_type); } diff --git a/src/util/json_expr.cpp b/src/util/json_expr.cpp index 5fbb4325607..4d9f7b5aa54 100644 --- a/src/util/json_expr.cpp +++ b/src/util/json_expr.cpp @@ -46,7 +46,8 @@ json_objectt json(const source_locationt &location) result["function"]=json_stringt(id2string(location.get_function())); if(!location.get_java_bytecode_index().empty()) - result["bytecode_index"]=json_stringt(id2string(location.get_java_bytecode_index())); + result["bytecode_index"]= + json_stringt(id2string(location.get_java_bytecode_index())); return result; } @@ -81,12 +82,14 @@ json_objectt json( else if(type.id()==ID_signedbv) { result["name"]=json_stringt("integer"); - result["width"]=json_numbert(std::to_string(to_signedbv_type(type).get_width())); + result["width"]= + json_numbert(std::to_string(to_signedbv_type(type).get_width())); } else if(type.id()==ID_floatbv) { result["name"]=json_stringt("float"); - result["width"]=json_numbert(std::to_string(to_floatbv_type(type).get_width())); + result["width"]= + json_numbert(std::to_string(to_floatbv_type(type).get_width())); } else if(type.id()==ID_bv) { @@ -107,7 +110,8 @@ json_objectt json( else if(type.id()==ID_fixedbv) { result["name"]=json_stringt("fixed"); - result["width"]=json_numbert(std::to_string(to_fixedbv_type(type).get_width())); + result["width"]= + json_numbert(std::to_string(to_fixedbv_type(type).get_width())); } else if(type.id()==ID_pointer) { diff --git a/src/util/source_location.cpp b/src/util/source_location.cpp index 8f8b16e3970..7583b40b496 100644 --- a/src/util/source_location.cpp +++ b/src/util/source_location.cpp @@ -35,18 +35,39 @@ std::string source_locationt::as_string(bool print_cwd) const if(!file.empty()) { - if(dest!="") dest+=' '; + if(dest!="") + dest+=' '; dest+="file "; if(print_cwd) - dest+=concat_dir_file(id2string(get_working_directory()), - id2string(file)); + dest+= + concat_dir_file(id2string(get_working_directory()), id2string(file)); else dest+=id2string(file); } - if(!line.empty()) { if(dest!="") dest+=' '; dest+="line "+id2string(line); } - if(!column.empty()) { if(dest!="") dest+=' '; dest+="column "+id2string(column); } - if(!function.empty()) { if(dest!="") dest+=' '; dest+="function "+id2string(function); } - if(!bytecode.empty()) { if(dest!="") dest+=' '; dest+="bytecode_index "+id2string(bytecode); } + if(!line.empty()) + { + if(dest!="") + dest+=' '; + dest+="line "+id2string(line); + } + if(!column.empty()) + { + if(dest!="") + dest+=' '; + dest+="column "+id2string(column); + } + if(!function.empty()) + { + if(dest!="") + dest+=' '; + dest+="function "+id2string(function); + } + if(!bytecode.empty()) + { + if(dest!="") + dest+=' '; + dest+="bytecode_index "+id2string(bytecode); + } return dest; } @@ -67,9 +88,8 @@ std::ostream &operator << ( std::ostream &out, const source_locationt &source_location) { - if(source_location.is_nil()) return out; - + if(source_location.is_nil()) + return out; out << source_location.as_string(); - return out; } diff --git a/src/util/source_location.h b/src/util/source_location.h index 83a79a8f03d..8d1e297b535 100644 --- a/src/util/source_location.h +++ b/src/util/source_location.h @@ -147,9 +147,6 @@ class source_locationt:public irept std::string as_string(bool print_cwd) const; }; -// will go away -//typedef source_locationt locationt; - std::ostream &operator <<(std::ostream &, const source_locationt &); #endif // CPROVER_UTIL_SOURCE_LOCATION_H From b651c4db4897701b4e33c7eb31cd765d13e3f2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 13 Jan 2017 23:35:20 +0100 Subject: [PATCH 17/45] take comments into account --- src/java_bytecode/expr2java.cpp | 2 +- .../java_bytecode_convert_class.cpp | 6 ++--- .../java_bytecode_convert_class.h | 2 +- .../java_bytecode_convert_method.cpp | 22 +++++++++---------- src/java_bytecode/java_bytecode_language.h | 2 +- src/java_bytecode/java_bytecode_parser.cpp | 2 +- src/java_bytecode/java_entry_point.cpp | 4 ++-- src/java_bytecode/java_types.cpp | 6 ++--- src/util/irep_ids.txt | 1 + 9 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 47e21d2f9c7..505e7425921 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -506,7 +506,7 @@ std::string expr2javat::convert( ")"; } else if(src.id()==ID_java_string_literal) - return '"'+id2string(src.get(ID_value))+'"'; // Todo: add escaping as needed + return '"'+id2string(src.get(ID_value))+'"'; // TODO: add escaping as needed else if(src.id()==ID_constant && (type.id()==ID_bool || type.id()==ID_c_bool)) { if(src.is_true()) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 295d7bfb367..320f3a95ba9 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -26,7 +26,7 @@ class java_bytecode_convert_classt:public messaget java_bytecode_convert_classt( symbol_tablet &_symbol_table, message_handlert &_message_handler, - const bool _disable_runtime_checks, + bool _disable_runtime_checks, size_t _max_array_length): messaget(_message_handler), symbol_table(_symbol_table), @@ -51,7 +51,7 @@ class java_bytecode_convert_classt:public messaget protected: symbol_tablet &symbol_table; const bool disable_runtime_checks; - size_t max_array_length; + const size_t max_array_length; // conversion void convert(const classt &c); @@ -312,7 +312,7 @@ bool java_bytecode_convert_class( const java_bytecode_parse_treet &parse_tree, symbol_tablet &symbol_table, message_handlert &message_handler, - const bool disable_runtime_checks, + bool disable_runtime_checks, size_t max_array_length) { java_bytecode_convert_classt java_bytecode_convert_class( diff --git a/src/java_bytecode/java_bytecode_convert_class.h b/src/java_bytecode/java_bytecode_convert_class.h index 264df6ca9df..ffaaf6e34da 100644 --- a/src/java_bytecode/java_bytecode_convert_class.h +++ b/src/java_bytecode/java_bytecode_convert_class.h @@ -18,7 +18,7 @@ bool java_bytecode_convert_class( const java_bytecode_parse_treet &parse_tree, symbol_tablet &symbol_table, message_handlert &message_handler, - const bool disable_runtime_checks, + bool disable_runtime_checks, size_t max_array_length); #endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_CLASS_H diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index c54f4f235f8..09d02b5dc58 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1882,12 +1882,12 @@ codet java_bytecode_convert_methodt::convert_instructions( { assert(op.empty() && results.size()==1); symbol_exprt symbol_expr(arg0.type()); - const auto& fieldname=arg0.get_string(ID_component_name); - symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+fieldname); + const auto& field_name=arg0.get_string(ID_component_name); + symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); results[0]=java_bytecode_promotion(symbol_expr); // set $assertionDisabled to false - if(fieldname.find("$assertionsDisabled")!=std::string::npos) + if(field_name.find("$assertionsDisabled")!=std::string::npos) { exprt e; e.make_false(); @@ -1903,8 +1903,8 @@ codet java_bytecode_convert_methodt::convert_instructions( { assert(op.size()==1 && results.empty()); symbol_exprt symbol_expr(arg0.type()); - const auto& fieldname=arg0.get_string(ID_component_name); - symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+fieldname); + const auto& field_name=arg0.get_string(ID_component_name); + symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); c=code_assignt(symbol_expr, op[0]); } else if(statement==patternt("?2?")) // i2c etc. @@ -1968,7 +1968,7 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!i_it->source_location.get_line().empty()) java_new_array.add_source_location()=i_it->source_location; - code_blockt checkandcreate; + code_blockt check_and_create; if(!disable_runtime_checks) { // TODO make this throw NegativeArrayIndexException instead. @@ -1978,18 +1978,18 @@ codet java_bytecode_convert_methodt::convert_instructions( check.add_source_location().set_comment("Array size < 0"); check.add_source_location() .set_property_class("array-create-negative-size"); - checkandcreate.move_to_operands(check); + check_and_create.move_to_operands(check); } if(max_array_length!=0) { constant_exprt size_limit=as_number(max_array_length, java_int_type()); binary_relation_exprt le_max_size(op[0], ID_le, size_limit); code_assumet assume_le_max_size(le_max_size); - checkandcreate.move_to_operands(assume_le_max_size); + check_and_create.move_to_operands(assume_le_max_size); } const exprt tmp=tmp_variable("newarray", ref_type); - checkandcreate.copy_to_operands(code_assignt(tmp, java_new_array)); - c=std::move(checkandcreate); + check_and_create.copy_to_operands(code_assignt(tmp, java_new_array)); + c=std::move(check_and_create); results[0]=tmp; } else if(statement=="multianewarray") @@ -2109,7 +2109,7 @@ codet java_bytecode_convert_methodt::convert_instructions( assert(op.size()==1 && results.size()==1); results[0]= - binary_predicate_exprt(op[0], "java_instanceof", arg0); + binary_predicate_exprt(op[0], ID_java_instanceof, arg0); } else if(statement=="monitorenter") { diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index dbbc945ccaf..834f6d60544 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -78,7 +78,7 @@ class java_bytecode_languaget:public languaget // - array bounds check // - array size for newarray size_t max_nondet_array_length; // maximal length for non-det array creation - size_t max_user_array_length; // max size for user supplied arrays + size_t max_user_array_length; // max size for user code created arrays }; languaget *new_java_bytecode_language(); diff --git a/src/java_bytecode/java_bytecode_parser.cpp b/src/java_bytecode/java_bytecode_parser.cpp index f2e14888d10..c025a4ad268 100644 --- a/src/java_bytecode/java_bytecode_parser.cpp +++ b/src/java_bytecode/java_bytecode_parser.cpp @@ -946,7 +946,7 @@ void java_bytecode_parsert::rbytecode( break; default: - assert(false && "unknown instruction"); + throw "unknown JVM bytecode instruction"; } bytecode_index++; } diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index e828b898d5f..ebca33adc21 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -463,7 +463,7 @@ main_function_resultt get_main_symbol( if(matches.empty()) { // Not found, silently ignore - res.main_function=symbol; + res.main_function=symbolt(); res.error_found=false; res.stop_convert=true; return res; @@ -473,7 +473,7 @@ main_function_resultt get_main_symbol( { message.error() << "main method in `" << main_class << "' is ambiguous" << messaget::eom; - res.main_function=symbol; + res.main_function=symbolt(); res.error_found=true; res.stop_convert=true; return res; // give up with error, no main diff --git a/src/java_bytecode/java_types.cpp b/src/java_bytecode/java_types.cpp index 88fc91d1587..cd3d23b22bd 100644 --- a/src/java_bytecode/java_types.cpp +++ b/src/java_bytecode/java_types.cpp @@ -7,7 +7,7 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ #include -#include +#include #include #include @@ -392,8 +392,8 @@ typet java_type_from_string(const std::string &src) const typet subtype=java_type_from_string(src.substr(1, std::string::npos)); if(subtype_letter=='L' || // [L denotes a reference array of some sort. subtype_letter=='[') // Array-of-arrays - subtype_letter='A'; - typet tmp=java_array_type((char)tolower(subtype_letter)); + subtype_letter='A'; + typet tmp=java_array_type(std::tolower(subtype_letter)); tmp.subtype().set(ID_C_element_type, subtype); return tmp; } diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index 95cb32a2480..e6f70ccbf37 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -734,3 +734,4 @@ low high bswap java_bytecode_index +java_instanceof From 2b23e3602d2e3f6dd68a9ade72685a69ba17fa63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sun, 15 Jan 2017 21:35:04 +0100 Subject: [PATCH 18/45] fix linter warnings after rebase --- .../java_bytecode_convert_method.cpp | 51 ++++++++++--------- src/java_bytecode/java_object_factory.cpp | 14 +++-- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 09d02b5dc58..f92208a1d8f 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1017,11 +1017,9 @@ codet java_bytecode_convert_methodt::convert_instructions( i_it!=instructions.end(); i_it++) { + converted_instructiont ins=converted_instructiont(i_it, code_skipt()); std::pair a_entry= - address_map.insert( - std::make_pair( - i_it->address, - converted_instructiont(i_it, code_skipt()))); + address_map.insert(std::make_pair(i_it->address, ins)); assert(a_entry.second); // addresses are strictly increasing, hence we must have inserted // a new maximal key @@ -1060,7 +1058,9 @@ codet java_bytecode_convert_methodt::convert_instructions( i_it->statement=="jsr_w") { instructionst::const_iterator next=i_it; - assert(++next!=instructions.end() && "jsr without valid return address?"); + assert( + ++next!=instructions.end() && + "jsr without valid return address?"); targets.insert(next->address); jsr_ret_targets.push_back(next->address); } @@ -1088,12 +1088,11 @@ codet java_bytecode_convert_methodt::convert_instructions( } } - // Draw edges from every `ret` to every `jsr` successor. - // Could do better with flow analysis to distinguish multiple subroutines within - // the same function. + // Draw edges from every `ret` to every `jsr` successor. Could do better with + // flow analysis to distinguish multiple subroutines within the same function. for(const auto retinst : ret_instructions) { - auto& a_entry=address_map.at(retinst->address); + auto &a_entry=address_map.at(retinst->address); a_entry.successors.insert( a_entry.successors.end(), jsr_ret_targets.begin(), @@ -1529,7 +1528,8 @@ codet java_bytecode_convert_methodt::convert_instructions( branches.move_to_operands(g); else { - code_ifthenelset branch; + code_ifthenelset + branch; auto address_ptr=as_number( jsr_ret_targets[idx], pointer_typet(void_typet(), 64)); @@ -1558,9 +1558,8 @@ codet java_bytecode_convert_methodt::convert_instructions( if(is_double || is_float) { const ieee_float_spect spec( - is_float? - ieee_float_spect::single_precision(): - ieee_float_spect::double_precision()); + is_float?ieee_float_spect::single_precision(): + ieee_float_spect::double_precision()); ieee_floatt value(spec); const typet &arg_type(arg0.type()); @@ -1752,15 +1751,19 @@ codet java_bytecode_convert_methodt::convert_instructions( // 1 if op[0] is greater than op[1] const typet t=java_int_type(); + exprt one=from_integer(1, t); + exprt minus_one=from_integer(-1, t); + + if_exprt greater=if_exprt( + binary_relation_exprt(op[0], ID_gt, op[1]), + one, + minus_one); results[0]= if_exprt( binary_relation_exprt(op[0], ID_equal, op[1]), gen_zero(t), - if_exprt( - binary_relation_exprt(op[0], ID_gt, op[1]), - from_integer(1, t), - from_integer(-1, t))); + greater); } else if(statement==patternt("?cmp?")) { @@ -1779,19 +1782,21 @@ codet java_bytecode_convert_methodt::convert_instructions( // (value1 == NaN || value2 == NaN) ? // nan_value : value1 == value2 ? 0 : value1 < value2 -1 ? 1 : 0; + exprt nan_op0=ieee_float_equal_exprt(nan_expr, op[0]); + exprt nan_op1=ieee_float_equal_exprt(nan_expr, op[1]); + exprt one=from_integer(1, result_type); + exprt minus_one=from_integer(-1, result_type); results[0]= if_exprt( - or_exprt( - ieee_float_equal_exprt(nan_expr, op[0]), - ieee_float_equal_exprt(nan_expr, op[1])), + or_exprt(nan_op0, nan_op1), nan_result, if_exprt( ieee_float_equal_exprt(op[0], op[1]), gen_zero(result_type), if_exprt( binary_relation_exprt(op[0], ID_lt, op[1]), - from_integer(-1, result_type), - from_integer(1, result_type)))); + minus_one, + one))); } else if(statement==patternt("?cmpl")) { @@ -2200,7 +2205,7 @@ codet java_bytecode_convert_methodt::convert_instructions( else { c.make_block(); - auto& last_statement=to_code_block(c).find_last_statement(); + auto &last_statement=to_code_block(c).find_last_statement(); if(last_statement.get_statement()==ID_goto) { // Insert stack twiddling before branch: diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 2935a411dd1..c63288efc6f 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -204,10 +204,9 @@ void gen_nondet_statet::gen_nondet_init( code_ifthenelset null_check; + exprt null_return=constant_exprt("0", returns_null_sym.type); null_check.cond()= - notequal_exprt( - returns_null, - constant_exprt("0", returns_null_sym.type)); + notequal_exprt(returns_null, null_return); null_check.then_case()=code_gotot(fresh_label); init_code.move_to_operands(null_check); } @@ -387,8 +386,8 @@ void gen_nondet_statet::gen_nondet_array_init( counter.type=length_sym_expr.type(); exprt counter_expr=counter.symbol_expr(); - init_code.copy_to_operands( - code_assignt(counter_expr, as_number(0, java_int_type()))); + exprt java_zero=as_number(0, java_int_type()); + init_code.copy_to_operands(code_assignt(counter_expr, java_zero)); std::string head_name=as_string(counter.base_name)+"_header"; code_labelt init_head_label(head_name, code_skipt()); @@ -429,9 +428,8 @@ void gen_nondet_statet::gen_nondet_array_init( true, /*override_type=*/&element_type); - code_assignt incr( - counter_expr, - plus_exprt(counter_expr, as_number(1, java_int_type()))); + exprt java_one=as_number(1, java_int_type()); + code_assignt incr(counter_expr, plus_exprt(counter_expr, java_one)); init_code.move_to_operands(incr); init_code.move_to_operands(goto_head); From 360ff4d3345168d61245450f2ec309803af92436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sun, 15 Jan 2017 22:07:57 +0100 Subject: [PATCH 19/45] remove static method is_string_array --- src/java_bytecode/java_entry_point.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index ebca33adc21..09fff0cc4de 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -179,12 +179,6 @@ bool java_static_lifetime_init( return false; } -static bool is_string_array(const typet& t) -{ - typet compare_to=java_type_from_string("[Ljava.lang.String;"); - return full_eq(t, compare_to); -} - /*******************************************************************\ Function: java_build_arguments @@ -221,11 +215,13 @@ exprt::operandst java_build_arguments( if(!is_main) { bool named_main=has_suffix(config.main, ".main"); + const typet &string_array_type= + java_type_from_string("[Ljava.lang.String;"); bool has_correct_type= to_code_type(function.type).return_type().id()==ID_empty && (!to_code_type(function.type).has_this()) && parameters.size()==1 && - is_string_array(parameters[0].type()); + full_eq(parameters[0].type(), string_array_type); is_main=(named_main && has_correct_type); } From 608c5e3dec75ea06bb493234ab9b318d29d3c009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sun, 15 Jan 2017 22:15:13 +0100 Subject: [PATCH 20/45] take comments into account --- .../java_bytecode_convert_method.cpp | 31 ++++++++++++------- src/java_bytecode/java_entry_point.cpp | 2 +- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index f92208a1d8f..d84fdba79d9 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -108,6 +108,11 @@ class java_bytecode_convert_methodt:public messaget INST_INDEX_CONST=3 } instruction_sizet; + codet get_array_bounds_check( + const exprt &arraystruct, + const exprt &idx, + const source_locationt& original_sloc); + // return corresponding reference of variable const variablet &find_variable_for_slot( size_t address, @@ -672,7 +677,7 @@ static member_exprt to_member(const exprt &pointer, const exprt &fieldref) fieldref.type()); } -codet get_array_bounds_check( +codet java_bytecode_convert_methodt::get_array_bounds_check( const exprt &arraystruct, const exprt &idx, const source_locationt& original_sloc) @@ -681,22 +686,24 @@ codet get_array_bounds_check( binary_relation_exprt gezero(idx, ID_ge, intzero); const member_exprt length_field(arraystruct, "length", java_int_type()); binary_relation_exprt ltlength(idx, ID_lt, length_field); - code_blockt boundschecks; - boundschecks.add(code_assertt(gezero)); - boundschecks.operands().back().add_source_location()=original_sloc; - boundschecks.operands().back().add_source_location() + code_blockt bounds_checks; + + bounds_checks.add(code_assertt(gezero)); + bounds_checks.operands().back().add_source_location()=original_sloc; + bounds_checks.operands().back().add_source_location() .set_comment("Array index < 0"); - boundschecks.operands().back().add_source_location() + bounds_checks.operands().back().add_source_location() .set_property_class("array-index-oob-low"); - boundschecks.add(code_assertt(ltlength)); - boundschecks.operands().back().add_source_location()=original_sloc; - boundschecks.operands().back().add_source_location() + bounds_checks.add(code_assertt(ltlength)); + + bounds_checks.operands().back().add_source_location()=original_sloc; + bounds_checks.operands().back().add_source_location() .set_comment("Array index >= length"); - boundschecks.operands().back().add_source_location() + bounds_checks.operands().back().add_source_location() .set_property_class("array-index-oob-high"); // TODO make this throw ArrayIndexOutOfBoundsException instead of asserting. - return boundschecks; + return bounds_checks; } /*******************************************************************\ @@ -1235,7 +1242,7 @@ codet java_bytecode_convert_methodt::convert_instructions( { // Remember that this is triggered by an assertion if(statement=="invokespecial" && - as_string(arg0.get(ID_identifier)) + id2string(arg0.get(ID_identifier)) .find("AssertionError")!=std::string::npos) { assertion_failure=true; diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index 09fff0cc4de..3d525d78060 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -210,7 +210,7 @@ exprt::operandst java_build_arguments( { bool is_this=(param_number==0) && parameters[param_number].get_this(); - bool is_default_entry_point=config.main==""; + bool is_default_entry_point(config.main==""); bool is_main=is_default_entry_point; if(!is_main) { From 6d9a350ef55f415e9135f66c8edc24d80587989e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 20 Jan 2017 15:33:39 +0100 Subject: [PATCH 21/45] remove cast_if_necessary --- .../java_bytecode_convert_method.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index d84fdba79d9..896a4726fa7 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -317,23 +317,13 @@ static size_t get_variable_slots(const code_typet::parametert ¶m) return count_slots(0, param); } -static bool is_constructor(const class_typet::methodt &method) +bool is_constructor(const class_typet::methodt &method) { const std::string &name(id2string(method.get_name())); const std::string::size_type &npos(std::string::npos); return npos!=name.find("") || npos!=name.find(""); } -static void cast_if_necessary(binary_relation_exprt &condition) -{ - exprt &lhs(condition.lhs()); - exprt &rhs(condition.rhs()); - const typet &lhs_type(lhs.type()); - if(lhs_type==rhs.type()) - return; - rhs=typecast_exprt(rhs, lhs_type); -} - static irep_idt strip_java_namespace_prefix(const irep_idt to_strip) { const auto to_strip_str=id2string(to_strip); @@ -1600,7 +1590,12 @@ codet java_bytecode_convert_methodt::convert_instructions( binary_relation_exprt condition(op[0], cmp_op, op[1]); - cast_if_necessary(condition); + exprt &lhs(condition.lhs()); + exprt &rhs(condition.rhs()); + const typet &lhs_type(lhs.type()); + if(lhs_type!=rhs.type()) + rhs=typecast_exprt(rhs, lhs_type); + code_branch.cond()=condition; code_branch.cond().add_source_location()=i_it->source_location; code_branch.then_case()=code_gotot(label(number)); From 67f40196a0f206b0eabbef7081f33afa7f2fca1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 20 Jan 2017 15:21:27 +0100 Subject: [PATCH 22/45] is_constructor and is_virtual as class methods --- .../java_bytecode_convert_method.cpp | 395 ++++-------------- .../java_bytecode_convert_method_class.h | 34 +- src/java_bytecode/java_bytecode_vtable.cpp | 13 +- 3 files changed, 110 insertions(+), 332 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 896a4726fa7..0d1b432b649 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -55,253 +55,6 @@ class patternt const char *p; }; -class java_bytecode_convert_methodt:public messaget -{ -public: - java_bytecode_convert_methodt( - symbol_tablet &_symbol_table, - message_handlert &_message_handler, - bool _disable_runtime_checks, - size_t _max_array_length): - messaget(_message_handler), - symbol_table(_symbol_table), - disable_runtime_checks(_disable_runtime_checks), - max_array_length(_max_array_length) - { - } - - typedef java_bytecode_parse_treet::methodt methodt; - typedef java_bytecode_parse_treet::instructiont instructiont; - typedef methodt::instructionst instructionst; - - void operator()(const symbolt &class_symbol, const methodt &method) - { - convert(class_symbol, method); - } - -protected: - symbol_tablet &symbol_table; - const bool disable_runtime_checks; - size_t max_array_length; - - irep_idt method_id; - irep_idt current_method; - typet method_return_type; - - class variablet - { - public: - symbol_exprt symbol_expr; - size_t start_pc; - size_t length; - bool is_parameter=false; - }; - - typedef std::vector variablest; - expanding_vector variables; - std::set used_local_names; - bool method_has_this; - - typedef enum instruction_sizet - { - INST_INDEX=2, - INST_INDEX_CONST=3 - } instruction_sizet; - - codet get_array_bounds_check( - const exprt &arraystruct, - const exprt &idx, - const source_locationt& original_sloc); - - // return corresponding reference of variable - const variablet &find_variable_for_slot( - size_t address, - variablest &var_list, - instruction_sizet inst_size) - { - for(const variablet &var : var_list) - { - size_t start_pc=var.start_pc; - size_t length=var.length; - if(address+(size_t)inst_size>=start_pc && - address::max(); - return var_list[list_length]; - } - - // JVM local variables - enum variable_cast_argumentt - { - CAST_AS_NEEDED, - NO_CAST - }; - - const exprt variable( - const exprt &arg, - char type_char, - size_t address, - instruction_sizet inst_size, - variable_cast_argumentt do_cast) - { - irep_idt number=to_constant_expr(arg).get_value(); - - std::size_t number_int=safe_string2size_t(id2string(number)); - typet t=java_type_from_char(type_char); - variablest &var_list=variables[number_int]; - - // search variable in list for correct frame / address if necessary - const variablet &var= - find_variable_for_slot(address, var_list, inst_size); - - if(var.symbol_expr.get_identifier().empty()) - { - // an un-named local variable - irep_idt base_name="anonlocal::"+id2string(number)+type_char; - irep_idt identifier=id2string(current_method)+"::"+id2string(base_name); - - symbol_exprt result(identifier, t); - result.set(ID_C_base_name, base_name); - used_local_names.insert(result); - - return result; - } - else - { - exprt result=var.symbol_expr; - if(!var.is_parameter) - used_local_names.insert(to_symbol_expr(result)); - if(do_cast==CAST_AS_NEEDED && t!=result.type()) - result=typecast_exprt(result, t); - return result; - } - } - - // temporary variables - std::list tmp_vars; - - symbol_exprt tmp_variable(const std::string &prefix, const typet &type) - { - irep_idt base_name=prefix+"_tmp"+std::to_string(tmp_vars.size()); - irep_idt identifier=id2string(current_method)+"::"+id2string(base_name); - - auxiliary_symbolt tmp_symbol; - tmp_symbol.base_name=base_name; - tmp_symbol.is_static_lifetime=false; - tmp_symbol.mode=ID_java; - tmp_symbol.name=identifier; - tmp_symbol.type=type; - symbol_table.add(tmp_symbol); - - symbol_exprt result(identifier, type); - result.set(ID_C_base_name, base_name); - tmp_vars.push_back(result); - - return result; - } - - // JVM program locations - irep_idt label(const irep_idt &address) - { - return "pc"+id2string(address); - } - - // JVM Stack - typedef std::vector stackt; - stackt stack; - - exprt::operandst pop(std::size_t n) - { - if(stack.size() successors; - std::set predecessors; - codet code; - stackt stack; - bool done; - }; - - typedef std::map address_mapt; - - struct block_tree_nodet - { - bool leaf; - std::vector branch_addresses; - std::vector branch; - block_tree_nodet():leaf(false) {} - explicit block_tree_nodet(bool l):leaf(l) {} - static block_tree_nodet get_leaf() { return block_tree_nodet(true); } - }; - - static void replace_goto_target( - codet &repl, - const irep_idt &old_label, - const irep_idt &new_label); - - code_blockt &get_block_for_pcrange( - block_tree_nodet &tree, - code_blockt &this_block, - unsigned address_start, - unsigned address_limit, - unsigned next_block_start_address); - - code_blockt &get_or_create_block_for_pcrange( - block_tree_nodet &tree, - code_blockt &this_block, - unsigned address_start, - unsigned address_limit, - unsigned next_block_start_address, - const address_mapt &amap, - bool allow_merge=true); - - // conversion - void convert(const symbolt &class_symbol, const methodt &); - void convert(const instructiont &); - - codet convert_instructions( - const instructionst &, - const code_typet &); - - const bytecode_infot &get_bytecode_info(const irep_idt &statement); -}; - const size_t SLOTS_PER_INTEGER(1u); const size_t INTEGER_WIDTH(64u); static size_t count_slots( @@ -317,13 +70,6 @@ static size_t get_variable_slots(const code_typet::parametert ¶m) return count_slots(0, param); } -bool is_constructor(const class_typet::methodt &method) -{ - const std::string &name(id2string(method.get_name())); - const std::string::size_type &npos(std::string::npos); - return npos!=name.find("") || npos!=name.find(""); -} - static irep_idt strip_java_namespace_prefix(const irep_idt to_strip) { const auto to_strip_str=id2string(to_strip); @@ -331,47 +77,44 @@ static irep_idt strip_java_namespace_prefix(const irep_idt to_strip) return to_strip_str.substr(6, std::string::npos); } -java_bytecode_convert_methodt::java_bytecode_convert_methodt( - symbol_tablet &_symbol_table, - message_handlert &_message_handler) : - messaget(_message_handler), - symbol_table(_symbol_table) +// name contains or +bool java_bytecode_convert_methodt::is_constructor( + const class_typet::methodt &method) { + const std::string &name(id2string(method.get_name())); + const std::string::size_type &npos(std::string::npos); + return npos!=name.find("") || npos!=name.find(""); } -const exprt java_bytecode_convert_methodt::variable( - const exprt &arg, - char type_char, - size_t address, - variable_cast_argumentt do_cast) +exprt::operandst java_bytecode_convert_methodt::pop(std::size_t n) { - irep_idt number=to_constant_expr(arg).get_value(); + if(stack.size() working_set; bool assertion_failure=false; @@ -1405,7 +1154,7 @@ codet java_bytecode_convert_methodt::convert_instructions( assert(op.size()==1 && results.empty()); exprt var= - variable(arg0, statement[0], i_it->address, INST_INDEX, NO_CAST); + variable(arg0, statement[0], i_it->address, NO_CAST); exprt toassign=op[0]; if('a'==statement[0] && toassign.type()!=var.type()) @@ -1446,7 +1195,7 @@ codet java_bytecode_convert_methodt::convert_instructions( { // load a value from a local variable results[0]= - variable(arg0, statement[0], i_it->address, INST_INDEX, CAST_AS_NEEDED); + variable(arg0, statement[0], i_it->address, CAST_AS_NEEDED); } else if(statement=="ldc" || statement=="ldc_w" || statement=="ldc2" || statement=="ldc2_w") @@ -1666,7 +1415,7 @@ codet java_bytecode_convert_methodt::convert_instructions( { code_assignt code_assign; code_assign.lhs()= - variable(arg0, 'i', i_it->address, INST_INDEX_CONST, NO_CAST); + variable(arg0, 'i', i_it->address, NO_CAST); code_assign.rhs()=plus_exprt( variable(arg0, 'i', i_it->address, CAST_AS_NEEDED), typecast_exprt(arg1, java_int_type())); @@ -2021,17 +1770,19 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!disable_runtime_checks) { // TODO make this throw NegativeArrayIndexException instead. - constant_exprt intzero=as_number(0,java_int_type()); - binary_relation_exprt gezero(op[0],ID_ge,intzero); + constant_exprt intzero=as_number(0, java_int_type()); + binary_relation_exprt gezero(op[0], ID_ge, intzero); code_assertt check(gezero); check.add_source_location().set_comment("Array size < 0"); - check.add_source_location().set_property_class("array-create-negative-size"); + check.add_source_location() + .set_property_class("array-create-negative-size"); checkandcreate.move_to_operands(check); if(max_array_length!=0) { - constant_exprt size_limit=as_number(max_array_length,java_int_type()); - binary_relation_exprt le_max_size(op[0],ID_le,size_limit); + constant_exprt size_limit= + as_number(max_array_length, java_int_type()); + binary_relation_exprt le_max_size(op[0], ID_le, size_limit); code_assumet assume_le_max_size(le_max_size); checkandcreate.move_to_operands(assume_le_max_size); } diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index 003492355d1..d961a7131be 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -27,7 +27,15 @@ class java_bytecode_convert_methodt:public messaget public: java_bytecode_convert_methodt( symbol_tablet &_symbol_table, - message_handlert &_message_handler); + message_handlert &_message_handler, + bool _disable_runtime_checks, + size_t _max_array_length): + messaget(_message_handler), + symbol_table(_symbol_table), + disable_runtime_checks(_disable_runtime_checks), + max_array_length(_max_array_length) + { + } typedef java_bytecode_parse_treet::methodt methodt; typedef java_bytecode_parse_treet::instructiont instructiont; @@ -41,9 +49,11 @@ class java_bytecode_convert_methodt:public messaget } protected: - irep_idt method_id; symbol_tablet &symbol_table; + const bool disable_runtime_checks; + size_t max_array_length; + irep_idt method_id; irep_idt current_method; typet method_return_type; @@ -80,8 +90,21 @@ class java_bytecode_convert_methodt:public messaget std::set used_local_names; bool method_has_this; + typedef enum instruction_sizet + { + INST_INDEX=2, + INST_INDEX_CONST=3 + } instruction_sizet; + + codet get_array_bounds_check( + const exprt &arraystruct, + const exprt &idx, + const source_locationt& original_sloc); + // return corresponding reference of variable - const variablet &find_variable_for_slot(size_t address, variablest &var_list); + const variablet &find_variable_for_slot( + size_t address, + variablest &var_list); // JVM local variables enum variable_cast_argumentt @@ -112,6 +135,8 @@ class java_bytecode_convert_methodt:public messaget void push(const exprt::operandst &o); + bool is_constructor(const class_typet::methodt &method); + struct converted_instructiont { converted_instructiont( @@ -129,7 +154,7 @@ class java_bytecode_convert_methodt:public messaget public: typedef std::map address_mapt; - typedef std::pair method_with_amapt; + typedef std::pair method_with_amapt; typedef cfg_dominators_templatet java_cfg_dominatorst; @@ -180,7 +205,6 @@ class java_bytecode_convert_methodt:public messaget // conversion void convert(const symbolt &class_symbol, const methodt &); - void convert(const instructiont &); codet convert_instructions( const methodt &, diff --git a/src/java_bytecode/java_bytecode_vtable.cpp b/src/java_bytecode/java_bytecode_vtable.cpp index 5be6e9a751b..1af016870f9 100644 --- a/src/java_bytecode/java_bytecode_vtable.cpp +++ b/src/java_bytecode/java_bytecode_vtable.cpp @@ -16,11 +16,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -namespace { -bool is_virtual(const class_typet::methodt &method) { - return method.get_bool(ID_is_virtual) - && !method.get_bool(ID_constructor); -} +namespace +{ const char ID_virtual_name[] = "virtual_name"; @@ -154,6 +151,12 @@ class java_bytecode_vtable_factoryt } } + bool is_virtual(const class_typet::methodt &method) + { + return method.get_bool(ID_is_virtual) + && !method.get_bool(ID_constructor); + } + void create_base_vtable_entries( struct_exprt &vtable_value, const class_typet &class_type, From ceea4b761b33de9b969e8fd50e42f0e29dfcd076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sun, 15 Jan 2017 23:00:09 +0100 Subject: [PATCH 23/45] make param const reference in clean_deref --- src/java_bytecode/java_pointer_casts.cpp | 2 +- src/java_bytecode/java_pointer_casts.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java_bytecode/java_pointer_casts.cpp b/src/java_bytecode/java_pointer_casts.cpp index b8a569f55f4..74587ccabe7 100644 --- a/src/java_bytecode/java_pointer_casts.cpp +++ b/src/java_bytecode/java_pointer_casts.cpp @@ -24,7 +24,7 @@ Function: clean_deref \*******************************************************************/ -exprt clean_deref(const exprt ptr) +exprt clean_deref(const exprt &ptr) { return ptr.id()==ID_address_of ? ptr.op0() diff --git a/src/java_bytecode/java_pointer_casts.h b/src/java_bytecode/java_pointer_casts.h index c07492b3db2..3e0bd6c53d5 100644 --- a/src/java_bytecode/java_pointer_casts.h +++ b/src/java_bytecode/java_pointer_casts.h @@ -9,7 +9,7 @@ Author: DiffBlue #ifndef CPROVER_JAVA_BYTECODE_JAVA_POINTER_CASTS_H #define CPROVER_JAVA_BYTECODE_JAVA_POINTER_CASTS_H -exprt clean_deref(const exprt ptr); +exprt clean_deref(const exprt &ptr); bool find_superclass_with_type( exprt &ptr, From 4bf1e4af70da6a5b8fc902b4edc8f4a1f5e59d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sun, 15 Jan 2017 23:19:08 +0100 Subject: [PATCH 24/45] irep ID_java_super_method_call --- src/java_bytecode/java_bytecode_convert_method.cpp | 2 +- src/util/irep_ids.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 0d1b432b649..bc17d4b1581 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1007,7 +1007,7 @@ codet java_bytecode_convert_methodt::convert_instructions( .find("")!=std::string::npos) code_type.set(ID_constructor, true); else - code_type.set("java_super_method_call", true); + code_type.set(ID_java_super_method_call, true); } pointer_typet object_ref_type(thistype); code_typet::parametert this_p(object_ref_type); diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index e6f70ccbf37..e320f329ecf 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -735,3 +735,4 @@ high bswap java_bytecode_index java_instanceof +java_super_method_call From a358515d16eb310840382691bfc20f0e926b628b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sun, 15 Jan 2017 23:34:54 +0100 Subject: [PATCH 25/45] comments for java object factory --- src/java_bytecode/java_object_factory.cpp | 34 +++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index c63288efc6f..7ca08d6885e 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -32,7 +32,7 @@ Function: gen_nondet_init \*******************************************************************/ -class gen_nondet_statet +class java_object_factoryt { code_blockt &init_code; std::set recursion_set; @@ -42,12 +42,16 @@ class gen_nondet_statet namespacet ns; public: - gen_nondet_statet(code_blockt& ic, bool ann, size_t mnal, symbol_tablet& st) : - init_code(ic), - assume_non_null(ann), - max_nondet_array_length(mnal), - symbol_table(st), - ns(st) {} + java_object_factoryt( + code_blockt& _init_code, + bool _assume_non_null, + size_t _max_nondet_array_length, + symbol_tablet& _symbol_table) : + init_code(_init_code), + assume_non_null(_assume_non_null), + max_nondet_array_length(_max_nondet_array_length), + symbol_table(_symbol_table), + ns(_symbol_table) {} exprt allocate_object( const exprt&, @@ -70,7 +74,7 @@ class gen_nondet_statet // Returns false if we can't figure out the size of allocate_type. // allocate_type may differ from target_expr, e.g. for target_expr having // type int* and allocate_type being an int[10]. -exprt gen_nondet_statet::allocate_object( +exprt java_object_factoryt::allocate_object( const exprt& target_expr, const typet& allocate_type, const source_locationt &loc, @@ -106,7 +110,7 @@ exprt gen_nondet_statet::allocate_object( malloc_expr.copy_to_operands(object_size); typet result_type=pointer_typet(allocate_type); malloc_expr.type()=result_type; - // Create a symbol for the malloc expression so we can initialise + // Create a symbol for the malloc expression so we can initialize // without having to do it potentially through a double-deref, which // breaks the to-SSA phase. symbolt &malloc_sym=new_tmp_symbol(symbol_table, "malloc_site"); @@ -139,7 +143,7 @@ exprt gen_nondet_statet::allocate_object( // type regardless. Used at the moment for reference arrays, which are // implemented as void* arrays but should be init'd as their true type with // appropriate casts. -void gen_nondet_statet::gen_nondet_init( +void java_object_factoryt::gen_nondet_init( const exprt &expr, bool is_sub, irep_idt class_identifier, @@ -177,7 +181,7 @@ void gen_nondet_statet::gen_nondet_init( code_labelt set_null_label; code_labelt init_done_label; - static unsigned long synthetic_constructor_count=0; + static size_t synthetic_constructor_count=0; if(!assume_non_null) { @@ -323,7 +327,7 @@ static constant_exprt as_number(const mp_integer value, const typet &type) return constant_exprt(binary_width+significant_bits, type); } -void gen_nondet_statet::gen_nondet_array_init( +void java_object_factoryt::gen_nondet_array_init( const exprt &expr, const source_locationt &loc) { @@ -341,7 +345,7 @@ void gen_nondet_statet::gen_nondet_array_init( length_sym.type=java_int_type(); const auto &length_sym_expr=length_sym.symbol_expr(); - // Initialise array with some undetermined length: + // Initialize array with some undetermined length: gen_nondet_init(length_sym_expr, false, irep_idt(), loc, false, false); // Insert assumptions to bound its length: @@ -356,7 +360,7 @@ void gen_nondet_statet::gen_nondet_array_init( side_effect_exprt java_new_array(ID_java_new_array, expr.type()); java_new_array.copy_to_operands(length_sym_expr); - java_new_array.set("skip_initialise", true); + java_new_array.set("skip_initialize", true); java_new_array.type().subtype().set(ID_C_element_type, element_type); codet assign=code_assignt(expr, java_new_array); assign.add_source_location()=loc; @@ -459,7 +463,7 @@ void gen_nondet_init( bool assume_non_null, size_t max_nondet_array_length) { - gen_nondet_statet state( + java_object_factoryt state( init_code, assume_non_null, max_nondet_array_length, From f54bbc2b2ff720a01596c7e7e6d6b726a03277e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sun, 15 Jan 2017 23:58:37 +0100 Subject: [PATCH 26/45] documentation block gen_nondeet_array_init --- src/java_bytecode/java_object_factory.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 7ca08d6885e..76169197eeb 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -327,6 +327,20 @@ static constant_exprt as_number(const mp_integer value, const typet &type) return constant_exprt(binary_width+significant_bits, type); } +/*******************************************************************\ + +Function: gen_nondet_array_init + + Inputs: + + Outputs: + + Purpose: create code to initialize a Java array with size + `max_nondet_array_length`, loop over elements and initialize + them + +\*******************************************************************/ + void java_object_factoryt::gen_nondet_array_init( const exprt &expr, const source_locationt &loc) From 371f92f395313cc0f1b9beb170223f5e713a7511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 16 Jan 2017 00:23:23 +0100 Subject: [PATCH 27/45] remove default values from object factory --- src/java_bytecode/java_object_factory.cpp | 2 +- src/java_bytecode/java_object_factory.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 76169197eeb..f9a620ede7c 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -444,7 +444,7 @@ void java_object_factoryt::gen_nondet_array_init( loc, false, true, - /*override_type=*/&element_type); + &element_type); exprt java_one=as_number(1, java_int_type()); code_assignt incr(counter_expr, plus_exprt(counter_expr, java_one)); diff --git a/src/java_bytecode/java_object_factory.h b/src/java_bytecode/java_object_factory.h index a868a2ae200..7807e176749 100644 --- a/src/java_bytecode/java_object_factory.h +++ b/src/java_bytecode/java_object_factory.h @@ -25,9 +25,9 @@ void gen_nondet_init( code_blockt &init_code, symbol_tablet &symbol_table, const source_locationt &, - bool skip_classid=false, - bool create_dynamic_objects=false, - bool assume_non_null=false, + bool skip_classid, + bool create_dynamic_objects, + bool assume_non_null, size_t max_nondet_array_length=5); exprt get_nondet_bool(const typet&); From b4ac05cd7d07af6863f24ce7b49402ab9c259a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 17 Jan 2017 11:02:25 +0100 Subject: [PATCH 28/45] export as_number to java_utils.cpp --- src/java_bytecode/Makefile | 2 +- .../java_bytecode_convert_method.cpp | 18 +++++------------ src/java_bytecode/java_object_factory.cpp | 11 +--------- src/java_bytecode/java_utils.cpp | 20 +++++++++++++++++++ src/java_bytecode/java_utils.h | 18 +++++++++++++++++ 5 files changed, 45 insertions(+), 24 deletions(-) create mode 100644 src/java_bytecode/java_utils.cpp create mode 100644 src/java_bytecode/java_utils.h diff --git a/src/java_bytecode/Makefile b/src/java_bytecode/Makefile index 66ad1003cac..e27bc3e038d 100644 --- a/src/java_bytecode/Makefile +++ b/src/java_bytecode/Makefile @@ -6,7 +6,7 @@ SRC = java_bytecode_language.cpp java_bytecode_parse_tree.cpp \ java_root_class.cpp java_bytecode_parser.cpp bytecode_info.cpp \ java_class_loader.cpp jar_file.cpp java_object_factory.cpp \ java_bytecode_convert_method.cpp java_local_variable_table.cpp \ - java_pointer_casts.cpp + java_pointer_casts.cpp java_utils.cpp INCLUDES= -I .. diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index bc17d4b1581..13656b3d028 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -26,6 +26,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_bytecode_convert_method_class.h" #include "bytecode_info.h" #include "java_types.h" +#include "java_utils.h" #include #include @@ -394,14 +395,6 @@ static irep_idt get_if_cmp_operator(const irep_idt &stmt) throw "unhandled java comparison instruction"; } -static constant_exprt as_number(const mp_integer value, const typet &type) -{ - const std::size_t java_int_width(type.get_unsigned_int(ID_width)); - const std::string significant_bits(integer2string(value, 2)); - std::string binary_width(java_int_width-significant_bits.length(), '0'); - return constant_exprt(binary_width+=significant_bits, type); -} - static member_exprt to_member(const exprt &pointer, const exprt &fieldref) { symbol_typet class_type(fieldref.get(ID_class)); @@ -1724,7 +1717,7 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!i_it->source_location.get_line().empty()) java_new_array.add_source_location()=i_it->source_location; - code_blockt check_and_create; + c=code_blockt(); if(!disable_runtime_checks) { // TODO make this throw NegativeArrayIndexException instead. @@ -1734,18 +1727,17 @@ codet java_bytecode_convert_methodt::convert_instructions( check.add_source_location().set_comment("Array size < 0"); check.add_source_location() .set_property_class("array-create-negative-size"); - check_and_create.move_to_operands(check); + c.move_to_operands(check); } if(max_array_length!=0) { constant_exprt size_limit=as_number(max_array_length, java_int_type()); binary_relation_exprt le_max_size(op[0], ID_le, size_limit); code_assumet assume_le_max_size(le_max_size); - check_and_create.move_to_operands(assume_le_max_size); + c.move_to_operands(assume_le_max_size); } const exprt tmp=tmp_variable("newarray", ref_type); - check_and_create.copy_to_operands(code_assignt(tmp, java_new_array)); - c=std::move(check_and_create); + c.copy_to_operands(code_assignt(tmp, java_new_array)); results[0]=tmp; } else if(statement=="multianewarray") diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index f9a620ede7c..5699835800b 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -19,6 +19,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_object_factory.h" #include "java_types.h" +#include "java_utils.h" /*******************************************************************\ @@ -317,16 +318,6 @@ void java_object_factoryt::gen_nondet_init( } } -// Borrowed from java_bytecode_convert.cpp -- todo find a sensible place to -// factor this. -static constant_exprt as_number(const mp_integer value, const typet &type) -{ - const size_t java_int_width(type.get_unsigned_int(ID_width)); - const std::string significant_bits(integer2string(value, 2)); - std::string binary_width(java_int_width-significant_bits.length(), '0'); - return constant_exprt(binary_width+significant_bits, type); -} - /*******************************************************************\ Function: gen_nondet_array_init diff --git a/src/java_bytecode/java_utils.cpp b/src/java_bytecode/java_utils.cpp new file mode 100644 index 00000000000..94b52f11e23 --- /dev/null +++ b/src/java_bytecode/java_utils.cpp @@ -0,0 +1,20 @@ +/*******************************************************************\ + +Module: JAVA Bytecode Language Conversion + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include + +#include "java_utils.h" +#include "java_types.h" + +constant_exprt as_number(const mp_integer value, const typet &type) +{ + const size_t java_int_width(type.get_unsigned_int(ID_width)); + const std::string significant_bits(integer2string(value, 2)); + std::string binary_width(java_int_width-significant_bits.length(), '0'); + return constant_exprt(binary_width+significant_bits, type); +} diff --git a/src/java_bytecode/java_utils.h b/src/java_bytecode/java_utils.h new file mode 100644 index 00000000000..d01d93f2aca --- /dev/null +++ b/src/java_bytecode/java_utils.h @@ -0,0 +1,18 @@ +/*******************************************************************\ + +Module: JAVA Bytecode Language Conversion + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#ifndef CPROVER_JAVA_BYTECODE_JAVA_UTILS_H +#define CPROVER_JAVA_BYTECODE_JAVA_UTILS_H + +#include +#include +#include + +constant_exprt as_number(const mp_integer value, const typet &type); + +#endif // CPROVER_JAVA_BYTECODE_JAVA_UTILS_H From b7cdfd322b08d9a642e8348037f793e1f0b16790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Fri, 20 Jan 2017 17:18:10 +0100 Subject: [PATCH 29/45] take tautschnig's comments into account --- src/java_bytecode/expr2java.cpp | 14 ++-- src/java_bytecode/expr2java.h | 7 +- .../java_bytecode_convert_class.cpp | 11 ++- .../java_bytecode_convert_method.cpp | 50 ++++++-------- src/java_bytecode/java_bytecode_language.h | 4 +- src/java_bytecode/java_bytecode_parser.cpp | 6 +- .../java_bytecode_typecheck_expr.cpp | 6 +- src/java_bytecode/java_entry_point.cpp | 22 +++--- src/java_bytecode/java_object_factory.cpp | 68 ++++++++++++------- src/java_bytecode/java_object_factory.h | 6 +- src/java_bytecode/java_pointer_casts.cpp | 5 +- src/java_bytecode/java_pointer_casts.h | 2 - src/java_bytecode/java_utils.cpp | 20 ------ src/java_bytecode/java_utils.h | 18 ----- src/util/json_expr.cpp | 1 - 15 files changed, 105 insertions(+), 135 deletions(-) delete mode 100644 src/java_bytecode/java_utils.cpp delete mode 100644 src/java_bytecode/java_utils.h diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 505e7425921..74211dc5ab7 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -15,6 +15,7 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include #include +#include #include #include "java_types.h" @@ -216,7 +217,8 @@ std::string expr2javat::convert_constant( dest.reserve(char_representation_length); mp_integer int_value; - to_integer(src, int_value); + if(!to_integer(src, int_value)) + assert(false); dest+="(char)'"; @@ -238,7 +240,8 @@ std::string expr2javat::convert_constant( { // No byte-literals in Java, so just cast: mp_integer int_value; - to_integer(src, int_value); + if(!to_integer(src, int_value)) + assert(false); std::string dest="(byte)"; dest+=integer2string(int_value); return dest; @@ -247,7 +250,8 @@ std::string expr2javat::convert_constant( { // No short-literals in Java, so just cast: mp_integer int_value; - to_integer(src, int_value); + if(!to_integer(src, int_value)) + assert(false); std::string dest="(short)"; dest+=integer2string(int_value); return dest; @@ -482,7 +486,7 @@ std::string expr2javat::convert( const typet &type=ns.follow(src.type()); if(src.id()=="java-this") return convert_java_this(src, precedence=15); - if(src.id()=="java_instanceof") + if(src.id()==ID_java_instanceof) return convert_java_instanceof(src, precedence=15); else if(src.id()==ID_side_effect && (src.get(ID_statement)==ID_java_new || @@ -506,7 +510,7 @@ std::string expr2javat::convert( ")"; } else if(src.id()==ID_java_string_literal) - return '"'+id2string(src.get(ID_value))+'"'; // TODO: add escaping as needed + return '"'+MetaString(src.get_string(ID_value))+'"'; else if(src.id()==ID_constant && (type.id()==ID_bool || type.id()==ID_c_bool)) { if(src.is_true()) diff --git a/src/java_bytecode/expr2java.h b/src/java_bytecode/expr2java.h index a304f077288..d7889dc73a6 100644 --- a/src/java_bytecode/expr2java.h +++ b/src/java_bytecode/expr2java.h @@ -12,10 +12,6 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include #include -class exprt; -class namespacet; -class typet; - class expr2javat:public expr2ct { public: @@ -56,7 +52,8 @@ class expr2javat:public expr2ct const std::string &declarator); // length of string representation of Java Char - const std::size_t char_representation_length=14; + // representation is '\u0000' + const std::size_t char_representation_length=8; }; std::string expr2java(const exprt &expr, const namespacet &ns); diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 320f3a95ba9..049f6b4ead1 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -173,8 +173,8 @@ void java_bytecode_convert_classt::generate_class_stub( if(symbol_table.move(new_symbol, class_symbol)) { - warning() << "stub class symbol "+ - id2string(new_symbol.name)+" already exists"; + warning() << "stub class symbol " << new_symbol.name + << " already exists" << eom; } else { @@ -225,10 +225,7 @@ void java_bytecode_convert_classt::convert( symbol_table.symbols.erase(s_it); // erase, we stubbed it if(symbol_table.add(new_symbol)) - { - error() << "failed to add static field symbol" << eom; - throw 0; - } + assert(false && "failed to add static field symbol"); } else { @@ -276,6 +273,8 @@ void java_bytecode_convert_classt::add_array_types() // we have the base class, java.lang.Object, length and data // of appropriate type struct_type.set_tag(symbol_type.get_identifier()); + + struct_type.components().reserve(3); struct_typet::componentt comp0("@java.lang.Object", symbol_typet("java::java.lang.Object")); struct_type.components().push_back(comp0); diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 13656b3d028..0d0cd14028a 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -26,7 +26,6 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_bytecode_convert_method_class.h" #include "bytecode_info.h" #include "java_types.h" -#include "java_utils.h" #include #include @@ -415,7 +414,7 @@ codet java_bytecode_convert_methodt::get_array_bounds_check( const exprt &idx, const source_locationt& original_sloc) { - constant_exprt intzero=as_number(0, java_int_type()); + constant_exprt intzero=from_integer(0, java_int_type()); binary_relation_exprt gezero(idx, ID_ge, intzero); const member_exprt length_field(arraystruct, "length", java_int_type()); binary_relation_exprt ltlength(idx, ID_lt, length_field); @@ -937,7 +936,7 @@ codet java_bytecode_convert_methodt::convert_instructions( // The stack isn't modified. // TODO: convert assertions to exceptions. assert(op.size()==1 && results.size()==1); - binary_predicate_exprt check(op[0], "java_instanceof", arg0); + binary_predicate_exprt check(op[0], ID_java_instanceof, arg0); c=code_assertt(check); c.add_source_location().set_comment("Dynamic cast check"); c.add_source_location().set_property_class("bad-dynamic-cast"); @@ -1011,12 +1010,10 @@ codet java_bytecode_convert_methodt::convert_instructions( } code_function_callt call; - source_locationt loc; - loc=i_it->source_location; + source_locationt loc=i_it->source_location; loc.set_function(method_id); - source_locationt &source_loc=loc; - call.add_source_location()=source_loc; + call.add_source_location()=loc; call.arguments()=pop(parameters.size()); // double-check a bit @@ -1089,7 +1086,7 @@ codet java_bytecode_convert_methodt::convert_instructions( call.function()=symbol_exprt(arg0.get(ID_identifier), arg0.type()); } - call.function().add_source_location()=source_loc; + call.function().add_source_location()=loc; c=call; } else if(statement=="return") @@ -1245,7 +1242,7 @@ codet java_bytecode_convert_methodt::convert_instructions( irep_idt number=to_constant_expr(arg0).get_value(); code_gotot code_goto(label(number)); c=code_goto; - results[0]=as_number( + results[0]=from_integer( std::next(i_it)->address, pointer_typet(void_typet(), 64)); } @@ -1267,9 +1264,8 @@ codet java_bytecode_convert_methodt::convert_instructions( branches.move_to_operands(g); else { - code_ifthenelset - branch; - auto address_ptr=as_number( + code_ifthenelset branch; + auto address_ptr=from_integer( jsr_ret_targets[idx], pointer_typet(void_typet(), 64)); branch.cond()=equal_exprt(retvar, address_ptr); @@ -1311,9 +1307,9 @@ codet java_bytecode_convert_methodt::convert_instructions( } else { - const size_t value(arg0.get_unsigned_int(ID_value)); + const unsigned value(arg0.get_unsigned_int(ID_value)); const typet type=java_type_from_char(statement[0]); - results[0]=as_number(value, type); + results[0]=from_integer(value, type); } } else if(statement==patternt("?ipush")) @@ -1326,8 +1322,7 @@ codet java_bytecode_convert_methodt::convert_instructions( irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==2 && results.empty()); - code_ifthenelset - code_branch; + code_ifthenelset code_branch; const irep_idt cmp_op=get_if_cmp_operator(statement); binary_relation_exprt condition(op[0], cmp_op, op[1]); @@ -1360,8 +1355,7 @@ codet java_bytecode_convert_methodt::convert_instructions( irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==1 && results.empty()); - code_ifthenelset - code_branch; + code_ifthenelset code_branch; code_branch.cond()= binary_relation_exprt(op[0], id, gen_zero(op[0].type())); code_branch.cond().add_source_location()=i_it->source_location; @@ -1378,8 +1372,7 @@ codet java_bytecode_convert_methodt::convert_instructions( { irep_idt number=to_constant_expr(arg0).get_value(); assert(op.size()==1 && results.empty()); - code_ifthenelset - code_branch; + code_ifthenelset code_branch; const typecast_exprt lhs(op[0], pointer_typet(empty_typet())); const exprt rhs(gen_zero(lhs.type())); code_branch.cond()=binary_relation_exprt(lhs, ID_notequal, rhs); @@ -1393,8 +1386,7 @@ codet java_bytecode_convert_methodt::convert_instructions( { assert(op.size()==1 && results.empty()); irep_idt number=to_constant_expr(arg0).get_value(); - code_ifthenelset - code_branch; + code_ifthenelset code_branch; const typecast_exprt lhs(op[0], pointer_typet(empty_typet())); const exprt rhs(gen_zero(lhs.type())); code_branch.cond()=binary_relation_exprt(lhs, ID_equal, rhs); @@ -1506,7 +1498,7 @@ codet java_bytecode_convert_methodt::convert_instructions( results[0]= if_exprt( binary_relation_exprt(op[0], ID_equal, op[1]), - gen_zero(t), + from_integer(0, t), greater); } else if(statement==patternt("?cmp?")) @@ -1637,11 +1629,7 @@ codet java_bytecode_convert_methodt::convert_instructions( // set $assertionDisabled to false if(field_name.find("$assertionsDisabled")!=std::string::npos) - { - exprt e; - e.make_false(); - c=code_assignt(symbol_expr, e); - } + c=code_assignt(symbol_expr, false_exprt()); } else if(statement=="putfield") { @@ -1721,7 +1709,7 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!disable_runtime_checks) { // TODO make this throw NegativeArrayIndexException instead. - constant_exprt intzero=as_number(0, java_int_type()); + constant_exprt intzero=from_integer(0, java_int_type()); binary_relation_exprt gezero(op[0], ID_ge, intzero); code_assertt check(gezero); check.add_source_location().set_comment("Array size < 0"); @@ -1731,7 +1719,7 @@ codet java_bytecode_convert_methodt::convert_instructions( } if(max_array_length!=0) { - constant_exprt size_limit=as_number(max_array_length, java_int_type()); + constant_exprt size_limit=from_integer(max_array_length, java_int_type()); binary_relation_exprt le_max_size(op[0], ID_le, size_limit); code_assumet assume_le_max_size(le_max_size); c.move_to_operands(assume_le_max_size); @@ -1750,7 +1738,7 @@ codet java_bytecode_convert_methodt::convert_instructions( op=pop(dimension); assert(results.size()==1); - const pointer_typet ref_type=pointer_typet(arg0.type()); + const pointer_typet ref_type(arg0.type()); side_effect_exprt java_new_array(ID_java_new_array, ref_type); java_new_array.operands()=op; diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index 834f6d60544..a62aca0c887 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -14,6 +14,8 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_class_loader.h" +#define MAX_NONDET_ARRAY_LENGTH_DEFAULT 5 + class java_bytecode_languaget:public languaget { public: @@ -39,7 +41,7 @@ class java_bytecode_languaget:public languaget virtual ~java_bytecode_languaget(); java_bytecode_languaget(): - max_nondet_array_length(5), + max_nondet_array_length(MAX_NONDET_ARRAY_LENGTH_DEFAULT), max_user_array_length(0) { } bool from_expr( diff --git a/src/java_bytecode/java_bytecode_parser.cpp b/src/java_bytecode/java_bytecode_parser.cpp index c025a4ad268..c72105581f0 100644 --- a/src/java_bytecode/java_bytecode_parser.cpp +++ b/src/java_bytecode/java_bytecode_parser.cpp @@ -1449,7 +1449,7 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class) u2 sourcefile_index=read_u2(); irep_idt sourcefile_name; - std::string fqn=std::string(id2string(parsed_class.name)); + std::string fqn(id2string(parsed_class.name)); size_t last_index=fqn.find_last_of("."); if(last_index==std::string::npos) sourcefile_name=pool_entry(sourcefile_index).s; @@ -1457,8 +1457,8 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class) { std::string packageName=fqn.substr(0, last_index+1); std::replace(packageName.begin(), packageName.end(), '.', '/'); - const std::string &fullFileName= - std::string(packageName+id2string(pool_entry(sourcefile_index).s)); + const std::string + &fullFileName=(packageName+id2string(pool_entry(sourcefile_index).s)); sourcefile_name=fullFileName; } diff --git a/src/java_bytecode/java_bytecode_typecheck_expr.cpp b/src/java_bytecode/java_bytecode_typecheck_expr.cpp index d1bb21eea0d..5c234378936 100644 --- a/src/java_bytecode/java_bytecode_typecheck_expr.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_expr.cpp @@ -93,9 +93,9 @@ void java_bytecode_typecheckt::typecheck_expr_java_new_array( static void escape_non_alnum(std::string& toescape) { - for(size_t idx=0, lim=toescape.size(); idx!=lim; ++idx) - if(!isalnum(toescape[idx])) - toescape[idx]='_'; + for(auto &ch : toescape) + if(!isalnum(ch)) + ch='_'; } /*******************************************************************\ diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index 3d525d78060..ef0d35b15c3 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -92,10 +92,7 @@ static bool should_init_symbol(const symbolt& sym) sym.mode==ID_java) return true; - if(has_prefix(id2string(sym.name), "java::java.lang.String.Literal")) - return true; - - return false; + return has_prefix(id2string(sym.name), "java::java.lang.String.Literal"); } bool java_static_lifetime_init( @@ -112,8 +109,7 @@ bool java_static_lifetime_init( // external. Iterate over a copy of the symtab, as its iterators are // invalidated by object_factory: - std::vector symnames; - symnames.reserve(symbol_table.symbols.size()); + std::list symnames; for(const auto& entry : symbol_table.symbols) symnames.push_back(entry.first); @@ -144,7 +140,8 @@ bool java_static_lifetime_init( allow_null, symbol_table, max_nondet_array_length, - source_location); + source_location, + message_handler); code_assignt assignment(sym.symbol_expr(), newsym); code_block.add(assignment); } @@ -196,7 +193,8 @@ exprt::operandst java_build_arguments( code_blockt &init_code, symbol_tablet &symbol_table, bool assume_init_pointers_not_null, - unsigned max_nondet_array_length) + unsigned max_nondet_array_length, + message_handlert &message_handler) { const code_typet::parameterst ¶meters= to_code_type(function.type).parameters(); @@ -234,7 +232,8 @@ exprt::operandst java_build_arguments( allow_null, symbol_table, max_nondet_array_length, - function.location); + function.location, + message_handler); const symbolt &p_symbol= symbol_table.lookup(parameters[param_number].get_identifier()); @@ -459,7 +458,7 @@ main_function_resultt get_main_symbol( if(matches.empty()) { // Not found, silently ignore - res.main_function=symbolt(); + res.main_function=symbol; res.error_found=false; res.stop_convert=true; return res; @@ -596,7 +595,8 @@ bool java_entry_point( init_code, symbol_table, assume_init_pointers_not_null, - max_nondet_array_length); + max_nondet_array_length, + message_handler); call_main.arguments()=main_arguments; init_code.move_to_operands(call_main); diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 5699835800b..7aa6d13ead6 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -9,17 +9,20 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include +#include #include #include #include #include +#include + #include "java_object_factory.h" #include "java_types.h" -#include "java_utils.h" /*******************************************************************\ @@ -33,13 +36,14 @@ Function: gen_nondet_init \*******************************************************************/ -class java_object_factoryt +class java_object_factoryt:public messaget { code_blockt &init_code; std::set recursion_set; bool assume_non_null; size_t max_nondet_array_length; symbol_tablet &symbol_table; + message_handlert &message_handler; namespacet ns; public: @@ -47,12 +51,15 @@ class java_object_factoryt code_blockt& _init_code, bool _assume_non_null, size_t _max_nondet_array_length, - symbol_tablet& _symbol_table) : + symbol_tablet &_symbol_table, + message_handlert &_message_handler): init_code(_init_code), assume_non_null(_assume_non_null), max_nondet_array_length(_max_nondet_array_length), symbol_table(_symbol_table), - ns(_symbol_table) {} + message_handler(_message_handler), + ns(_symbol_table) + {} exprt allocate_object( const exprt&, @@ -69,7 +76,8 @@ class java_object_factoryt const source_locationt &loc, bool skip_classid, bool create_dynamic_objects, - const typet *override_type=0); + bool override=false, + const typet &override_type=empty_typet()); }; // Returns false if we can't figure out the size of allocate_type. @@ -151,10 +159,11 @@ void java_object_factoryt::gen_nondet_init( const source_locationt &loc, bool skip_classid, bool create_dynamic_objects, - const typet *override_type) + bool override, + const typet &override_type) { const typet &type= - override_type ? ns.follow(*override_type) : ns.follow(expr.type()); + override ? ns.follow(override_type) : ns.follow(expr.type()); if(type.id()==ID_pointer) { @@ -199,17 +208,15 @@ void java_object_factoryt::gen_nondet_init( code_assignt(expr, null_pointer_exprt(pointer_type)); set_null_inst.add_source_location()=loc; - std::ostringstream fresh_label_oss; - fresh_label_oss<<"post_synthetic_malloc_" - <<(++synthetic_constructor_count); - std::string fresh_label=fresh_label_oss.str(); + std::string fresh_label= + "post_synthetic_malloc_"+std::to_string(++synthetic_constructor_count); set_null_label=code_labelt(fresh_label, set_null_inst); init_done_label=code_labelt(fresh_label+"_init_done", code_skipt()); - code_ifthenelset - null_check; - exprt null_return=constant_exprt("0", returns_null_sym.type); + code_ifthenelset null_check; + exprt null_return= + zero_initializer(returns_null_sym.type, loc, ns, message_handler); null_check.cond()= notequal_exprt(returns_null, null_return); null_check.then_case()=code_gotot(fresh_label); @@ -343,7 +350,7 @@ void java_object_factoryt::gen_nondet_array_init( const typet &element_type= static_cast(expr.type().subtype().find(ID_C_element_type)); - auto max_length_expr=as_number(max_nondet_array_length, java_int_type()); + auto max_length_expr=from_integer(max_nondet_array_length, java_int_type()); typet allocate_type; symbolt &length_sym=new_tmp_symbol(symbol_table, "nondet_array_length"); @@ -355,7 +362,7 @@ void java_object_factoryt::gen_nondet_array_init( // Insert assumptions to bound its length: binary_relation_exprt - assume1(length_sym_expr, ID_ge, as_number(0, java_int_type())); + assume1(length_sym_expr, ID_ge, from_integer(0, java_int_type())); binary_relation_exprt assume2(length_sym_expr, ID_le, max_length_expr); code_assumet assume_inst1(assume1); @@ -395,7 +402,7 @@ void java_object_factoryt::gen_nondet_array_init( counter.type=length_sym_expr.type(); exprt counter_expr=counter.symbol_expr(); - exprt java_zero=as_number(0, java_int_type()); + exprt java_zero=from_integer(0, java_int_type()); init_code.copy_to_operands(code_assignt(counter_expr, java_zero)); std::string head_name=as_string(counter.base_name)+"_header"; @@ -408,8 +415,7 @@ void java_object_factoryt::gen_nondet_array_init( code_labelt init_done_label(done_name, code_skipt()); code_gotot goto_done(done_name); - code_ifthenelset - done_test; + code_ifthenelset done_test; done_test.cond()=equal_exprt(counter_expr, length_sym_expr); done_test.then_case()=goto_done; @@ -417,8 +423,7 @@ void java_object_factoryt::gen_nondet_array_init( // Add a redundant if(counter == max_length) break that is easier for the // unwinder to understand. - code_ifthenelset - max_test; + code_ifthenelset max_test; max_test.cond()=equal_exprt(counter_expr, max_length_expr); max_test.then_case()=goto_done; @@ -435,9 +440,10 @@ void java_object_factoryt::gen_nondet_array_init( loc, false, true, - &element_type); + true, + element_type); - exprt java_one=as_number(1, java_int_type()); + exprt java_one=from_integer(1, java_int_type()); code_assignt incr(counter_expr, plus_exprt(counter_expr, java_one)); init_code.move_to_operands(incr); @@ -466,14 +472,22 @@ void gen_nondet_init( bool skip_classid, bool create_dyn_objs, bool assume_non_null, + message_handlert &message_handler, size_t max_nondet_array_length) { java_object_factoryt state( init_code, assume_non_null, max_nondet_array_length, - symbol_table); - state.gen_nondet_init(expr, false, "", loc, skip_classid, create_dyn_objs); + symbol_table, + message_handler); + state.gen_nondet_init( + expr, + false, + "", + loc, + skip_classid, + create_dyn_objs); } /*******************************************************************\ @@ -543,7 +557,8 @@ exprt object_factory( bool allow_null, symbol_tablet &symbol_table, size_t max_nondet_array_length, - const source_locationt &loc) + const source_locationt &loc, + message_handlert &message_handler) { if(type.id()==ID_pointer) { @@ -562,6 +577,7 @@ exprt object_factory( false, false, !allow_null, + message_handler, max_nondet_array_length); return object; diff --git a/src/java_bytecode/java_object_factory.h b/src/java_bytecode/java_object_factory.h index 7807e176749..13d933d9da5 100644 --- a/src/java_bytecode/java_object_factory.h +++ b/src/java_bytecode/java_object_factory.h @@ -9,6 +9,7 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_JAVA_BYTECODE_JAVA_OBJECT_FACTORY_H #define CPROVER_JAVA_BYTECODE_JAVA_OBJECT_FACTORY_H +#include #include #include @@ -18,7 +19,8 @@ exprt object_factory( bool allow_null, symbol_tablet &symbol_table, size_t max_nondet_array_length, - const source_locationt &); + const source_locationt &, + message_handlert &message_handler); void gen_nondet_init( const exprt &expr, @@ -28,8 +30,10 @@ void gen_nondet_init( bool skip_classid, bool create_dynamic_objects, bool assume_non_null, + message_handlert &message_handler, size_t max_nondet_array_length=5); + exprt get_nondet_bool(const typet&); symbolt &new_tmp_symbol( diff --git a/src/java_bytecode/java_pointer_casts.cpp b/src/java_bytecode/java_pointer_casts.cpp index 74587ccabe7..135e4705cb2 100644 --- a/src/java_bytecode/java_pointer_casts.cpp +++ b/src/java_bytecode/java_pointer_casts.cpp @@ -24,7 +24,7 @@ Function: clean_deref \*******************************************************************/ -exprt clean_deref(const exprt &ptr) +static exprt clean_deref(const exprt &ptr) { return ptr.id()==ID_address_of ? ptr.op0() @@ -50,6 +50,7 @@ bool find_superclass_with_type( const typet &target_type, const namespacet &ns) { + assert(ptr.type().id()==ID_pointer); while(true) { const typet ptr_base=ns.follow(ptr.type().subtype()); @@ -59,7 +60,7 @@ bool find_superclass_with_type( const struct_typet &base_struct=to_struct_type(ptr_base); - if(base_struct.components().size()==0) + if(base_struct.components().empty()) return false; const typet &first_field_type= diff --git a/src/java_bytecode/java_pointer_casts.h b/src/java_bytecode/java_pointer_casts.h index 3e0bd6c53d5..7b5d23a3c8a 100644 --- a/src/java_bytecode/java_pointer_casts.h +++ b/src/java_bytecode/java_pointer_casts.h @@ -9,8 +9,6 @@ Author: DiffBlue #ifndef CPROVER_JAVA_BYTECODE_JAVA_POINTER_CASTS_H #define CPROVER_JAVA_BYTECODE_JAVA_POINTER_CASTS_H -exprt clean_deref(const exprt &ptr); - bool find_superclass_with_type( exprt &ptr, const typet &target_type, diff --git a/src/java_bytecode/java_utils.cpp b/src/java_bytecode/java_utils.cpp deleted file mode 100644 index 94b52f11e23..00000000000 --- a/src/java_bytecode/java_utils.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/*******************************************************************\ - -Module: JAVA Bytecode Language Conversion - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include - -#include "java_utils.h" -#include "java_types.h" - -constant_exprt as_number(const mp_integer value, const typet &type) -{ - const size_t java_int_width(type.get_unsigned_int(ID_width)); - const std::string significant_bits(integer2string(value, 2)); - std::string binary_width(java_int_width-significant_bits.length(), '0'); - return constant_exprt(binary_width+significant_bits, type); -} diff --git a/src/java_bytecode/java_utils.h b/src/java_bytecode/java_utils.h deleted file mode 100644 index d01d93f2aca..00000000000 --- a/src/java_bytecode/java_utils.h +++ /dev/null @@ -1,18 +0,0 @@ -/*******************************************************************\ - -Module: JAVA Bytecode Language Conversion - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#ifndef CPROVER_JAVA_BYTECODE_JAVA_UTILS_H -#define CPROVER_JAVA_BYTECODE_JAVA_UTILS_H - -#include -#include -#include - -constant_exprt as_number(const mp_integer value, const typet &type); - -#endif // CPROVER_JAVA_BYTECODE_JAVA_UTILS_H diff --git a/src/util/json_expr.cpp b/src/util/json_expr.cpp index 4d9f7b5aa54..c44769fceda 100644 --- a/src/util/json_expr.cpp +++ b/src/util/json_expr.cpp @@ -16,7 +16,6 @@ Author: Peter Schrammel #include "config.h" #include "json_expr.h" -#include /*******************************************************************\ Function: json From 344e4a3e41a5556059ef1168197443669cf96745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 23 Jan 2017 11:10:19 +0100 Subject: [PATCH 30/45] remove namespace from vtable --- src/java_bytecode/java_bytecode_vtable.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/java_bytecode/java_bytecode_vtable.cpp b/src/java_bytecode/java_bytecode_vtable.cpp index 1af016870f9..be0cf2a15b8 100644 --- a/src/java_bytecode/java_bytecode_vtable.cpp +++ b/src/java_bytecode/java_bytecode_vtable.cpp @@ -16,9 +16,6 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -namespace -{ - const char ID_virtual_name[] = "virtual_name"; class is_virtual_name_equalt { @@ -213,7 +210,6 @@ class java_bytecode_vtable_factoryt } }; -} /******************************************************************* From 8848f8fcd34728cc6ad9ba59427ba4b14b9da587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 23 Jan 2017 11:34:38 +0100 Subject: [PATCH 31/45] remove const_cast --- src/java_bytecode/java_bytecode_typecheck_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java_bytecode/java_bytecode_typecheck_expr.cpp b/src/java_bytecode/java_bytecode_typecheck_expr.cpp index 5c234378936..0c5e8002af0 100644 --- a/src/java_bytecode/java_bytecode_typecheck_expr.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_expr.cpp @@ -235,7 +235,7 @@ void java_bytecode_typecheckt::typecheck_expr_member(member_exprt &expr) while(1) { - typet &base_type=const_cast(ns.follow(expr.struct_op().type())); + typet base_type(ns.follow(expr.struct_op().type())); if(base_type.id()!=ID_struct) break; // give up From 4b6c1ab65a5bcef91cbcbd81b3b7c6e9a232fd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 23 Jan 2017 14:32:19 +0100 Subject: [PATCH 32/45] add java_utils.cpp --- src/java_bytecode/java_object_factory.cpp | 6 ++---- src/java_bytecode/java_utils.cpp | 21 +++++++++++++++++++++ src/java_bytecode/java_utils.h | 16 ++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 src/java_bytecode/java_utils.cpp create mode 100644 src/java_bytecode/java_utils.h diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 7aa6d13ead6..3cff49703fd 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -23,6 +23,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_object_factory.h" #include "java_types.h" +#include "java_utils.h" /*******************************************************************\ @@ -223,11 +224,8 @@ void java_object_factoryt::gen_nondet_init( init_code.move_to_operands(null_check); } - if(subtype.id()==ID_struct && - has_prefix(id2string(to_struct_type(subtype).get_tag()), "java::array[")) - { + if(java_is_array_type(subtype)) gen_nondet_array_init(expr, loc); - } else { exprt allocated= diff --git a/src/java_bytecode/java_utils.cpp b/src/java_bytecode/java_utils.cpp new file mode 100644 index 00000000000..2e84c77f870 --- /dev/null +++ b/src/java_bytecode/java_utils.cpp @@ -0,0 +1,21 @@ +/*******************************************************************\ + +Module: + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include +#include + +#include "java_utils.h" + +bool java_is_array_type(const typet &type) +{ + if(type.id()!=ID_struct) + return false; + return has_prefix(id2string( + to_struct_type(type).get_tag()), + "java::array["); +} diff --git a/src/java_bytecode/java_utils.h b/src/java_bytecode/java_utils.h new file mode 100644 index 00000000000..ec7e6a9ad8e --- /dev/null +++ b/src/java_bytecode/java_utils.h @@ -0,0 +1,16 @@ +/*******************************************************************\ + +Module: + +Author: Daniel Kroening, kroening@kroening.com + +\*******************************************************************/ + +#include + +#ifndef CPROVER_JAVA_BYTECODE_JAVA_UTILS_H +#define CPROVER_JAVA_BYTECODE_JAVA_UTILS_H + +bool java_is_array_type(const typet &type); + +#endif // CPROVER_JAVA_BYTECODE_JAVA_UTILS_H From f866a9f7453a494d473d8ebc568ed59e3d5c058a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 23 Jan 2017 13:52:27 +0100 Subject: [PATCH 33/45] Peter's comments --- src/java_bytecode/expr2java.cpp | 2 +- .../java_bytecode_convert_method.cpp | 12 +++---- .../java_bytecode_convert_method_class.h | 2 +- src/java_bytecode/java_bytecode_parser.cpp | 10 +++--- src/java_bytecode/java_entry_point.cpp | 4 +-- src/java_bytecode/java_object_factory.cpp | 32 +++++++++++++------ src/java_bytecode/java_pointer_casts.cpp | 1 - src/util/json_expr.cpp | 2 +- 8 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 74211dc5ab7..8b5966b8afe 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -50,7 +50,7 @@ std::string expr2javat::convert_code_function_call( unsigned p; std::string lhs_str=convert(src.lhs(), p); - // TODO: ggf. Klammern je nach p + // TODO: if necessery add parentheses, dependent on p dest+=lhs_str; dest+='='; } diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 0d0cd14028a..fd95df405ed 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -425,14 +425,14 @@ codet java_bytecode_convert_methodt::get_array_bounds_check( bounds_checks.operands().back().add_source_location() .set_comment("Array index < 0"); bounds_checks.operands().back().add_source_location() - .set_property_class("array-index-oob-low"); + .set_property_class("array-index-out-of-bounds-low"); bounds_checks.add(code_assertt(ltlength)); bounds_checks.operands().back().add_source_location()=original_sloc; bounds_checks.operands().back().add_source_location() .set_comment("Array index >= length"); bounds_checks.operands().back().add_source_location() - .set_property_class("array-index-oob-high"); + .set_property_class("array-index-out-of-bounds-high"); // TODO make this throw ArrayIndexOutOfBoundsException instead of asserting. return bounds_checks; @@ -795,9 +795,9 @@ codet java_bytecode_convert_methodt::convert_instructions( if(i_it->statement=="jsr" || i_it->statement=="jsr_w") { - instructionst::const_iterator next=i_it; + instructionst::const_iterator next=i_it+1; assert( - ++next!=instructions.end() && + next!=instructions.end() && "jsr without valid return address?"); targets.insert(next->address); jsr_ret_targets.push_back(next->address); @@ -1750,7 +1750,7 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!disable_runtime_checks) { // TODO make this throw NegativeArrayIndexException instead. - constant_exprt intzero=as_number(0, java_int_type()); + constant_exprt intzero=from_integer(0, java_int_type()); binary_relation_exprt gezero(op[0], ID_ge, intzero); code_assertt check(gezero); check.add_source_location().set_comment("Array size < 0"); @@ -1761,7 +1761,7 @@ codet java_bytecode_convert_methodt::convert_instructions( if(max_array_length!=0) { constant_exprt size_limit= - as_number(max_array_length, java_int_type()); + from_integer(max_array_length, java_int_type()); binary_relation_exprt le_max_size(op[0], ID_le, size_limit); code_assumet assume_le_max_size(le_max_size); checkandcreate.move_to_operands(assume_le_max_size); diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index d961a7131be..8aa79c7bd2b 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -51,7 +51,7 @@ class java_bytecode_convert_methodt:public messaget protected: symbol_tablet &symbol_table; const bool disable_runtime_checks; - size_t max_array_length; + const size_t max_array_length; irep_idt method_id; irep_idt current_method; diff --git a/src/java_bytecode/java_bytecode_parser.cpp b/src/java_bytecode/java_bytecode_parser.cpp index c72105581f0..93f082ecb7d 100644 --- a/src/java_bytecode/java_bytecode_parser.cpp +++ b/src/java_bytecode/java_bytecode_parser.cpp @@ -1455,11 +1455,11 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class) sourcefile_name=pool_entry(sourcefile_index).s; else { - std::string packageName=fqn.substr(0, last_index+1); - std::replace(packageName.begin(), packageName.end(), '.', '/'); - const std::string - &fullFileName=(packageName+id2string(pool_entry(sourcefile_index).s)); - sourcefile_name=fullFileName; + std::string package_name=fqn.substr(0, last_index+1); + std::replace(package_name.begin(), package_name.end(), '.', '/'); + const std::string &full_file_name= + package_name+id2string(pool_entry(sourcefile_index).s); + sourcefile_name=full_file_name; } for(methodst::iterator m_it=parsed_class.methods.begin(); diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index ef0d35b15c3..d560bb234fa 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -105,12 +105,12 @@ bool java_static_lifetime_init( symbolt &initialize_symbol=symbol_table.lookup(INITIALIZE); code_blockt &code_block=to_code_block(to_code(initialize_symbol.value)); - // W need to zero out all static variables, or nondet-initialize if they're + // We need to zero out all static variables, or nondet-initialize if they're // external. Iterate over a copy of the symtab, as its iterators are // invalidated by object_factory: std::list symnames; - for(const auto& entry : symbol_table.symbols) + for(const auto &entry : symbol_table.symbols) symnames.push_back(entry.first); for(const auto& symname : symnames) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 3cff49703fd..a02da1a43f0 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -81,17 +81,30 @@ class java_object_factoryt:public messaget const typet &override_type=empty_typet()); }; -// Returns false if we can't figure out the size of allocate_type. -// allocate_type may differ from target_expr, e.g. for target_expr having -// type int* and allocate_type being an int[10]. + +/*******************************************************************\ + +Function: gen_nondet_array_init + + Inputs: the target expression, desired object type, source location + and Boolean whether to create a dynamic object + + Outputs: the allocated object + + Purpose: Returns false if we can't figure out the size of allocate_type. + allocate_type may differ from target_expr, e.g. for target_expr + having type int* and allocate_type being an int[10]. + +\*******************************************************************/ + exprt java_object_factoryt::allocate_object( - const exprt& target_expr, - const typet& allocate_type, + const exprt &target_expr, + const typet &allocate_type, const source_locationt &loc, bool create_dynamic_objects) { - const typet& allocate_type_resolved=ns.follow(allocate_type); - const typet& target_type=ns.follow(target_expr.type().subtype()); + const typet &allocate_type_resolved=ns.follow(allocate_type); + const typet &target_type=ns.follow(target_expr.type().subtype()); bool cast_needed=allocate_type_resolved!=target_type; if(!create_dynamic_objects) { @@ -197,7 +210,7 @@ void java_object_factoryt::gen_nondet_init( if(!assume_non_null) { auto returns_null_sym= - new_tmp_symbol(symbol_table, "opaque_returns_null"); + new_tmp_symbol(symbol_table, "opaque_returns_null"); returns_null_sym.type=c_bool_typet(1); auto returns_null=returns_null_sym.symbol_expr(); auto assign_returns_null= @@ -449,7 +462,6 @@ void java_object_factoryt::gen_nondet_array_init( init_code.move_to_operands(init_done_label); } - /*******************************************************************\ Function: gen_nondet_init @@ -502,7 +514,7 @@ Function: new_tmp_symbol symbolt &new_tmp_symbol(symbol_tablet &symbol_table, const std::string& prefix) { - static size_t temporary_counter=0; + static size_t temporary_counter=0; // TODO change this auxiliary_symbolt new_symbol; symbolt *symbol_ptr; diff --git a/src/java_bytecode/java_pointer_casts.cpp b/src/java_bytecode/java_pointer_casts.cpp index 135e4705cb2..934e6cfb135 100644 --- a/src/java_bytecode/java_pointer_casts.cpp +++ b/src/java_bytecode/java_pointer_casts.cpp @@ -44,7 +44,6 @@ Function: find_superclass_with_type \*******************************************************************/ - bool find_superclass_with_type( exprt &ptr, const typet &target_type, diff --git a/src/util/json_expr.cpp b/src/util/json_expr.cpp index c44769fceda..7d52ca93c31 100644 --- a/src/util/json_expr.cpp +++ b/src/util/json_expr.cpp @@ -265,7 +265,7 @@ json_objectt json( if(expr.get(ID_value)==ID_NULL) result["data"]=json_stringt("NULL"); } - else if(type.id()==ID_bool || type.id()==ID_c_bool) + else if(type.id()==ID_bool) { result["name"]=json_stringt("boolean"); result["binary"]=json_stringt(expr.is_true()?"1":"0"); From e2827033f0f5c0f1af9d989d424d20abf28ddbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 23 Jan 2017 15:03:54 +0100 Subject: [PATCH 34/45] remove superfluous std::move from conversion --- .../java_bytecode_convert_method.cpp | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index fd95df405ed..7d6140966d5 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -1124,18 +1124,17 @@ codet java_bytecode_convert_methodt::convert_instructions( typet element_type=data_ptr.type().subtype(); const dereference_exprt element(data_plus_offset, element_type); - code_blockt assert_and_put; + c=code_blockt(); if(!disable_runtime_checks) { codet bounds_check= get_array_bounds_check(deref, op[1], i_it->source_location); bounds_check.add_source_location()=i_it->source_location; - assert_and_put.move_to_operands(bounds_check); + c.move_to_operands(bounds_check); } code_assignt array_put(element, op[2]); array_put.add_source_location()=i_it->source_location; - assert_and_put.move_to_operands(array_put); - c=std::move(assert_and_put); + c.move_to_operands(array_put); c.add_source_location()=i_it->source_location; } else if(statement==patternt("?store")) @@ -1174,10 +1173,8 @@ codet java_bytecode_convert_methodt::convert_instructions( if(!disable_runtime_checks) { - codet bounds_check= - get_array_bounds_check(deref, op[1], i_it->source_location); - bounds_check.add_source_location()=i_it->source_location; - c=std::move(bounds_check); + c=get_array_bounds_check(deref, op[1], i_it->source_location); + c.add_source_location()=i_it->source_location; } results[0]=java_bytecode_promotion(element); } @@ -1252,7 +1249,7 @@ codet java_bytecode_convert_methodt::convert_instructions( // and write something like: // if(retaddr==5) goto 5; else if(retaddr==10) goto 10; ... assert(op.empty() && results.empty()); - code_blockt branches; + c=code_blockt(); auto retvar=variable(arg0, 'a', i_it->address, NO_CAST); assert(!jsr_ret_targets.empty()); for(size_t idx=0, idxlim=jsr_ret_targets.size(); idx!=idxlim; ++idx) @@ -1261,7 +1258,7 @@ codet java_bytecode_convert_methodt::convert_instructions( code_gotot g(label(number)); g.add_source_location()=i_it->source_location; if(idx==idxlim-1) - branches.move_to_operands(g); + c.move_to_operands(g); else { code_ifthenelset branch; @@ -1272,10 +1269,9 @@ codet java_bytecode_convert_methodt::convert_instructions( branch.cond().add_source_location()=i_it->source_location; branch.then_case()=g; branch.add_source_location()=i_it->source_location; - branches.move_to_operands(branch); + c.move_to_operands(branch); } } - c=std::move(branches); } else if(statement=="iconst_m1") { From f36dcae70fb7bb8ff5f60bf700a6f9fc30f58203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 23 Jan 2017 16:45:59 +0100 Subject: [PATCH 35/45] adapt NullPointer[1-4] regression tests --- regression/cbmc-java/NullPointer1/test.desc | 2 +- regression/cbmc-java/NullPointer2/test.desc | 2 +- regression/cbmc-java/NullPointer3/test.desc | 2 +- regression/cbmc-java/NullPointer4/test.desc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/regression/cbmc-java/NullPointer1/test.desc b/regression/cbmc-java/NullPointer1/test.desc index bf4dc51e8da..0394ce544f3 100644 --- a/regression/cbmc-java/NullPointer1/test.desc +++ b/regression/cbmc-java/NullPointer1/test.desc @@ -3,7 +3,7 @@ NullPointer1.class --pointer-check --stop-on-fail ^EXIT=10$ ^SIGNAL=0$ -^ file NullPointer1.java line 16$ +^ file NullPointer1.java line 16 function java::NullPointer1.main:(\[Ljava/lang/String;)V$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/cbmc-java/NullPointer2/test.desc b/regression/cbmc-java/NullPointer2/test.desc index 8bf602bc2af..a794ca8ac88 100644 --- a/regression/cbmc-java/NullPointer2/test.desc +++ b/regression/cbmc-java/NullPointer2/test.desc @@ -3,7 +3,7 @@ NullPointer2.class --pointer-check --stop-on-fail ^EXIT=10$ ^SIGNAL=0$ -^ file NullPointer2.java line 9$ +^ file NullPointer2.java line 9 function java::NullPointer2.main:(\[Ljava/lang/String;)V bytecode_index 1$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/cbmc-java/NullPointer3/test.desc b/regression/cbmc-java/NullPointer3/test.desc index d422f43b99d..f4956e75540 100644 --- a/regression/cbmc-java/NullPointer3/test.desc +++ b/regression/cbmc-java/NullPointer3/test.desc @@ -3,7 +3,7 @@ NullPointer3.class --pointer-check --stop-on-fail ^EXIT=10$ ^SIGNAL=0$ -^ file NullPointer3.java line 5$ +^ file NullPointer3.java line 5 function java::NullPointer3.main:(\[Ljava/lang/String;)V bytecode_index 1$ ^VERIFICATION FAILED$ -- ^warning: ignoring diff --git a/regression/cbmc-java/NullPointer4/test.desc b/regression/cbmc-java/NullPointer4/test.desc index 788cb61fdf1..653f7cf47bd 100644 --- a/regression/cbmc-java/NullPointer4/test.desc +++ b/regression/cbmc-java/NullPointer4/test.desc @@ -3,7 +3,7 @@ NullPointer4.class --pointer-check --stop-on-fail ^EXIT=10$ ^SIGNAL=0$ -^ file NullPointer4.java line 6$ +^ file NullPointer4.java line 6 function java::NullPointer4.main:(\[Ljava/lang/String;)V$ ^VERIFICATION FAILED$ -- ^warning: ignoring From 39fb0172ec94932ec64ac4b1e9f4e6e05c53181c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Mon, 23 Jan 2017 17:13:23 +0100 Subject: [PATCH 36/45] default ctor for java_convert_methodt::variablet --- src/java_bytecode/java_bytecode_convert_method.cpp | 9 +++++---- src/java_bytecode/java_bytecode_convert_method_class.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index 7d6140966d5..a2ca21ef80d 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -412,7 +412,7 @@ static member_exprt to_member(const exprt &pointer, const exprt &fieldref) codet java_bytecode_convert_methodt::get_array_bounds_check( const exprt &arraystruct, const exprt &idx, - const source_locationt& original_sloc) + const source_locationt &original_sloc) { constant_exprt intzero=from_integer(0, java_int_type()); binary_relation_exprt gezero(idx, ID_ge, intzero); @@ -1619,7 +1619,7 @@ codet java_bytecode_convert_methodt::convert_instructions( { assert(op.empty() && results.size()==1); symbol_exprt symbol_expr(arg0.type()); - const auto& field_name=arg0.get_string(ID_component_name); + const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); results[0]=java_bytecode_promotion(symbol_expr); @@ -1636,7 +1636,7 @@ codet java_bytecode_convert_methodt::convert_instructions( { assert(op.size()==1 && results.empty()); symbol_exprt symbol_expr(arg0.type()); - const auto& field_name=arg0.get_string(ID_component_name); + const auto &field_name=arg0.get_string(ID_component_name); symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name); c=code_assignt(symbol_expr, op[0]); } @@ -1715,7 +1715,8 @@ codet java_bytecode_convert_methodt::convert_instructions( } if(max_array_length!=0) { - constant_exprt size_limit=from_integer(max_array_length, java_int_type()); + constant_exprt size_limit= + from_integer(max_array_length, java_int_type()); binary_relation_exprt le_max_size(op[0], ID_le, size_limit); code_assumet assume_le_max_size(le_max_size); c.move_to_operands(assume_le_max_size); diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index 8aa79c7bd2b..ca4efee46e3 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -82,7 +82,7 @@ class java_bytecode_convert_methodt:public messaget size_t length; bool is_parameter; std::vector holes; - variablet() : symbol_expr(), is_parameter(false) {} + variablet() : symbol_expr(), start_pc(0), length(0), is_parameter(false) {} }; typedef std::vector variablest; From f5c89d067374de0025436021b70735407c3fc8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 24 Jan 2017 00:10:35 +0100 Subject: [PATCH 37/45] take tautschnig's comments into account --- src/java_bytecode/expr2java.cpp | 2 +- src/java_bytecode/java_bytecode_language.cpp | 16 ++++---- .../java_bytecode_typecheck_expr.cpp | 4 +- src/java_bytecode/java_entry_point.cpp | 40 +++++++++---------- src/java_bytecode/java_object_factory.cpp | 2 +- src/util/json_expr.cpp | 1 + 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 8b5966b8afe..1da34a5bd37 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -95,7 +95,7 @@ std::string expr2javat::convert_code_function_call( first=false; else dest+=", "; - // TODO: ggf. Klammern je nach p + // TODO: if necessery add parentheses, dependent on p dest+=arg_str; } } diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 20b996999d5..4a38e1cf9da 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -239,15 +239,13 @@ bool java_bytecode_languaget::final(symbol_tablet &symbol_table) symbolt entry=res.main_function; - if(java_entry_point( - symbol_table, - main_class, - get_message_handler(), - assume_inputs_non_null, - max_nondet_array_length)) - return true; - - return false; + return( + java_entry_point( + symbol_table, + main_class, + get_message_handler(), + assume_inputs_non_null, + max_nondet_array_length)); } /*******************************************************************\ diff --git a/src/java_bytecode/java_bytecode_typecheck_expr.cpp b/src/java_bytecode/java_bytecode_typecheck_expr.cpp index 0c5e8002af0..069aee1830b 100644 --- a/src/java_bytecode/java_bytecode_typecheck_expr.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_expr.cpp @@ -94,8 +94,8 @@ void java_bytecode_typecheckt::typecheck_expr_java_new_array( static void escape_non_alnum(std::string& toescape) { for(auto &ch : toescape) - if(!isalnum(ch)) - ch='_'; + if(!isalnum(ch)) + ch='_'; } /*******************************************************************\ diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index d560bb234fa..67fc10a2fd1 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -10,6 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include @@ -71,18 +72,6 @@ static void create_initialize(symbol_tablet &symbol_table) } -/*******************************************************************\ - -Function: java_static_lifetime_init - - Inputs: - - Outputs: - - Purpose: - -\*******************************************************************/ - static bool should_init_symbol(const symbolt& sym) { if(sym.type.id()!=ID_code && @@ -95,6 +84,18 @@ static bool should_init_symbol(const symbolt& sym) return has_prefix(id2string(sym.name), "java::java.lang.String.Literal"); } +/*******************************************************************\ + +Function: java_static_lifetime_init + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + bool java_static_lifetime_init( symbol_tablet &symbol_table, const source_locationt &source_location, @@ -126,12 +127,11 @@ bool java_static_lifetime_init( std::string namestr=id2string(sym.symbol_expr().get_identifier()); const std::string suffix="@class_model"; // Static '.class' fields are always non-null. - if(namestr.size()>=suffix.size() && - namestr.substr(namestr.size()-suffix.size())==suffix) + if(has_suffix(namestr, suffix)) allow_null=false; if(allow_null && has_prefix( - namestr, - "java::java.lang.String.Literal")) + namestr, + "java::java.lang.String.Literal")) allow_null=false; } auto newsym=object_factory( @@ -208,7 +208,7 @@ exprt::operandst java_build_arguments( { bool is_this=(param_number==0) && parameters[param_number].get_this(); - bool is_default_entry_point(config.main==""); + bool is_default_entry_point(config.main.empty()); bool is_main=is_default_entry_point; if(!is_main) { @@ -244,7 +244,7 @@ exprt::operandst java_build_arguments( input.op0()=address_of_exprt( index_exprt( string_constantt(p_symbol.base_name), - gen_zero(index_type()))); + from_integer(0, index_type()))); input.op1()=main_arguments[param_number]; input.add_source_location()=function.location; @@ -293,7 +293,7 @@ void java_record_outputs( address_of_exprt( index_exprt( string_constantt(return_symbol.base_name), - gen_zero(index_type()))); + from_integer(0, index_type()))); output.op1()=return_symbol.symbol_expr(); output.add_source_location()=function.location; @@ -316,7 +316,7 @@ void java_record_outputs( address_of_exprt( index_exprt( string_constantt(p_symbol.base_name), - gen_zero(index_type()))); + from_integer(0, index_type()))); output.op1()=main_arguments[param_number]; output.add_source_location()=function.location; diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index a02da1a43f0..c9530c59a19 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -514,7 +514,7 @@ Function: new_tmp_symbol symbolt &new_tmp_symbol(symbol_tablet &symbol_table, const std::string& prefix) { - static size_t temporary_counter=0; // TODO change this + static size_t temporary_counter=0; // TODO encapsulate as class variable auxiliary_symbolt new_symbol; symbolt *symbol_ptr; diff --git a/src/util/json_expr.cpp b/src/util/json_expr.cpp index 7d52ca93c31..77f58eb0e18 100644 --- a/src/util/json_expr.cpp +++ b/src/util/json_expr.cpp @@ -16,6 +16,7 @@ Author: Peter Schrammel #include "config.h" #include "json_expr.h" + /*******************************************************************\ Function: json From 39c3cf72cd6209bbf89739b918cfbe178511d6d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 24 Jan 2017 15:05:32 +0100 Subject: [PATCH 38/45] assert known Java object size --- src/java_bytecode/java_bytecode_convert_class.cpp | 2 -- src/java_bytecode/java_object_factory.cpp | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 049f6b4ead1..113a8b9422d 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -6,8 +6,6 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ -#define DEBUG - #ifdef DEBUG #include #endif diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index c9530c59a19..50e5872abcb 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -126,8 +126,9 @@ exprt java_object_factoryt::allocate_object( // build size expression exprt object_size=size_of_expr(allocate_type, namespacet(symbol_table)); - if(allocate_type.id()!=ID_empty && !object_size.is_nil()) + if(allocate_type.id()!=ID_empty) { + assert(!object_size.is_nil() && "size of Java objects should be known"); // malloc expression exprt malloc_expr=side_effect_exprt(ID_malloc); malloc_expr.copy_to_operands(object_size); From 196dd5b4401bf73cc5da06eb22e120617076c78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 24 Jan 2017 15:16:01 +0100 Subject: [PATCH 39/45] remove unused skip_initialize --- src/java_bytecode/java_object_factory.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index 50e5872abcb..bec79c87e55 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -384,7 +384,6 @@ void java_object_factoryt::gen_nondet_array_init( side_effect_exprt java_new_array(ID_java_new_array, expr.type()); java_new_array.copy_to_operands(length_sym_expr); - java_new_array.set("skip_initialize", true); java_new_array.type().subtype().set(ID_C_element_type, element_type); codet assign=code_assignt(expr, java_new_array); assign.add_source_location()=loc; From 31b25f7b0186d5546dbec0170b6ec5f655fdd378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 24 Jan 2017 18:30:04 +0100 Subject: [PATCH 40/45] remove TODOs from expr2java --- src/java_bytecode/expr2java.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 1da34a5bd37..7fb050dddad 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -50,7 +50,6 @@ std::string expr2javat::convert_code_function_call( unsigned p; std::string lhs_str=convert(src.lhs(), p); - // TODO: if necessery add parentheses, dependent on p dest+=lhs_str; dest+='='; } @@ -95,7 +94,6 @@ std::string expr2javat::convert_code_function_call( first=false; else dest+=", "; - // TODO: if necessery add parentheses, dependent on p dest+=arg_str; } } From c1101eaaeeb0d80e2300f8588583ef871ef6700a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 24 Jan 2017 18:44:17 +0100 Subject: [PATCH 41/45] beautification --- .../java_bytecode_convert_method_class.h | 14 +++++++------- src/java_bytecode/java_bytecode_language.cpp | 2 +- src/java_bytecode/java_bytecode_language.h | 5 +++-- src/java_bytecode/java_bytecode_parser.cpp | 4 ++-- .../java_bytecode_typecheck_expr.cpp | 2 +- src/java_bytecode/java_entry_point.cpp | 10 +++++----- src/java_bytecode/java_local_variable_table.cpp | 16 ++++++++-------- src/java_bytecode/java_object_factory.cpp | 10 +++++----- src/java_bytecode/java_object_factory.h | 4 ++-- src/java_bytecode/java_pointer_casts.cpp | 2 +- 10 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index ca4efee46e3..b5ee7b28f55 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -99,7 +99,7 @@ class java_bytecode_convert_methodt:public messaget codet get_array_bounds_check( const exprt &arraystruct, const exprt &idx, - const source_locationt& original_sloc); + const source_locationt &original_sloc); // return corresponding reference of variable const variablet &find_variable_for_slot( @@ -160,17 +160,17 @@ class java_bytecode_convert_methodt:public messaget protected: void find_initialisers( - local_variable_table_with_holest& vars, - const address_mapt& amap, - const java_cfg_dominatorst& doms); + local_variable_table_with_holest &vars, + const address_mapt &amap, + const java_cfg_dominatorst &doms); void find_initialisers_for_slot( local_variable_table_with_holest::iterator firstvar, local_variable_table_with_holest::iterator varlimit, - const address_mapt& amap, - const java_cfg_dominatorst& doms); + const address_mapt &amap, + const java_cfg_dominatorst &doms); - void setup_local_variables(const methodt& m, const address_mapt& amap); + void setup_local_variables(const methodt &m, const address_mapt &amap); struct block_tree_nodet { diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 4a38e1cf9da..1d9d9f57b41 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -36,7 +36,7 @@ Function: java_bytecode_languaget::get_language_options \*******************************************************************/ -void java_bytecode_languaget::get_language_options(const cmdlinet& cmd) +void java_bytecode_languaget::get_language_options(const cmdlinet &cmd) { disable_runtime_checks=cmd.isset("disable-runtime-check"); assume_inputs_non_null=cmd.isset("java-assume-inputs-non-null"); diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index a62aca0c887..be43a606a8f 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -19,7 +19,7 @@ Author: Daniel Kroening, kroening@kroening.com class java_bytecode_languaget:public languaget { public: - virtual void get_language_options(const cmdlinet&); + virtual void get_language_options(const cmdlinet &); virtual bool preprocess( std::istream &instream, @@ -42,7 +42,8 @@ class java_bytecode_languaget:public languaget virtual ~java_bytecode_languaget(); java_bytecode_languaget(): max_nondet_array_length(MAX_NONDET_ARRAY_LENGTH_DEFAULT), - max_user_array_length(0) { } + max_user_array_length(0) + {} bool from_expr( const exprt &expr, diff --git a/src/java_bytecode/java_bytecode_parser.cpp b/src/java_bytecode/java_bytecode_parser.cpp index 93f082ecb7d..8fdcb6007d6 100644 --- a/src/java_bytecode/java_bytecode_parser.cpp +++ b/src/java_bytecode/java_bytecode_parser.cpp @@ -352,7 +352,7 @@ void java_bytecode_parsert::get_class_refs() } break; - default:{}; + default:{} } } @@ -1243,7 +1243,7 @@ void java_bytecode_parsert::rcode_attribute(methodt &method) } void java_bytecode_parsert::read_verification_type_info( - methodt::verification_type_infot& v) + methodt::verification_type_infot &v) { u1 tag=read_u1(); switch(tag) diff --git a/src/java_bytecode/java_bytecode_typecheck_expr.cpp b/src/java_bytecode/java_bytecode_typecheck_expr.cpp index 069aee1830b..941871d5cd3 100644 --- a/src/java_bytecode/java_bytecode_typecheck_expr.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_expr.cpp @@ -91,7 +91,7 @@ void java_bytecode_typecheckt::typecheck_expr_java_new_array( typecheck_type(type); } -static void escape_non_alnum(std::string& toescape) +static void escape_non_alnum(std::string &toescape) { for(auto &ch : toescape) if(!isalnum(ch)) diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index 67fc10a2fd1..e2c71735fec 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -72,7 +72,7 @@ static void create_initialize(symbol_tablet &symbol_table) } -static bool should_init_symbol(const symbolt& sym) +static bool should_init_symbol(const symbolt &sym) { if(sym.type.id()!=ID_code && sym.is_lvalue && @@ -110,13 +110,13 @@ bool java_static_lifetime_init( // external. Iterate over a copy of the symtab, as its iterators are // invalidated by object_factory: - std::list symnames; + std::list symbol_names; for(const auto &entry : symbol_table.symbols) - symnames.push_back(entry.first); + symbol_names.push_back(entry.first); - for(const auto& symname : symnames) + for(const auto &symname : symbol_names) { - const symbolt& sym=symbol_table.lookup(symname); + const symbolt &sym=symbol_table.lookup(symname); if(should_init_symbol(sym)) { if(sym.value.is_nil() && sym.type!=empty_typet()) diff --git a/src/java_bytecode/java_local_variable_table.cpp b/src/java_bytecode/java_local_variable_table.cpp index dd9e8eee4d1..19580d15094 100644 --- a/src/java_bytecode/java_local_variable_table.cpp +++ b/src/java_bytecode/java_local_variable_table.cpp @@ -156,9 +156,9 @@ Function: gather_transitive_predecessors \*******************************************************************/ static void gather_transitive_predecessors( - local_variable_with_holest* start, + local_variable_with_holest *start, const predecessor_mapt &predecessor_map, - std::set& result) + std::set &result) { if(!result.insert(start).second) return; @@ -251,7 +251,7 @@ Function: populate_variable_address_map static void populate_variable_address_map( local_variable_table_with_holest::iterator firstvar, local_variable_table_with_holest::iterator varlimit, - std::vector& live_variable_at_address) + std::vector &live_variable_at_address) { for(auto it=firstvar, itend=varlimit; it!=itend; ++it) { @@ -298,7 +298,7 @@ Function: populate_predecessor_map static void populate_predecessor_map( local_variable_table_with_holest::iterator firstvar, local_variable_table_with_holest::iterator varlimit, - const std::vector& live_variable_at_address, + const std::vector &live_variable_at_address, const address_mapt &amap, predecessor_mapt &predecessor_map, message_handlert &msg_handler) @@ -480,7 +480,7 @@ Function: populate_live_range_holes static void populate_live_range_holes( local_variable_with_holest &merge_into, - const std::set& merge_vars, + const std::set &merge_vars, unsigned expanded_live_range_start) { std::vector sorted_by_startpc( @@ -518,7 +518,7 @@ Function: merge_variable_table_entries static void merge_variable_table_entries( local_variable_with_holest &merge_into, - const std::set& merge_vars, + const std::set &merge_vars, const java_cfg_dominatorst &dominator_analysis, std::ostream &debug_out) { @@ -729,7 +729,7 @@ Function: cleanup_var_table \*******************************************************************/ static void cleanup_var_table( - std::vector& vars_with_holes) + std::vector &vars_with_holes) { size_t toremove=0; for(size_t i=0; i<(vars_with_holes.size()-toremove); ++i) @@ -795,7 +795,7 @@ void java_bytecode_convert_methodt::setup_local_variables( // to calculate which variable to use, one uses the address of the instruction // that uses the variable, the size of the instruction and the start_pc / // length values in the local variable table - for(const auto & v : vars_with_holes) + for(const auto &v : vars_with_holes) { if(v.var.start_pc==0) // Parameter? continue; diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index bec79c87e55..f8f3d98748f 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -49,7 +49,7 @@ class java_object_factoryt:public messaget public: java_object_factoryt( - code_blockt& _init_code, + code_blockt &_init_code, bool _assume_non_null, size_t _max_nondet_array_length, symbol_tablet &_symbol_table, @@ -63,8 +63,8 @@ class java_object_factoryt:public messaget {} exprt allocate_object( - const exprt&, - const typet&, + const exprt &, + const typet &, const source_locationt &, bool create_dynamic_objects); @@ -512,7 +512,7 @@ Function: new_tmp_symbol \*******************************************************************/ -symbolt &new_tmp_symbol(symbol_tablet &symbol_table, const std::string& prefix) +symbolt &new_tmp_symbol(symbol_tablet &symbol_table, const std::string &prefix) { static size_t temporary_counter=0; // TODO encapsulate as class variable @@ -542,7 +542,7 @@ Function: get_nondet_bool \*******************************************************************/ -exprt get_nondet_bool(const typet& type) +exprt get_nondet_bool(const typet &type) { // We force this to 0 and 1 and won't consider // other values. diff --git a/src/java_bytecode/java_object_factory.h b/src/java_bytecode/java_object_factory.h index 13d933d9da5..d111948e365 100644 --- a/src/java_bytecode/java_object_factory.h +++ b/src/java_bytecode/java_object_factory.h @@ -34,10 +34,10 @@ void gen_nondet_init( size_t max_nondet_array_length=5); -exprt get_nondet_bool(const typet&); +exprt get_nondet_bool(const typet &); symbolt &new_tmp_symbol( symbol_tablet &symbol_table, - const std::string& prefix="tmp_object_factory"); + const std::string &prefix="tmp_object_factory"); #endif // CPROVER_JAVA_BYTECODE_JAVA_OBJECT_FACTORY_H diff --git a/src/java_bytecode/java_pointer_casts.cpp b/src/java_bytecode/java_pointer_casts.cpp index 934e6cfb135..174bad0a9b1 100644 --- a/src/java_bytecode/java_pointer_casts.cpp +++ b/src/java_bytecode/java_pointer_casts.cpp @@ -89,7 +89,7 @@ Function: look_through_casts \*******************************************************************/ -static const exprt& look_through_casts(const exprt& in) +static const exprt &look_through_casts(const exprt &in) { if(in.id()==ID_typecast) { From 5e6f7efc0a9505948a8268f8eeb31534af233d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Tue, 24 Jan 2017 18:48:30 +0100 Subject: [PATCH 42/45] change "* "->" *", too --- .../java_local_variable_table.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/java_bytecode/java_local_variable_table.cpp b/src/java_bytecode/java_local_variable_table.cpp index 19580d15094..3cfb5030136 100644 --- a/src/java_bytecode/java_local_variable_table.cpp +++ b/src/java_bytecode/java_local_variable_table.cpp @@ -109,8 +109,8 @@ static bool lt_index( return a.var.indexvar.start_pcvar.start_pc; } @@ -118,8 +118,8 @@ static bool lt_startpc( // The predecessor map, and a top-sorting comparator: typedef std::map< - local_variable_with_holest*, - std::set > + local_variable_with_holest *, + std::set > predecessor_mapt; struct is_predecessor_oft @@ -129,8 +129,8 @@ struct is_predecessor_oft explicit is_predecessor_oft(const predecessor_mapt &_order) : order(_order) {} bool operator()( - local_variable_with_holest* a, - local_variable_with_holest* b) const + local_variable_with_holest *a, + local_variable_with_holest *b) const { auto findit=order.find(a); if(findit==order.end()) @@ -483,7 +483,7 @@ static void populate_live_range_holes( const std::set &merge_vars, unsigned expanded_live_range_start) { - std::vector sorted_by_startpc( + std::vector sorted_by_startpc( merge_vars.begin(), merge_vars.end()); std::sort(sorted_by_startpc.begin(), sorted_by_startpc.end(), lt_startpc); @@ -591,7 +591,7 @@ void java_bytecode_convert_methodt::find_initialisers_for_slot( // Build a simple map from instruction PC to the variable // live in this slot at that PC, and a map from each variable // to variables that flow into it: - std::vector live_variable_at_address; + std::vector live_variable_at_address; populate_variable_address_map(firstvar, varlimit, live_variable_at_address); // Now find variables that flow together by @@ -612,14 +612,14 @@ void java_bytecode_convert_methodt::find_initialisers_for_slot( // Take the transitive closure of the predecessor map: for(auto &kv : predecessor_map) { - std::set closed_preds; + std::set closed_preds; gather_transitive_predecessors(kv.first, predecessor_map, closed_preds); kv.second=std::move(closed_preds); } // Top-sort so that we get the bottom variables first: is_predecessor_oft comp(predecessor_map); - std::vector topsorted_vars; + std::vector topsorted_vars; for(auto it=firstvar, itend=varlimit; it!=itend; ++it) topsorted_vars.push_back(&*it); From 669a5b0bb5f483eec2101eb1bf2b4988deb16c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Wed, 25 Jan 2017 21:32:45 +0100 Subject: [PATCH 43/45] adapt NullPointer2 regression test --- regression/cbmc-java/NullPointer2/test.desc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regression/cbmc-java/NullPointer2/test.desc b/regression/cbmc-java/NullPointer2/test.desc index a794ca8ac88..f89103d5f52 100644 --- a/regression/cbmc-java/NullPointer2/test.desc +++ b/regression/cbmc-java/NullPointer2/test.desc @@ -3,7 +3,7 @@ NullPointer2.class --pointer-check --stop-on-fail ^EXIT=10$ ^SIGNAL=0$ -^ file NullPointer2.java line 9 function java::NullPointer2.main:(\[Ljava/lang/String;)V bytecode_index 1$ +^ file NullPointer2.java line 9 function java::NullPointer2.main:(\[Ljava/lang/String;)V$ ^VERIFICATION FAILED$ -- ^warning: ignoring From eb71f2c0a8421e0b6f7b7ba7668b81aa8c7f2100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Wed, 25 Jan 2017 22:14:23 +0100 Subject: [PATCH 44/45] adapt interface in CEGIS with default values --- src/cegis/refactor/constraint/constraint_factory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cegis/refactor/constraint/constraint_factory.cpp b/src/cegis/refactor/constraint/constraint_factory.cpp index abe6d33e4fa..42a2c324f71 100644 --- a/src/cegis/refactor/constraint/constraint_factory.cpp +++ b/src/cegis/refactor/constraint/constraint_factory.cpp @@ -41,7 +41,7 @@ void create_or_redirect_entry(symbol_tablet &st, goto_functionst &gf) if (fmap.end() == it) { config.main=CONSTRAINT_CALLER; - assert(!java_entry_point(st, ID_empty, msg)); + assert(!java_entry_point(st, ID_empty, msg, false, 0)); goto_convert(CPROVER_INIT, st, gf, msg); goto_convert(goto_functionst::entry_point(), st, gf, msg); } else From a0e251feffc2c21e41313fa9906c5be26de9cd48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Wed, 25 Jan 2017 22:21:31 +0100 Subject: [PATCH 45/45] whitespace in front of { --- src/java_bytecode/java_bytecode_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java_bytecode/java_bytecode_parser.cpp b/src/java_bytecode/java_bytecode_parser.cpp index 8fdcb6007d6..7138ab3951b 100644 --- a/src/java_bytecode/java_bytecode_parser.cpp +++ b/src/java_bytecode/java_bytecode_parser.cpp @@ -352,7 +352,7 @@ void java_bytecode_parsert::get_class_refs() } break; - default:{} + default: {} } }