Skip to content

Commit 5e633f1

Browse files
committed
Java bytecode front-end: do not crash upon invalid class names
Do not make unchecked use of the result of `java_type_from_string`. Fixes: #728 Fixes: #849
1 parent 4fe3ade commit 5e633f1

File tree

4 files changed

+60
-22
lines changed

4 files changed

+60
-22
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,11 @@ void java_bytecode_convert_classt::convert(
677677
}
678678
}
679679
else
680-
field_type = *java_type_from_string(f.descriptor);
680+
{
681+
auto type_opt = java_type_from_string(f.descriptor);
682+
CHECK_RETURN(type_opt.has_value());
683+
field_type = *type_opt;
684+
}
681685

682686
// determine access
683687
irep_idt access;

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ class java_bytecode_parsert final : public parsert
8585

8686
const typet type_entry(u2 index)
8787
{
88-
return *java_type_from_string(id2string(pool_entry(index).s));
88+
auto type_opt = java_type_from_string(id2string(pool_entry(index).s));
89+
CHECK_RETURN(type_opt.has_value());
90+
return std::move(*type_opt);
8991
}
9092

9193
void rClassFile();
@@ -408,6 +410,12 @@ bool java_bytecode_parsert::parse()
408410
return true;
409411
}
410412

413+
catch(const unsupported_java_class_signature_exceptiont &e)
414+
{
415+
log.error() << e.str() << messaget::eom;
416+
return true;
417+
}
418+
411419
catch(...)
412420
{
413421
log.error() << "parsing error" << messaget::eom;
@@ -514,8 +522,11 @@ void java_bytecode_parsert::get_class_refs()
514522
break;
515523

516524
case CONSTANT_NameAndType:
517-
get_class_refs_rec(
518-
*java_type_from_string(id2string(pool_entry(c.ref2).s)));
525+
{
526+
auto type_opt = java_type_from_string(id2string(pool_entry(c.ref2).s));
527+
CHECK_RETURN(type_opt.has_value());
528+
get_class_refs_rec(*type_opt);
529+
}
519530
break;
520531

521532
default: {}
@@ -543,7 +554,9 @@ void java_bytecode_parsert::get_class_refs()
543554
}
544555
else
545556
{
546-
get_class_refs_rec(*java_type_from_string(field.descriptor));
557+
auto type_opt = java_type_from_string(field.descriptor);
558+
CHECK_RETURN(type_opt);
559+
get_class_refs_rec(*type_opt);
547560
}
548561
}
549562

@@ -565,7 +578,9 @@ void java_bytecode_parsert::get_class_refs()
565578
}
566579
else
567580
{
568-
get_class_refs_rec(*java_type_from_string(method.descriptor));
581+
auto type_opt = java_type_from_string(method.descriptor);
582+
CHECK_RETURN(type_opt);
583+
get_class_refs_rec(*type_opt);
569584
}
570585

571586
for(const auto &var : method.local_variable_table)
@@ -582,7 +597,9 @@ void java_bytecode_parsert::get_class_refs()
582597
}
583598
else
584599
{
585-
get_class_refs_rec(*java_type_from_string(var.descriptor));
600+
auto type_opt = java_type_from_string(var.descriptor);
601+
CHECK_RETURN(type_opt.has_value());
602+
get_class_refs_rec(*type_opt);
586603
}
587604
}
588605
}
@@ -637,7 +654,9 @@ void java_bytecode_parsert::get_annotation_value_class_refs(const exprt &value)
637654
if(const auto &symbol_expr = expr_try_dynamic_cast<symbol_exprt>(value))
638655
{
639656
const irep_idt &value_id = symbol_expr->get_identifier();
640-
get_class_refs_rec(*java_type_from_string(id2string(value_id)));
657+
auto type_opt = java_type_from_string(id2string(value_id));
658+
CHECK_RETURN(type_opt.has_value());
659+
get_class_refs_rec(*type_opt);
641660
}
642661
else if(const auto &array_expr = expr_try_dynamic_cast<array_exprt>(value))
643662
{
@@ -1967,13 +1986,14 @@ java_bytecode_parsert::parse_method_handle(const method_handle_infot &entry)
19671986
irep_idt method_name = name_and_type.get_name(pool_entry_lambda);
19681987
std::string descriptor = name_and_type.get_descriptor(pool_entry_lambda);
19691988
irep_idt mangled_method_name = id2string(method_name) + ":" + descriptor;
1970-
typet method_type = *java_type_from_string(descriptor);
1989+
auto method_type_opt = java_type_from_string(descriptor);
1990+
CHECK_RETURN(method_type_opt.has_value());
19711991

19721992
method_handle_typet handle_type =
19731993
get_method_handle_type(entry.get_handle_kind());
19741994

19751995
class_method_descriptor_exprt method_descriptor{
1976-
method_type, mangled_method_name, class_name, method_name};
1996+
*method_type, mangled_method_name, class_name, method_name};
19771997
lambda_method_handlet lambda_method_handle{method_descriptor, handle_type};
19781998

19791999
return lambda_method_handle;

