Revision: 12446
Author: [email protected]
Date: Wed Sep 5 09:08:13 2012
Log: Check the return value of API calls on ia32 and x64.
This implies that the return value of native getters is checked. The nice
part
is that one can even see the name of the property in question in the abort
output when the check failed.
Under some circumstances even the return value of interceptors gets
checked, but
I'm not 100% sure about this, because the interceptor code is basically
tuned to
death.
The change seems to have very low overhead, so it might be feasible to keep
this
check enabled unconditionally.
Review URL: https://chromiumcodereview.appspot.com/10918071
Patch from Sven Panne <[email protected]>.
http://code.google.com/p/v8/source/detail?r=12446
Modified:
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.cc
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Aug 28
07:20:50 2012
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Wed Sep 5
09:08:13 2012
@@ -1939,6 +1939,42 @@
cmp(Operand::StaticVariable(scheduled_exception_address),
Immediate(isolate()->factory()->the_hole_value()));
j(not_equal, &promote_scheduled_exception);
+
+#if ENABLE_EXTRA_CHECKS
+ // Check if the function returned a valid JavaScript value.
+ Label ok;
+ Register return_value = eax;
+ Register map = ecx;
+
+ JumpIfSmi(return_value, &ok, Label::kNear);
+ mov(map, FieldOperand(return_value, HeapObject::kMapOffset));
+
+ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
+ j(below, &ok, Label::kNear);
+
+ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
+ j(above_equal, &ok, Label::kNear);
+
+ cmp(map, isolate()->factory()->heap_number_map());
+ j(equal, &ok, Label::kNear);
+
+ cmp(return_value, isolate()->factory()->undefined_value());
+ j(equal, &ok, Label::kNear);
+
+ cmp(return_value, isolate()->factory()->true_value());
+ j(equal, &ok, Label::kNear);
+
+ cmp(return_value, isolate()->factory()->false_value());
+ j(equal, &ok, Label::kNear);
+
+ cmp(return_value, isolate()->factory()->null_value());
+ j(equal, &ok, Label::kNear);
+
+ Abort("API call returned invalid object");
+
+ bind(&ok);
+#endif
+
LeaveApiExitFrame();
ret(stack_space * kPointerSize);
=======================================
--- /branches/bleeding_edge/src/objects.cc Wed Sep 5 05:30:49 2012
+++ /branches/bleeding_edge/src/objects.cc Wed Sep 5 09:08:13 2012
@@ -210,7 +210,20 @@
if (result.IsEmpty()) {
return isolate->heap()->undefined_value();
}
- return *v8::Utils::OpenHandle(*result);
+ Object* return_value = *v8::Utils::OpenHandle(*result);
+#if ENABLE_EXTRA_CHECKS
+ if (!(return_value->IsSmi() ||
+ return_value->IsString() ||
+ return_value->IsSpecObject() ||
+ return_value->IsHeapNumber() ||
+ return_value->IsUndefined() ||
+ return_value->IsTrue() ||
+ return_value->IsFalse() ||
+ return_value->IsNull())) {
+ FATAL("API call returned invalid object");
+ }
+#endif
+ return return_value;
}
// __defineGetter__ callback
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue Aug 28
07:20:50 2012
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Wed Sep 5
09:08:13 2012
@@ -751,6 +751,41 @@
Cmp(Operand(rsi, 0), factory->the_hole_value());
j(not_equal, &promote_scheduled_exception);
+#if ENABLE_EXTRA_CHECKS
+ // Check if the function returned a valid JavaScript value.
+ Label ok;
+ Register return_value = rax;
+ Register map = rcx;
+
+ JumpIfSmi(return_value, &ok, Label::kNear);
+ movq(map, FieldOperand(return_value, HeapObject::kMapOffset));
+
+ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
+ j(below, &ok, Label::kNear);
+
+ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
+ j(above_equal, &ok, Label::kNear);
+
+ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ CompareRoot(return_value, Heap::kUndefinedValueRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ CompareRoot(return_value, Heap::kTrueValueRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ CompareRoot(return_value, Heap::kFalseValueRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ CompareRoot(return_value, Heap::kNullValueRootIndex);
+ j(equal, &ok, Label::kNear);
+
+ Abort("API call returned invalid object");
+
+ bind(&ok);
+#endif
+
LeaveApiExitFrame();
ret(stack_space * kPointerSize);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev