Skip to content

Commit 9c09d3a

Browse files
Merge pull request #4802 from peterschrammel/assume-non-null
Add preconditions for Java NotNull annotations
2 parents ee678f3 + b11ffc8 commit 9c09d3a

File tree

8 files changed

+111
-4
lines changed

8 files changed

+111
-4
lines changed
Binary file not shown.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import javax.validation.constraints.NotNull;
2+
3+
public class Main {
4+
public static Integer test1(boolean y, Object z, String[] s)
5+
{
6+
return foo(1, y, z, s);
7+
}
8+
public static Integer test2(Integer x, boolean y, Object z)
9+
{
10+
return new Main().bar(x, y, z, new String[0]);
11+
}
12+
public static Integer test3(boolean y)
13+
{
14+
return foo(new Integer(1), y, null, new String[0]);
15+
}
16+
public static Integer foo(@NotNull Integer x, @NotNull boolean y, Object z, @NotNull String[] s) {
17+
return x;
18+
}
19+
public Integer bar(@NotNull Integer x, @NotNull boolean y, Object z, @NotNull String[] s) {
20+
return x;
21+
}
22+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
Main.class
3+
--function Main.test2 --classpath `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
\[not-null-annotation-check\.1\] line \d+ Not null annotation check: FAILURE
8+
\[not-null-annotation-check\.2\] line \d+ Not null annotation check: SUCCESS
9+
--
10+
^warning: ignoring
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
Main.class
3+
--function Main.test1 --classpath `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
\[not-null-annotation-check\.1\] line \d+ Not null annotation check: SUCCESS
8+
\[not-null-annotation-check\.2\] line \d+ Not null annotation check: FAILURE
9+
--
10+
^warning: ignoring
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
Main.class
3+
--function Main.test3 --classpath `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
\[not-null-annotation-check\.1\] line \d+ Not null annotation check: SUCCESS
8+
\[not-null-annotation-check\.2\] line \d+ Not null annotation check: SUCCESS
9+
--
10+
^warning: ignoring

jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -585,9 +585,12 @@ void java_bytecode_convert_methodt::convert(
585585
current_method = method_symbol.name;
586586
method_has_this = method_type.has_this();
587587
if((!m.is_abstract) && (!m.is_native))
588-
method_symbol.value = convert_instructions(
589-
m,
590-
to_java_class_type(class_symbol.type).lambda_method_handles());
588+
{
589+
code_blockt code(convert_parameter_annotations(m, method_type));
590+
code.append(convert_instructions(
591+
m, to_java_class_type(class_symbol.type).lambda_method_handles()));
592+
method_symbol.value = std::move(code);
593+
}
591594
}
592595

593596
static irep_idt get_if_cmp_operator(const irep_idt &stmt)
@@ -966,6 +969,54 @@ static std::size_t get_bytecode_type_width(const typet &ty)
966969
return to_bitvector_type(ty).get_width();
967970
}
968971

972+
code_blockt java_bytecode_convert_methodt::convert_parameter_annotations(
973+
const methodt &method,
974+
const java_method_typet &method_type)
975+
{
976+
code_blockt code;
977+
978+
// Consider parameter annotations
979+
const java_method_typet::parameterst &parameters(method_type.parameters());
980+
std::size_t param_index = method_type.has_this() ? 1 : 0;
981+
DATA_INVARIANT(
982+
parameters.size() >= method.parameter_annotations.size() + param_index,
983+
"parameters and parameter annotations mismatch");
984+
for(const auto &param_annotations : method.parameter_annotations)
985+
{
986+
// NotNull annotations are not standardized. We support these:
987+
if(
988+
java_bytecode_parse_treet::find_annotation(
989+
param_annotations, "java::javax.validation.constraints.NotNull") ||
990+
java_bytecode_parse_treet::find_annotation(
991+
param_annotations, "java::org.jetbrains.annotations.NotNull") ||
992+
java_bytecode_parse_treet::find_annotation(
993+
param_annotations, "org.eclipse.jdt.annotation.NonNull") ||
994+
java_bytecode_parse_treet::find_annotation(
995+
param_annotations, "java::edu.umd.cs.findbugs.annotations.NonNull"))
996+
{
997+
const irep_idt &param_identifier =
998+
parameters[param_index].get_identifier();
999+
const symbolt &param_symbol = symbol_table.lookup_ref(param_identifier);
1000+
const auto param_type =
1001+
type_try_dynamic_cast<pointer_typet>(param_symbol.type);
1002+
if(param_type)
1003+
{
1004+
code_assertt code_assert(notequal_exprt(
1005+
param_symbol.symbol_expr(), null_pointer_exprt(*param_type)));
1006+
source_locationt check_loc = method.source_location;
1007+
check_loc.set_comment("Not null annotation check");
1008+
check_loc.set_property_class("not-null-annotation-check");
1009+
code_assert.add_source_location() = check_loc;
1010+
1011+
code.add(std::move(code_assert));
1012+
}
1013+
}
1014+
++param_index;
1015+
}
1016+
1017+
return code;
1018+
}
1019+
9691020
code_blockt java_bytecode_convert_methodt::convert_instructions(
9701021
const methodt &method,
9711022
const java_class_typet::java_lambda_method_handlest &lambda_method_handles)

jbmc/src/java_bytecode/java_bytecode_convert_method_class.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ class java_bytecode_convert_methodt:public messaget
300300
// conversion
301301
void convert(const symbolt &class_symbol, const methodt &);
302302

303+
code_blockt convert_parameter_annotations(
304+
const methodt &method,
305+
const java_method_typet &method_type);
306+
303307
code_blockt convert_instructions(
304308
const methodt &,
305309
const java_class_typet::java_lambda_method_handlest &);

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1276,7 +1276,7 @@ void java_bytecode_parsert::rmethod_attribute(methodt &method)
12761276
attribute_name == "RuntimeVisibleParameterAnnotations")
12771277
{
12781278
u1 parameter_count = read_u1();
1279-
// There may be attributes for both runtime-visiible and rutime-invisible
1279+
// There may be attributes for both runtime-visible and runtime-invisible
12801280
// annotations, the length of either array may be longer than the other as
12811281
// trailing parameters without annotations are omitted.
12821282
// Extend our parameter_annotations if this one is longer than the one

0 commit comments

Comments
 (0)