jbmc/src/java_bytecode/java_entry_point.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ bool is_java_main(const symbolt &function)
307307
bool named_main = has_suffix(id2string(function.name), JAVA_MAIN_METHOD);
308308
const java_method_typet &function_type = to_java_method_type(function.type);
309309
const auto string_array_type = java_type_from_string("[Ljava/lang/String;");
310+
CHECK_RETURN(string_array_type.has_value());
310311
// checks whether the function is static and has a single String[] parameter
311312
bool is_static = !function_type.has_this();
312313
// this should be implied by the signature

jbmc/src/java_bytecode/java_types.cpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -624,10 +624,14 @@ std::optional<typet> java_type_from_string(
624624
{
625625
std::size_t e_pos=src.rfind(')');
626626
if(e_pos==std::string::npos)
627-
return {};
627+
{
628+
throw unsupported_java_class_signature_exceptiont(
629+
"Failed to find function signature closing delimiter");
630+
}
628631

629632
auto return_type = java_type_from_string(
630633
std::string(src, e_pos + 1, std::string::npos), class_name_prefix);
634+
CHECK_RETURN(return_type.has_value());
631635

632636
std::vector<typet> param_types =
633637
parse_list_types(src.substr(0, e_pos + 1), class_name_prefix, '(', ')');
@@ -648,10 +652,14 @@ std::optional<typet> java_type_from_string(
648652
// If this is a reference array, we generate a plain array[reference]
649653
// with void* members, but note the real type in ID_element_type.
650654
if(src.size()<=1)
651-
return {};
655+
{
656+
throw unsupported_java_class_signature_exceptiont(
657+
"Failed to find array signature closing delimiter");
658+
}
652659
char subtype_letter=src[1];
653660
auto subtype = java_type_from_string(
654661
src.substr(1, std::string::npos), class_name_prefix);
662+
CHECK_RETURN(subtype.has_value());
655663
if(subtype_letter=='L' || // [L denotes a reference array of some sort.
656664
subtype_letter=='[' || // Array-of-arrays
657665
subtype_letter=='T') // Array of generic types
@@ -681,11 +689,11 @@ std::optional<typet> java_type_from_string(
681689
INVARIANT(src[src.size()-1]==';', "Generic type name must end on ';'.");
682690
PRECONDITION(!class_name_prefix.empty());
683691
irep_idt type_var_name(class_name_prefix+"::"+src.substr(1, src.size()-2));
692+
auto lang_object = java_type_from_string("Ljava/lang/Object;");
693+
CHECK_RETURN(lang_object.has_value());
684694
return java_generic_parametert(
685695
type_var_name,
686-
to_struct_tag_type(
687-
to_java_reference_type(*java_type_from_string("Ljava/lang/Object;"))
688-
.base_type()));
696+
to_struct_tag_type(to_java_reference_type(*lang_object).base_type()));
689697
}
690698
case 'L':
691699
{
@@ -781,13 +789,13 @@ std::vector<typet> java_generic_type_from_string(
781789

782790
std::string type_var_name(
783791
"java::"+class_name+"::"+signature.substr(0, bound_sep));
784-
std::string bound_type(signature.substr(bound_sep+1, var_sep-bound_sep));
785-
792+
std::string bound_type_str(
793+
signature.substr(bound_sep + 1, var_sep - bound_sep));
794+
auto bound_type = java_type_from_string(bound_type_str, class_name);
795+
CHECK_RETURN(bound_type.has_value());
786796
java_generic_parametert type_var_type(
787797
type_var_name,
788-
to_struct_tag_type(
789-
to_java_reference_type(*java_type_from_string(bound_type, class_name))
790-
.base_type()));
798+
to_struct_tag_type(to_java_reference_type(*bound_type).base_type()));
791799

792800
types.push_back(type_var_type);
793801
signature=signature.substr(var_sep+1, std::string::npos);
@@ -809,8 +817,11 @@ static std::string slash_to_dot(const std::string &src)
809817
struct_tag_typet java_classname(const std::string &id)
810818
{
811819
if(!id.empty() && id[0]=='[')
812-
return to_struct_tag_type(
813-
to_java_reference_type(*java_type_from_string(id)).base_type());
820+
{
821+
auto array_type = java_type_from_string(id);
822+
CHECK_RETURN(array_type.has_value());
823+
return to_struct_tag_type(to_java_reference_type(*array_type).base_type());
824+
}
814825

815826
std::string class_name=id;
816827

@@ -1014,6 +1025,7 @@ void get_dependencies_from_generic_parameters(
10141025
{
10151026
auto type_from_string =
10161027
java_type_from_string(signature, erase_type_arguments(signature));
1028+
CHECK_RETURN(type_from_string.has_value());
10171029
get_dependencies_from_generic_parameters_rec(*type_from_string, refs);
10181030
}
10191031
}
@@ -1053,6 +1065,7 @@ java_generic_struct_tag_typet::java_generic_struct_tag_typet(
10531065
{
10541066
set(ID_C_java_generic_symbol, true);
10551067
const auto base_type = java_type_from_string(base_ref, class_name_prefix);
1068+
CHECK_RETURN(base_type.has_value());
10561069
PRECONDITION(is_java_generic_type(*base_type));
10571070
const java_generic_typet &gen_base_type = to_java_generic_type(*base_type);
10581071
INVARIANT(

0 commit comments

Comments
 (0)