Merge pull request #4405 from NathanJPhillips/feature/skip-instrs-not-atts

Update Java bytecode parser to always load code attributes
This commit is contained in:
Nathan Phillips 2019-03-19 14:20:29 +00:00 committed by GitHub
commit 391738d670
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 21 deletions

View File

@ -1222,35 +1222,44 @@ void java_bytecode_parsert::rmethod_attribute(methodt &method)
irep_idt attribute_name=pool_entry(attribute_name_index).s;
if(attribute_name == "Code" && !skip_instructions)
if(attribute_name == "Code")
{
UNUSED_u2(max_stack);
UNUSED_u2(max_locals);
rbytecode(method.instructions);
if(skip_instructions)
skip_bytes(read_u4());
else
rbytecode(method.instructions);
u2 exception_table_length=read_u2();
method.exception_table.resize(exception_table_length);
for(std::size_t e=0; e<exception_table_length; e++)
if(skip_instructions)
skip_bytes(exception_table_length * 8u);
else
{
u2 start_pc=read_u2();
u2 end_pc=read_u2();
method.exception_table.resize(exception_table_length);
// from the class file format spec ("4.7.3. The Code Attribute" for Java8)
INVARIANT(
start_pc < end_pc,
"The start_pc must be less than the end_pc as this is the range the "
"exception is active");
for(std::size_t e = 0; e < exception_table_length; e++)
{
u2 start_pc = read_u2();
u2 end_pc = read_u2();
u2 handler_pc=read_u2();
u2 catch_type=read_u2();
method.exception_table[e].start_pc=start_pc;
method.exception_table[e].end_pc=end_pc;
method.exception_table[e].handler_pc=handler_pc;
if(catch_type!=0)
method.exception_table[e].catch_type =
to_struct_tag_type(pool_entry(catch_type).expr.type());
// From the class file format spec ("4.7.3. The Code Attribute" for
// Java8)
INVARIANT(
start_pc < end_pc,
"The start_pc must be less than the end_pc as this is the range the "
"exception is active");
u2 handler_pc = read_u2();
u2 catch_type = read_u2();
method.exception_table[e].start_pc = start_pc;
method.exception_table[e].end_pc = end_pc;
method.exception_table[e].handler_pc = handler_pc;
if(catch_type != 0)
method.exception_table[e].catch_type =
to_struct_tag_type(pool_entry(catch_type).expr.type());
}
}
u2 attributes_count=read_u2();

View File

@ -3,8 +3,15 @@ public class Trivial {
public class Inner {
@Annotation
private int x;
public Inner() { x = 1; }
@Annotation
public void f() { x++; };
public void f(int y) {
try {
x++;
} catch(Exception ex) {
}
}
}
}

View File

@ -41,8 +41,14 @@ static void check_class_structure(
REQUIRE(method_f.is_public);
REQUIRE(method_f.annotations.size() == 1);
REQUIRE(method_f.local_variable_table.size() == 2);
REQUIRE(method_f.local_variable_table[0].name == "this");
REQUIRE(method_f.local_variable_table[1].name == "y");
REQUIRE(method_constructor.is_public);
REQUIRE(method_constructor.annotations.size() == 0);
REQUIRE(method_f.local_variable_table.size() == 2);
REQUIRE(method_constructor.local_variable_table[0].name == "this");
REQUIRE(method_constructor.local_variable_table[1].name == "this$0");
}
SCENARIO(
@ -72,6 +78,12 @@ SCENARIO(
REQUIRE(methodone.instructions.size() == 0);
REQUIRE(methodtwo.instructions.size() == 0);
}
THEN("Neither method should have an exception table")
{
REQUIRE(methodone.exception_table.empty());
REQUIRE(methodtwo.exception_table.empty());
}
}
}
}
@ -99,6 +111,12 @@ SCENARIO(
REQUIRE(methodone.instructions.size() != 0);
REQUIRE(methodtwo.instructions.size() != 0);
}
const auto &method_f = methodone.name == "f" ? methodone : methodtwo;
THEN("f should have an exception table")
{
REQUIRE(!method_f.exception_table.empty());
}
}
}
}