Skip to content

Commit 1fe1e37

Browse files
author
Matthias Güdemann
committed
Add java_enum_array_clone_unwind_handler
This handler unwinds loops in specialized `.clone` functions for `Enum` arrays.
1 parent adc72d1 commit 1fe1e37

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

jbmc/src/java_bytecode/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SRC = bytecode_info.cpp \
2020
java_bytecode_typecheck_type.cpp \
2121
java_class_loader.cpp \
2222
java_class_loader_limit.cpp \
23+
java_enum_array_clone_unwind_handler.cpp \
2324
java_enum_static_init_unwind_handler.cpp \
2425
java_entry_point.cpp \
2526
java_local_variable_table.cpp \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*******************************************************************\
2+
3+
Module: Unwind loops in array clone for enums
4+
5+
Author: Diffblue
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Unwind loops in array.clone for enums
11+
#include "java_enum_array_clone_unwind_handler.h"
12+
13+
#include <util/invariant.h>
14+
#include <util/suffix.h>
15+
16+
#include <java_bytecode/java_utils.h>
17+
18+
/// Unwind handler that special-cases the clone functions of arrays of
19+
/// enumeration classes. This forces unwinding of the copy loop in the clone
20+
/// method with as many iterations as enum elements exist.
21+
/// \param function_id: function the loop is in
22+
/// \param loop_number: ordinal number of the loop (ignored)
23+
/// \param unwind_count: iteration count that is about to begin
24+
/// \param [out] unwind_max: may be set to an advisory (unenforced) maximum when
25+
/// we know the total iteration count
26+
/// \param symbol_table: global symbol table
27+
/// \return false if loop_id belongs to an enumeration's array clone method and
28+
/// unwind_count is <= the enumeration size, or unknown (defer / no decision)
29+
/// otherwise.
30+
tvt java_enum_array_clone_unwind_handler(
31+
const irep_idt &function_id,
32+
unsigned loop_number,
33+
unsigned unwind_count,
34+
unsigned &unwind_max,
35+
const symbol_tablet &symbol_table)
36+
{
37+
const std::string method_name = id2string(function_id);
38+
const std::string java_array_prefix = "java::array[";
39+
const size_t java_array_prefix_start = method_name.find(java_array_prefix);
40+
const size_t java_array_prefix_end =
41+
method_name.find("].clone:()Ljava/lang/Object;");
42+
if(java_array_prefix_end == std::string::npos || java_array_prefix_start != 0)
43+
return tvt::unknown();
44+
45+
const java_enum_elements_mapt java_enum_elements =
46+
get_java_enum_elements_map(symbol_table);
47+
48+
std::string enum_name = "java::" +
49+
method_name.substr(
50+
java_array_prefix.size(),
51+
java_array_prefix_end - java_array_prefix.size());
52+
std::replace(enum_name.begin(), enum_name.end(), '/', '.');
53+
const auto entry = java_enum_elements.find(enum_name);
54+
55+
if(entry != java_enum_elements.end())
56+
{
57+
const size_t bound = entry->second;
58+
if(unwind_count < bound)
59+
{
60+
unwind_max = bound;
61+
return tvt(false);
62+
}
63+
}
64+
return tvt::unknown();
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*******************************************************************\
2+
3+
Module: Unwind loops in array clone for enums
4+
5+
Author: Diffblue
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Unwind loops in array.clone for enums
11+
12+
#ifndef CPROVER_JAVA_BYTECODE_JAVA_ENUM_ARRAY_CLONE_UNWIND_HANDLER_H
13+
#define CPROVER_JAVA_BYTECODE_JAVA_ENUM_ARRAY_CLONE_UNWIND_HANDLER_H
14+
15+
#include <util/symbol_table.h>
16+
#include <util/threeval.h>
17+
18+
tvt java_enum_array_clone_unwind_handler(
19+
const irep_idt &function_id,
20+
unsigned loop_number,
21+
unsigned unwind_count,
22+
unsigned &unwind_max,
23+
const symbol_tablet &symbol_table);
24+
25+
#endif // CPROVER_JAVA_BYTECODE_JAVA_ENUM_ARRAY_CLONE_UNWIND_HANDLER_H

jbmc/src/jbmc/jbmc_parse_options.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Author: Daniel Kroening, [email protected]
5454

5555
#include <java_bytecode/convert_java_nondet.h>
5656
#include <java_bytecode/java_bytecode_language.h>
57+
#include <java_bytecode/java_enum_array_clone_unwind_handler.h>
5758
#include <java_bytecode/java_enum_static_init_unwind_handler.h>
5859
#include <java_bytecode/remove_exceptions.h>
5960
#include <java_bytecode/remove_instanceof.h>
@@ -518,6 +519,16 @@ int jbmc_parse_optionst::doit()
518519
max_unwind,
519520
symbol_table);
520521
});
522+
// unwind Enum.values() loop to correctly enable enum array cloning
523+
bmc.add_loop_unwind_handler(
524+
[&symbol_table](
525+
const irep_idt &function_id,
526+
unsigned loop_num,
527+
unsigned unwind_count,
528+
unsigned &max_unwind) {
529+
return java_enum_array_clone_unwind_handler(
530+
function_id, loop_num, unwind_count, max_unwind, symbol_table);
531+
});
521532
};
522533
}
523534

0 commit comments

Comments
 (0)