Skip to content

Commit d0be385

Browse files
author
owen-jones-diffblue
authored
Merge pull request #2619 from JohnDumbell/jd/bugfix/java_annotation_array_fix
Parse java arrays in annotations properly
2 parents 1ad6b5d + ac6c7d4 commit d0be385

File tree

6 files changed

+46
-18
lines changed

6 files changed

+46
-18
lines changed

jbmc/src/java_bytecode/java_bytecode_parser.cpp

+15-18
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class java_bytecode_parsert:public parsert
126126
void rRuntimeAnnotation_attribute(annotationst &);
127127
void rRuntimeAnnotation(annotationt &);
128128
void relement_value_pairs(annotationt::element_value_pairst &);
129-
void relement_value_pair(annotationt::element_value_pairt &);
129+
exprt get_relement_value();
130130
void rmethod_attribute(methodt &method);
131131
void rfield_attribute(fieldt &);
132132
void rcode_attribute(methodt &method);
@@ -1511,16 +1511,17 @@ void java_bytecode_parsert::relement_value_pairs(
15111511
{
15121512
u2 element_name_index=read_u2();
15131513
element_value_pair.element_name=pool_entry(element_name_index).s;
1514-
1515-
relement_value_pair(element_value_pair);
1514+
element_value_pair.value = get_relement_value();
15161515
}
15171516
}
15181517

15191518
/// Corresponds to the element_value structure
15201519
/// Described in Java 8 specification 4.7.16.1
15211520
/// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.16.1
1522-
void java_bytecode_parsert::relement_value_pair(
1523-
annotationt::element_value_pairt &element_value_pair)
1521+
/// \returns An exprt that represents the particular value of annotations field.
1522+
/// This is usually one of: a byte, number of some sort, string, character,
1523+
/// enum, Class type, array or another annotation.
1524+
exprt java_bytecode_parsert::get_relement_value()
15241525
{
15251526
u1 tag=read_u1();
15261527

@@ -1531,50 +1532,46 @@ void java_bytecode_parsert::relement_value_pair(
15311532
UNUSED_u2(type_name_index);
15321533
UNUSED_u2(const_name_index);
15331534
// todo: enum
1535+
return exprt();
15341536
}
1535-
break;
15361537

15371538
case 'c':
15381539
{
15391540
u2 class_info_index = read_u2();
1540-
element_value_pair.value = symbol_exprt(pool_entry(class_info_index).s);
1541+
return symbol_exprt(pool_entry(class_info_index).s);
15411542
}
1542-
break;
15431543

15441544
case '@':
15451545
{
1546+
// TODO: return this wrapped in an exprt
15461547
// another annotation, recursively
15471548
annotationt annotation;
15481549
rRuntimeAnnotation(annotation);
1550+
return exprt();
15491551
}
1550-
break;
15511552

15521553
case '[':
15531554
{
1555+
array_exprt values;
15541556
u2 num_values=read_u2();
15551557
for(std::size_t i=0; i<num_values; i++)
15561558
{
1557-
annotationt::element_value_pairt element_value;
1558-
relement_value_pair(element_value); // recursive call
1559+
values.operands().push_back(get_relement_value());
15591560
}
1561+
return values;
15601562
}
1561-
break;
15621563

15631564
case 's':
15641565
{
15651566
u2 const_value_index=read_u2();
1566-
element_value_pair.value=string_constantt(
1567-
pool_entry(const_value_index).s);
1567+
return string_constantt(pool_entry(const_value_index).s);
15681568
}
1569-
break;
15701569

15711570
default:
15721571
{
15731572
u2 const_value_index=read_u2();
1574-
element_value_pair.value=constant(const_value_index);
1573+
return constant(const_value_index);
15751574
}
1576-
1577-
break;
15781575
}
15791576
}
15801577

Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public @interface AnnotationWithStringArray {
2+
String[] value() default {};
3+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@AnnotationWithStringArray({"Dave", "Another Dave"})
2+
public class ClassWithArrayAnnotation {
3+
}

jbmc/unit/java_bytecode/java_bytecode_parser/parse_java_annotations.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,30 @@ SCENARIO(
9191
REQUIRE(java_type == void_type());
9292
}
9393
}
94+
WHEN("Parsing an annotation with an array field.")
95+
{
96+
const symbol_tablet &new_symbol_table = load_java_class(
97+
"ClassWithArrayAnnotation", "./java_bytecode/java_bytecode_parser");
98+
99+
THEN("The annotation should store an array of type string.")
100+
{
101+
const symbolt &class_symbol =
102+
*new_symbol_table.lookup("java::ClassWithArrayAnnotation");
103+
const std::vector<java_annotationt> &java_annotations =
104+
to_annotated_type(class_symbol.type).get_annotations();
105+
java_bytecode_parse_treet::annotationst annotations;
106+
convert_java_annotations(java_annotations, annotations);
107+
REQUIRE(annotations.size() == 1);
108+
const auto &annotation = annotations.front();
109+
const auto &element_value_pair = annotation.element_value_pairs.front();
110+
const auto &array = to_array_expr(element_value_pair.value);
111+
112+
REQUIRE(array.operands().size() == 2);
113+
const auto &dave = array.op0().get(ID_value);
114+
const auto &another_dave = array.op1().get(ID_value);
115+
REQUIRE(id2string(dave) == "Dave");
116+
REQUIRE(id2string(another_dave) == "Another Dave");
117+
}
118+
}
94119
}
95120
}

0 commit comments

Comments
 (0)