Merge "Stack overflow error and unit test." into dalvik-dev
diff --git a/src/dex_instruction.cc b/src/dex_instruction.cc
index 39348ed..4db8846 100644
--- a/src/dex_instruction.cc
+++ b/src/dex_instruction.cc
@@ -74,6 +74,8 @@
case k10t: // op +AA
vA = (int8_t) INST_AA(insn); // sign-extend 8-bit value
break;
+ case k20bc: // op AA, kind@BBBB
+ break;
case k20t: // op +AAAA
vA = (int16_t) FETCH(1); // sign-extend 16-bit value
break;
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index fd10017..ebb71b2 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -1381,6 +1381,8 @@
InsnFlags* insn_flags = vdata->insn_flags_.get();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
+ const ClassLoader* class_loader =
+ method->GetDeclaringClass()->GetClassLoader();
const uint16_t* insns = code_item->insns_ + insn_idx;
uint32_t insns_size = code_item->insns_size_;
uint32_t registers_size = code_item->registers_size_;
@@ -1649,11 +1651,12 @@
LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
<< " (" << bad_class_desc << ") in "
<< klass->GetDescriptor()->ToModifiedUtf8();
- DCHECK(failure != VERIFY_ERROR_GENERIC);
- } else {
- SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
- class_linker->FindSystemClass("Ljava/lang/Class;")));
+ if (failure != VERIFY_ERROR_NONE) {
+ break;
+ }
}
+ SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
+ class_linker->FindSystemClass("Ljava/lang/Class;")));
break;
case Instruction::MONITOR_ENTER:
@@ -1700,18 +1703,21 @@
LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
<< " (" << bad_class_desc << ") in "
<< klass->GetDescriptor()->ToModifiedUtf8();
- DCHECK(failure != VERIFY_ERROR_GENERIC);
- } else {
- RegType orig_type;
-
- orig_type = GetRegisterType(work_line, dec_insn.vA_);
- if (!RegTypeIsReference(orig_type)) {
- LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
- failure = VERIFY_ERROR_GENERIC;
+ if (failure != VERIFY_ERROR_NONE) {
break;
}
- SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
+ /* if the class is unresolvable, treat it as an object */
+ res_class = class_linker->FindClass("Ljava/lang/Object;", class_loader);
}
+ RegType orig_type;
+
+ orig_type = GetRegisterType(work_line, dec_insn.vA_);
+ if (!RegTypeIsReference(orig_type)) {
+ LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
+ failure = VERIFY_ERROR_GENERIC;
+ break;
+ }
+ SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
break;
case Instruction::INSTANCE_OF:
/* make sure we're checking a reference type */
@@ -1729,11 +1735,12 @@
LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
<< " (" << bad_class_desc << ") in "
<< klass->GetDescriptor()->ToModifiedUtf8();
- DCHECK(failure != VERIFY_ERROR_GENERIC);
- } else {
- /* result is boolean */
- SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
+ if (failure != VERIFY_ERROR_NONE) {
+ break;
+ }
}
+ /* result is boolean */
+ SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
break;
case Instruction::ARRAY_LENGTH:
@@ -1749,14 +1756,19 @@
break;
case Instruction::NEW_INSTANCE:
- res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
- if (res_class == NULL) {
- const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
- LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
- << " (" << bad_class_desc << ") in "
- << klass->GetDescriptor()->ToModifiedUtf8();
- DCHECK(failure != VERIFY_ERROR_GENERIC);
- } else {
+ {
+ res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
+ if (res_class == NULL) {
+ const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
+ LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
+ << " (" << bad_class_desc << ") in "
+ << klass->GetDescriptor()->ToModifiedUtf8();
+ if (failure != VERIFY_ERROR_NONE) {
+ break;
+ }
+ /* if the class is unresolvable, treat it as an object */
+ res_class = class_linker->FindClass("Ljava/lang/Object;", class_loader);
+ }
RegType uninit_type;
/* can't create an instance of an interface or abstract class */
@@ -1781,8 +1793,8 @@
/* add the new uninitialized reference to the register ste */
SetRegisterType(work_line, dec_insn.vA_, uninit_type);
+ break;
}
- break;
case Instruction::NEW_ARRAY:
res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
if (res_class == NULL) {
@@ -1790,8 +1802,13 @@
LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
<< " (" << bad_class_desc << ") in "
<< klass->GetDescriptor()->ToModifiedUtf8();
- DCHECK(failure != VERIFY_ERROR_GENERIC);
- } else if (!res_class->IsArrayClass()) {
+ if (failure != VERIFY_ERROR_NONE) {
+ break;
+ }
+ /* if the class is unresolvable, treat it as an object array */
+ res_class = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
+ }
+ if (!res_class->IsArrayClass()) {
LOG(ERROR) << "VFY: new-array on non-array class";
failure = VERIFY_ERROR_GENERIC;
} else {
@@ -1809,13 +1826,17 @@
LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
<< " (" << bad_class_desc << ") in "
<< klass->GetDescriptor()->ToModifiedUtf8();
- DCHECK(failure != VERIFY_ERROR_GENERIC);
- } else if (!res_class->IsArrayClass()) {
+ if (failure != VERIFY_ERROR_NONE) {
+ break;
+ }
+ /* if the class is unresolvable, treat it as an object array */
+ res_class = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
+ }
+ if (!res_class->IsArrayClass()) {
LOG(ERROR) << "VFY: filled-new-array on non-array class";
failure = VERIFY_ERROR_GENERIC;
} else {
- bool is_range = (dec_insn.opcode_ ==
- Instruction::FILLED_NEW_ARRAY_RANGE);
+ bool is_range = (dec_insn.opcode_ == Instruction::FILLED_NEW_ARRAY_RANGE);
/* check the arguments to the instruction */
VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
@@ -4121,11 +4142,19 @@
DCHECK(src_class != NULL);
DCHECK(check_class != NULL);
- if (!check_class->IsAssignableFrom(src_class)) {
- LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
- << " is not instance of "
- << check_class->GetDescriptor()->ToModifiedUtf8();
- *failure = VERIFY_ERROR_GENERIC;
+ if (check_class->IsInterface()) {
+ /*
+ * All objects implement all interfaces as far as the verifier is
+ * concerned. The runtime has to sort it out. See coments above
+ * FindCommonSuperclass.
+ */
+ } else {
+ if (!check_class->IsAssignableFrom(src_class)) {
+ LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
+ << " is not instance of "
+ << check_class->GetDescriptor()->ToModifiedUtf8();
+ *failure = VERIFY_ERROR_GENERIC;
+ }
}
}
break;
@@ -4332,10 +4361,12 @@
Class* res_class = class_linker->ResolveType(*dex_file, class_idx, referrer);
if (res_class == NULL) {
- *failure = VERIFY_ERROR_NO_CLASS;
+ //*failure = VERIFY_ERROR_NO_CLASS;
+ LOG(ERROR) << "VFY: can't find class with index 0x" << std::hex << class_idx << std::dec;
return NULL;
}
+#if 0
/* Check if access is allowed. */
if (!referrer->CanAccess(res_class)) {
LOG(ERROR) << "VFY: illegal class access: "
@@ -4344,6 +4375,7 @@
*failure = VERIFY_ERROR_ACCESS_CLASS;
return NULL;
}
+#endif
return res_class;
}
@@ -4382,16 +4414,18 @@
}
}
+#if 0
/* Check if access is allowed. */
if (!referrer->CanAccess(res_method->GetDeclaringClass())) {
LOG(ERROR) << "VFY: illegal method access (call "
<< res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
- << "." << res_method->GetName() << " "
- << res_method->GetSignature() << " from "
+ << "." << res_method->GetName()->ToModifiedUtf8() << " "
+ << res_method->GetSignature()->ToModifiedUtf8() << " from "
<< referrer->GetDescriptor()->ToModifiedUtf8() << ")";
*failure = VERIFY_ERROR_ACCESS_METHOD;
return NULL;
}
+#endif
return res_method;
}
@@ -5954,4 +5988,102 @@
return new_map;
}
+/* Dump the register types for the specifed address to the log file. */
+void DexVerifier::DumpRegTypes(const VerifierData* vdata,
+ const RegisterLine* register_line, int addr, const char* addr_name,
+ const UninitInstanceMap* uninit_map) {
+ const DexFile::CodeItem* code_item = vdata->code_item_;
+ uint16_t reg_count = code_item->registers_size_;
+ uint32_t insns_size = code_item->insns_size_;
+ const InsnFlags* insn_flags = vdata->insn_flags_.get();
+ const RegType* addr_regs = register_line->reg_types_.get();
+ int full_reg_count = reg_count + kExtraRegs;
+ bool branch_target = InsnIsBranchTarget(insn_flags, addr);
+ int i;
+
+ CHECK(addr >= 0 && addr < (int) insns_size);
+
+ int reg_char_size = full_reg_count + (full_reg_count - 1) / 4 + 2 + 1;
+ char reg_chars[reg_char_size + 1];
+ memset(reg_chars, ' ', reg_char_size);
+ reg_chars[0] = '[';
+ if (reg_count == 0)
+ reg_chars[1] = ']';
+ else
+ reg_chars[1 + (reg_count - 1) + (reg_count -1 ) / 4 + 1] = ']';
+ reg_chars[reg_char_size] = '\0';
+
+ for (i = 0; i < reg_count + kExtraRegs; i++) {
+ char tch;
+
+ switch (addr_regs[i]) {
+ case kRegTypeUnknown: tch = '.'; break;
+ case kRegTypeConflict: tch = 'X'; break;
+ case kRegTypeZero: tch = '0'; break;
+ case kRegTypeOne: tch = '1'; break;
+ case kRegTypeBoolean: tch = 'Z'; break;
+ case kRegTypeConstPosByte: tch = 'y'; break;
+ case kRegTypeConstByte: tch = 'Y'; break;
+ case kRegTypeConstPosShort: tch = 'h'; break;
+ case kRegTypeConstShort: tch = 'H'; break;
+ case kRegTypeConstChar: tch = 'c'; break;
+ case kRegTypeConstInteger: tch = 'i'; break;
+ case kRegTypePosByte: tch = 'b'; break;
+ case kRegTypeByte: tch = 'B'; break;
+ case kRegTypePosShort: tch = 's'; break;
+ case kRegTypeShort: tch = 'S'; break;
+ case kRegTypeChar: tch = 'C'; break;
+ case kRegTypeInteger: tch = 'I'; break;
+ case kRegTypeFloat: tch = 'F'; break;
+ case kRegTypeConstLo: tch = 'N'; break;
+ case kRegTypeConstHi: tch = 'n'; break;
+ case kRegTypeLongLo: tch = 'J'; break;
+ case kRegTypeLongHi: tch = 'j'; break;
+ case kRegTypeDoubleLo: tch = 'D'; break;
+ case kRegTypeDoubleHi: tch = 'd'; break;
+ default:
+ if (RegTypeIsReference(addr_regs[i])) {
+ if (RegTypeIsUninitReference(addr_regs[i]))
+ tch = 'U';
+ else
+ tch = 'L';
+ } else {
+ tch = '*';
+ CHECK(false);
+ }
+ break;
+ }
+
+ if (i < reg_count)
+ reg_chars[1 + i + (i / 4)] = tch;
+ else
+ reg_chars[1 + i + (i / 4) + 2] = tch;
+ }
+
+ if (addr == 0 && addr_name != NULL) {
+ char start = branch_target ? '>' : ' ';
+ LOG(INFO) << start << addr_name << " " << reg_chars << " mst="
+ << register_line->monitor_stack_top_;
+ } else {
+ char start = branch_target ? '>' : ' ';
+ LOG(INFO) << start << "0x" << std::hex << addr << std::dec << " "
+ << reg_chars << " mst=" << register_line->monitor_stack_top_;
+ }
+
+ for (i = 0; i < reg_count + kExtraRegs; i++) {
+ if (RegTypeIsReference(addr_regs[i]) && addr_regs[i] != kRegTypeZero) {
+ Class* klass = RegTypeReferenceToClass(addr_regs[i], uninit_map);
+ if (i < reg_count) {
+ const char* undef = RegTypeIsUninitReference(addr_regs[i]) ? "[U]" : "";
+ LOG(INFO) << " " << i << ": 0x" << std::hex << addr_regs[i] << std::dec
+ << " " << undef << klass->GetDescriptor()->ToModifiedUtf8();
+ } else {
+ const char* undef = RegTypeIsUninitReference(addr_regs[i]) ? "[U]" : "";
+ LOG(INFO) << " RS: 0x" << std::hex << addr_regs[i] << std::dec
+ << " " << undef << klass->GetDescriptor()->ToModifiedUtf8();
+ }
+ }
+ }
+}
+
} // namespace art
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 8b1f450..96349a3 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -1696,6 +1696,11 @@
const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
bool is_range, bool is_super, VerifyError* failure);
+ /* Dump the register types for the specifed address to the log file. */
+ static void DumpRegTypes(const VerifierData* vdata,
+ const RegisterLine* register_line, int addr, const char* addr_name,
+ const UninitInstanceMap* uninit_map);
+
DISALLOW_COPY_AND_ASSIGN(DexVerifier);
};
diff --git a/src/object.cc b/src/object.cc
index e92c8c7..1af840f 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -1107,8 +1107,9 @@
}
// Is this field in any of this class' interfaces?
- for (size_t i = 0; i < c->NumInterfaces(); ++i) {
- Class* interface = c->GetInterface(i);
+ for (int32_t i = 0; i < c->GetIfTableCount(); ++i) {
+ InterfaceEntry* interface_entry = c->GetIfTable()->Get(i);
+ Class* interface = interface_entry->GetInterface();
f = interface->FindDeclaredStaticField(name, type);
if (f != NULL) {
return f;