Skip to content

Commit 2a7e25c

Browse files
Merge pull request #1067 from cesaro/bugfix/groovy-lvt-handling
Fall back to anonlocal:: local variables for goto functions if LVT contains unexpected entries
2 parents 6a18c24 + a1af44f commit 2a7e25c

File tree

5 files changed

+50
-10
lines changed

5 files changed

+50
-10
lines changed
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
DetectSplitPackagesTask.class
3+
--show-symbol-table
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
--

regression/cbmc-java/lvt-unexpected/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
unexpected.class
33
--verbosity 10 --show-symbol-table
44
^EXIT=0$

src/java_bytecode/java_bytecode_convert_method.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,21 @@ symbol_exprt java_bytecode_convert_methodt::tmp_variable(
189189
return result;
190190
}
191191

192+
/// Returns a symbol_exprt indicating a local variable suitable to load/store
193+
/// from a bytecode at address `address` a value of type `type_char` stored in
194+
/// the JVM's slot `arg`.
195+
///
196+
/// \param arg
197+
/// The local variable slot
198+
/// \param type_char
199+
/// The type of the value stored in the slot pointed by `arg`.
200+
/// \param address
201+
/// Bytecode address used to find a variable that the LVT declares to be live
202+
/// and living in the slot pointed by `arg` for this bytecode.
203+
/// \param do_cast
204+
/// Indicates whether we should return the original symbol_exprt or a
205+
/// typecast_exprt if the type of the symbol_exprt does not equal that
206+
/// represented by `type_char`.
192207
const exprt java_bytecode_convert_methodt::variable(
193208
const exprt &arg,
194209
char type_char,

src/java_bytecode/java_local_variable_table.cpp

+27-9
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,12 @@ static void populate_predecessor_map(
289289
if(it->is_parameter)
290290
continue;
291291

292-
msg.debug() << "ppm: processing var idx " << it->var.index
292+
#ifdef DEBUG
293+
msg.debug() << "jcm: ppm: processing var idx " << it->var.index
293294
<< " name '" << it->var.name << "' start-pc "
294295
<< it->var.start_pc << " len " << it->var.length
295296
<< "; holes " << it->holes.size() << messaget::eom;
297+
#endif
296298

297299
// Find the last instruction within the live range:
298300
unsigned end_pc=it->var.start_pc+it->var.length;
@@ -362,11 +364,11 @@ static void populate_predecessor_map(
362364
*(inst_before_this->second.source),
363365
it->var.index))
364366
{
365-
msg.error() << "Local variable table: didn't find initializing "
366-
<< "store for predecessor of bytecode at address "
367-
<< amapit->first << " ("
368-
<< amapit->second.predecessors.size()
369-
<< " predecessors)" << msg.eom;
367+
msg.warning() << "Local variable table: didn't find initializing "
368+
<< "store for predecessor of bytecode at address "
369+
<< amapit->first << " ("
370+
<< amapit->second.predecessors.size()
371+
<< " predecessors)" << msg.eom;
370372
throw "local variable table: unexpected live ranges";
371373
}
372374
new_start_pc=pred;
@@ -541,7 +543,7 @@ static void merge_variable_table_entries(
541543
/// Given a sequence of users of the same local variable slot, this figures out
542544
/// which ones are related by control flow, and combines them into a single
543545
/// entry with holes, such that after combination we can create a single
544-
/// declaration per variable table entry, placed at the live range's start
546+
/// GOTO variable per variable table entry, placed at the live range's start
545547
/// address, which may be moved back so that the declaration dominates all uses.
546548
/// \par parameters: `firstvar`-`varlimit`: sequence of variable table entries,
547549
/// all of which should concern the same slot index.
@@ -720,8 +722,24 @@ void java_bytecode_convert_methodt::setup_local_variables(
720722
for(const auto &v : m.local_variable_table)
721723
vars_with_holes.push_back({v, is_parameter(v), {}});
722724

723-
// Merge variable records:
724-
find_initializers(vars_with_holes, amap, dominator_analysis);
725+
// Merge variable records. See documentation of in
726+
// `find_initializers_for_slot` for more details. If the strategy employed
727+
// there fails with an exception, we just ignore the LVT for this method, no
728+
// variable is generated in `this->variables[]` (because we return here and
729+
// dont let the for loop below to execute), and as a result the method
730+
// this->variable() will be forced to create new `anonlocal::` variables, as
731+
// the only source of variable names for that method is `this->variables[]`.
732+
try
733+
{
734+
find_initializers(vars_with_holes, amap, dominator_analysis);
735+
}
736+
catch(const char *message)
737+
{
738+
warning() << "Bytecode -> codet translation error: " << message << eom
739+
<< "This is probably due to an unexpected LVT, "
740+
<< "falling back to translation without LVT" << eom;
741+
return;
742+
}
725743

726744
// Clean up removed records from the variable table:
727745
cleanup_var_table(vars_with_holes);

0 commit comments

Comments
 (0)