Quick compiler: fix array overrun.
MIRGraph::InlineCalls() was using the MIR opcode to recover
Dalvik instruction flags - something that is only valid for
Dalvik opcodes and not the set of extended MIR opcodes.
This is probably the 3rd or 4th time we've had a bug using
the MIR opcode in situations that are only valid for the Dalvik
opcode subset. I took the opportunity to scan the code for
other cases of this (didn't find any), and did some cleanup while
I was in the neighborhood.
We should probably rework the DalvikOpcode/MirOpcode model whenver we
get around to removing DalvikInstruction from MIR.
Internal bug b/15352667: out-of-bound access in mir_optimization.cc
Change-Id: I75f06780468880892151e3cdd313e14bfbbaa489
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 1570c3a..6bb2284 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -758,7 +758,7 @@
// Check if we support the byte code.
if (std::find(support_list, support_list + support_list_size,
opcode) == support_list + support_list_size) {
- if (opcode < kMirOpFirst) {
+ if (!cu.mir_graph->IsPseudoMirOp(opcode)) {
VLOG(compiler) << "Unsupported dalvik byte code : "
<< mir->dalvikInsn.opcode;
} else {
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc
index 508f1c7..7129f8a 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -902,7 +902,7 @@
while (!done) {
tbb->visited = true;
for (MIR* mir = tbb->first_mir_insn; mir != NULL; mir = mir->next) {
- if (static_cast<uint32_t>(mir->dalvikInsn.opcode) >= kMirOpFirst) {
+ if (IsPseudoMirOp(mir->dalvikInsn.opcode)) {
// Skip any MIR pseudo-op.
continue;
}
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index 5ff6274..9fea709 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -1015,8 +1015,7 @@
uint64_t df_attributes = GetDataFlowAttributes(mir);
// If not a pseudo-op, note non-leaf or can throw
- if (static_cast<int>(mir->dalvikInsn.opcode) <
- static_cast<int>(kNumPackedOpcodes)) {
+ if (!IsPseudoMirOp(mir->dalvikInsn.opcode)) {
int flags = Instruction::FlagsOf(mir->dalvikInsn.opcode);
if ((flags & Instruction::kInvoke) != 0 && (mir->optimization_flags & MIR_INLINED) == 0) {
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 99dd50a..db28f3a 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -549,8 +549,7 @@
new_block->predecessors->Insert(cur_block->id);
MIR* new_insn = NewMIR();
*new_insn = *insn;
- insn->dalvikInsn.opcode =
- static_cast<Instruction::Code>(kMirOpCheck);
+ insn->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpCheck);
// Associate the two halves.
insn->meta.throw_insn = new_insn;
new_block->AppendMIR(new_insn);
@@ -837,8 +836,7 @@
} else {
fprintf(file, " {%04x %s %s %s\\l}%s\\\n", mir->offset,
mir->ssa_rep ? GetDalvikDisassembly(mir) :
- (opcode < kMirOpFirst) ?
- Instruction::Name(mir->dalvikInsn.opcode) :
+ !IsPseudoMirOp(opcode) ? Instruction::Name(mir->dalvikInsn.opcode) :
extended_mir_op_names_[opcode - kMirOpFirst],
(mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
(mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
@@ -1141,7 +1139,7 @@
nop = true;
}
- if (opcode >= kMirOpFirst) {
+ if (IsPseudoMirOp(opcode)) {
str.append(extended_mir_op_names_[opcode - kMirOpFirst]);
} else {
dalvik_format = Instruction::FormatOf(insn.opcode);
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index b04c16e..38cd5ee 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -905,11 +905,11 @@
return backward_branches_ + forward_branches_;
}
- bool IsPseudoMirOp(Instruction::Code opcode) {
+ static bool IsPseudoMirOp(Instruction::Code opcode) {
return static_cast<int>(opcode) >= static_cast<int>(kMirOpFirst);
}
- bool IsPseudoMirOp(int opcode) {
+ static bool IsPseudoMirOp(int opcode) {
return opcode >= static_cast<int>(kMirOpFirst);
}
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 256686e..23f2516 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -129,17 +129,16 @@
BasicBlock* tbb = bb;
mir = AdvanceMIR(&tbb, mir);
while (mir != NULL) {
- int opcode = mir->dalvikInsn.opcode;
if ((mir->dalvikInsn.opcode == Instruction::MOVE_RESULT) ||
(mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) ||
(mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_WIDE)) {
break;
}
// Keep going if pseudo op, otherwise terminate
- if (opcode < kNumPackedOpcodes) {
- mir = NULL;
- } else {
+ if (IsPseudoMirOp(mir->dalvikInsn.opcode)) {
mir = AdvanceMIR(&tbb, mir);
+ } else {
+ mir = NULL;
}
}
return mir;
@@ -866,7 +865,7 @@
struct BasicBlock* next_bb = GetBasicBlock(bb->fall_through);
for (MIR* tmir = next_bb->first_mir_insn; tmir != NULL;
tmir =tmir->next) {
- if (static_cast<int>(tmir->dalvikInsn.opcode) >= static_cast<int>(kMirOpFirst)) {
+ if (IsPseudoMirOp(tmir->dalvikInsn.opcode)) {
continue;
}
// First non-pseudo should be MOVE_RESULT_OBJECT
@@ -1183,6 +1182,9 @@
return;
}
for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
+ if (IsPseudoMirOp(mir->dalvikInsn.opcode)) {
+ continue;
+ }
if (!(Instruction::FlagsOf(mir->dalvikInsn.opcode) & Instruction::kInvoke)) {
continue;
}
diff --git a/compiler/dex/portable/mir_to_gbc.cc b/compiler/dex/portable/mir_to_gbc.cc
index 576e242..fd67608 100644
--- a/compiler/dex/portable/mir_to_gbc.cc
+++ b/compiler/dex/portable/mir_to_gbc.cc
@@ -712,7 +712,7 @@
int opt_flags = mir->optimization_flags;
if (cu_->verbose) {
- if (op_val < kMirOpFirst) {
+ if (!IsPseudoMirOp(op_val)) {
LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x" << std::hex << op_val;
} else {
LOG(INFO) << mir_graph_->extended_mir_op_names_[op_val - kMirOpFirst] << " 0x" << std::hex << op_val;
@@ -1550,7 +1550,7 @@
SetDexOffset(bb->start_offset);
for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
int opcode = mir->dalvikInsn.opcode;
- if (opcode < kMirOpFirst) {
+ if (!IsPseudoMirOp(opcode)) {
// Stop after first non-pseudo MIR op.
continue;
}
@@ -1759,7 +1759,7 @@
}
}
- if (opcode >= kMirOpFirst) {
+ if (IsPseudoMirOp(opcode)) {
ConvertExtendedMIR(bb, mir, llvm_bb);
continue;
}
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 526c981..6397208 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -43,6 +43,7 @@
uint32_t GetInvokeReg(MIR* invoke, uint32_t arg) {
DCHECK_LT(arg, invoke->dalvikInsn.vA);
+ DCHECK(!MIRGraph::IsPseudoMirOp(invoke->dalvikInsn.opcode));
if (Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k3rc) {
return invoke->dalvikInsn.vC + arg; // Non-range invoke.
} else {
@@ -53,6 +54,7 @@
bool WideArgIsInConsecutiveDalvikRegs(MIR* invoke, uint32_t arg) {
DCHECK_LT(arg + 1, invoke->dalvikInsn.vA);
+ DCHECK(!MIRGraph::IsPseudoMirOp(invoke->dalvikInsn.opcode));
return Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k3rc ||
invoke->dalvikInsn.arg[arg + 1u] == invoke->dalvikInsn.arg[arg] + 1u;
}
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 9fc93d0..df56820 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -1069,7 +1069,7 @@
work_half->meta.throw_insn = mir;
}
- if (opcode >= kMirOpFirst) {
+ if (MIRGraph::IsPseudoMirOp(opcode)) {
HandleExtendedMethodMIR(bb, mir);
continue;
}
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index ee02257..092e68e 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -869,7 +869,7 @@
for (MIR *mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
int opcode = mir->dalvikInsn.opcode;
- if (opcode >= kMirOpFirst) {
+ if (MIRGraph::IsPseudoMirOp(opcode)) {
AnalyzeExtendedMIR(opcode, bb, mir);
} else {
AnalyzeMIR(opcode, bb, mir);
diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc
index a4c62ad..c4af9cb 100644
--- a/compiler/dex/vreg_analysis.cc
+++ b/compiler/dex/vreg_analysis.cc
@@ -233,8 +233,7 @@
// Special-case handling for format 35c/3rc invokes
Instruction::Code opcode = mir->dalvikInsn.opcode;
- int flags = (static_cast<int>(opcode) >= kNumPackedOpcodes)
- ? 0 : Instruction::FlagsOf(mir->dalvikInsn.opcode);
+ int flags = IsPseudoMirOp(opcode) ? 0 : Instruction::FlagsOf(mir->dalvikInsn.opcode);
if ((flags & Instruction::kInvoke) &&
(attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
DCHECK_EQ(next, 0);
@@ -317,8 +316,7 @@
* The Phi set will include all low words or all high
* words, so we have to treat them specially.
*/
- bool is_phi = (static_cast<int>(mir->dalvikInsn.opcode) ==
- kMirOpPhi);
+ bool is_phi = (static_cast<int>(mir->dalvikInsn.opcode) == kMirOpPhi);
RegLocation rl_temp = reg_location_[defs[0]];
bool defined_fp = rl_temp.defined && rl_temp.fp;
bool defined_core = rl_temp.defined && rl_temp.core;