From ac6c7d4ed926522b15ef9792c99ee2d493cb87ca Mon Sep 17 00:00:00 2001 From: johndumbell Date: Tue, 24 Jul 2018 15:29:14 +0100 Subject: [PATCH] Parse java arrays in annotations properly Previously the value from the arrays was being parsed correctly but into an object which was then immediately thrown away, so the value was never really used. --- .../java_bytecode/java_bytecode_parser.cpp | 33 ++++++++---------- .../AnnotationWithStringArray.class | Bin 0 -> 239 bytes .../AnnotationWithStringArray.java | 3 ++ .../ClassWithArrayAnnotation.class | Bin 0 -> 410 bytes .../ClassWithArrayAnnotation.java | 3 ++ .../parse_java_annotations.cpp | 25 +++++++++++++ 6 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 jbmc/unit/java_bytecode/java_bytecode_parser/AnnotationWithStringArray.class create mode 100644 jbmc/unit/java_bytecode/java_bytecode_parser/AnnotationWithStringArray.java create mode 100644 jbmc/unit/java_bytecode/java_bytecode_parser/ClassWithArrayAnnotation.class create mode 100644 jbmc/unit/java_bytecode/java_bytecode_parser/ClassWithArrayAnnotation.java diff --git a/jbmc/src/java_bytecode/java_bytecode_parser.cpp b/jbmc/src/java_bytecode/java_bytecode_parser.cpp index 57301eff756..45e8f51e76a 100644 --- a/jbmc/src/java_bytecode/java_bytecode_parser.cpp +++ b/jbmc/src/java_bytecode/java_bytecode_parser.cpp @@ -126,7 +126,7 @@ class java_bytecode_parsert:public parsert void rRuntimeAnnotation_attribute(annotationst &); void rRuntimeAnnotation(annotationt &); void relement_value_pairs(annotationt::element_value_pairst &); - void relement_value_pair(annotationt::element_value_pairt &); + exprt get_relement_value(); void rmethod_attribute(methodt &method); void rfield_attribute(fieldt &); void rcode_attribute(methodt &method); @@ -1511,16 +1511,17 @@ void java_bytecode_parsert::relement_value_pairs( { u2 element_name_index=read_u2(); element_value_pair.element_name=pool_entry(element_name_index).s; - - relement_value_pair(element_value_pair); + element_value_pair.value = get_relement_value(); } } /// Corresponds to the element_value structure /// Described in Java 8 specification 4.7.16.1 /// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.16.1 -void java_bytecode_parsert::relement_value_pair( - annotationt::element_value_pairt &element_value_pair) +/// \returns An exprt that represents the particular value of annotations field. +/// This is usually one of: a byte, number of some sort, string, character, +/// enum, Class type, array or another annotation. +exprt java_bytecode_parsert::get_relement_value() { u1 tag=read_u1(); @@ -1531,50 +1532,46 @@ void java_bytecode_parsert::relement_value_pair( UNUSED_u2(type_name_index); UNUSED_u2(const_name_index); // todo: enum + return exprt(); } - break; case 'c': { u2 class_info_index = read_u2(); - element_value_pair.value = symbol_exprt(pool_entry(class_info_index).s); + return symbol_exprt(pool_entry(class_info_index).s); } - break; case '@': { + // TODO: return this wrapped in an exprt // another annotation, recursively annotationt annotation; rRuntimeAnnotation(annotation); + return exprt(); } - break; case '[': { + array_exprt values; u2 num_values=read_u2(); for(std::size_t i=0; ip zgns5(Ny;d#a$e53mX`mEt|?^AaF|X?Ue_FMp&<&Pk1dVh z!ecmCXU{OO1H>g)^Y}4ah}_@=4t &java_annotations = + to_annotated_type(class_symbol.type).get_annotations(); + java_bytecode_parse_treet::annotationst annotations; + convert_java_annotations(java_annotations, annotations); + REQUIRE(annotations.size() == 1); + const auto &annotation = annotations.front(); + const auto &element_value_pair = annotation.element_value_pairs.front(); + const auto &array = to_array_expr(element_value_pair.value); + + REQUIRE(array.operands().size() == 2); + const auto &dave = array.op0().get(ID_value); + const auto &another_dave = array.op1().get(ID_value); + REQUIRE(id2string(dave) == "Dave"); + REQUIRE(id2string(another_dave) == "Another Dave"); + } + } } }