Skip to content

Commit 442010f

Browse files
committed
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.
1 parent bcb7c76 commit 442010f

File tree

6 files changed

+45
-18
lines changed

6 files changed

+45
-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

+24
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,29 @@ 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 = to_annotated_type(class_symbol.type).get_annotations();
104+
java_bytecode_parse_treet::annotationst annotations;
105+
convert_java_annotations(java_annotations, annotations);
106+
REQUIRE(annotations.size() == 1);
107+
const auto &annotation = annotations.front();
108+
const auto &element_value_pair = annotation.element_value_pairs.front();
109+
const auto &array = to_array_expr(element_value_pair.value);
110+
111+
REQUIRE(array.operands().size() == 2);
112+
const auto &dave = array.op0().get(ID_value);
113+
const auto &another_dave = array.op1().get(ID_value);
114+
REQUIRE(id2string(dave) == "Dave");
115+
REQUIRE(id2string(another_dave) == "Another Dave");
116+
}
117+
}
94118
}
95119
}

0 commit comments

Comments
 (0)