Skip to content

Commit 10d7cf3

Browse files
Update Java bytecode parser to always load code attributes
Previously it didn't load code attributes when skip_instructions was set Now this flag just skips the actual instructions and the exceptions table This means it will have the local variable table, which will allow us to retrieve parameter names Updated unit test to check for this
1 parent a504983 commit 10d7cf3

File tree

5 files changed

+56
-22
lines changed

5 files changed

+56
-22
lines changed

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,35 +1222,44 @@ void java_bytecode_parsert::rmethod_attribute(methodt &method)
12221222

12231223
irep_idt attribute_name=pool_entry(attribute_name_index).s;
12241224

1225-
if(attribute_name == "Code" && !skip_instructions)
1225+
if(attribute_name == "Code")
12261226
{
12271227
UNUSED_u2(max_stack);
12281228
UNUSED_u2(max_locals);
12291229

1230-
rbytecode(method.instructions);
1230+
if(skip_instructions)
1231+
skip_bytes(read_u4());
1232+
else
1233+
rbytecode(method.instructions);
12311234

12321235
u2 exception_table_length=read_u2();
1233-
method.exception_table.resize(exception_table_length);
1234-
1235-
for(std::size_t e=0; e<exception_table_length; e++)
1236+
if(skip_instructions)
1237+
skip_bytes(exception_table_length * 8u);
1238+
else
12361239
{
1237-
u2 start_pc=read_u2();
1238-
u2 end_pc=read_u2();
1240+
method.exception_table.resize(exception_table_length);
12391241

1240-
// from the class file format spec ("4.7.3. The Code Attribute" for Java8)
1241-
INVARIANT(
1242-
start_pc < end_pc,
1243-
"The start_pc must be less than the end_pc as this is the range the "
1244-
"exception is active");
1245-
1246-
u2 handler_pc=read_u2();
1247-
u2 catch_type=read_u2();
1248-
method.exception_table[e].start_pc=start_pc;
1249-
method.exception_table[e].end_pc=end_pc;
1250-
method.exception_table[e].handler_pc=handler_pc;
1251-
if(catch_type!=0)
1252-
method.exception_table[e].catch_type =
1253-
to_struct_tag_type(pool_entry(catch_type).expr.type());
1242+
for(std::size_t e = 0; e < exception_table_length; e++)
1243+
{
1244+
u2 start_pc = read_u2();
1245+
u2 end_pc = read_u2();
1246+
1247+
// From the class file format spec ("4.7.3. The Code Attribute" for
1248+
// Java8)
1249+
INVARIANT(
1250+
start_pc < end_pc,
1251+
"The start_pc must be less than the end_pc as this is the range the "
1252+
"exception is active");
1253+
1254+
u2 handler_pc = read_u2();
1255+
u2 catch_type = read_u2();
1256+
method.exception_table[e].start_pc = start_pc;
1257+
method.exception_table[e].end_pc = end_pc;
1258+
method.exception_table[e].handler_pc = handler_pc;
1259+
if(catch_type != 0)
1260+
method.exception_table[e].catch_type =
1261+
to_struct_tag_type(pool_entry(catch_type).expr.type());
1262+
}
12541263
}
12551264

12561265
u2 attributes_count=read_u2();
Binary file not shown.
Binary file not shown.

jbmc/unit/java_bytecode/java_bytecode_parser/Trivial.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ public class Trivial {
33
public class Inner {
44
@Annotation
55
private int x;
6+
67
public Inner() { x = 1; }
8+
79
@Annotation
8-
public void f() { x++; };
10+
public void f(int y) {
11+
try {
12+
x++;
13+
} catch(Exception ex) {
14+
}
15+
}
916
}
1017
}

jbmc/unit/java_bytecode/java_bytecode_parser/parse_class_without_instructions.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,14 @@ static void check_class_structure(
4141

4242
REQUIRE(method_f.is_public);
4343
REQUIRE(method_f.annotations.size() == 1);
44+
REQUIRE(method_f.local_variable_table.size() == 2);
45+
REQUIRE(method_f.local_variable_table[0].name == "this");
46+
REQUIRE(method_f.local_variable_table[1].name == "y");
4447
REQUIRE(method_constructor.is_public);
4548
REQUIRE(method_constructor.annotations.size() == 0);
49+
REQUIRE(method_f.local_variable_table.size() == 2);
50+
REQUIRE(method_constructor.local_variable_table[0].name == "this");
51+
REQUIRE(method_constructor.local_variable_table[1].name == "this$0");
4652
}
4753

4854
SCENARIO(
@@ -72,6 +78,12 @@ SCENARIO(
7278
REQUIRE(methodone.instructions.size() == 0);
7379
REQUIRE(methodtwo.instructions.size() == 0);
7480
}
81+
82+
THEN("Neither method should have an exception table")
83+
{
84+
REQUIRE(methodone.exception_table.empty());
85+
REQUIRE(methodtwo.exception_table.empty());
86+
}
7587
}
7688
}
7789
}
@@ -99,6 +111,12 @@ SCENARIO(
99111
REQUIRE(methodone.instructions.size() != 0);
100112
REQUIRE(methodtwo.instructions.size() != 0);
101113
}
114+
115+
const auto &method_f = methodone.name == "f" ? methodone : methodtwo;
116+
THEN("f should have an exception table")
117+
{
118+
REQUIRE(!method_f.exception_table.empty());
119+
}
102120
}
103121
}
104122
}

0 commit comments

Comments
 (0)