Commit 9cb3a2e9 authored by danno@chromium.org's avatar danno@chromium.org

Add --trace-array-abuse to help find OOB accesses.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/12220040

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13613 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 19232a1e
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "objects.h" #include "objects.h"
#include "elements.h" #include "elements.h"
#include "utils.h" #include "utils.h"
#include "v8conversions.h"
// Each concrete ElementsAccessor can handle exactly one ElementsKind, // Each concrete ElementsAccessor can handle exactly one ElementsKind,
// several abstract ElementsAccessor classes are used to allow sharing // several abstract ElementsAccessor classes are used to allow sharing
...@@ -483,6 +483,63 @@ static void CopyDictionaryToDoubleElements(FixedArrayBase* from_base, ...@@ -483,6 +483,63 @@ static void CopyDictionaryToDoubleElements(FixedArrayBase* from_base,
} }
static void TraceTopFrame() {
StackFrameIterator it;
if (it.done()) {
PrintF("unknown location (no JavaScript frames present)");
return;
}
StackFrame* raw_frame = it.frame();
if (raw_frame->is_internal()) {
Isolate* isolate = Isolate::Current();
Code* apply_builtin = isolate->builtins()->builtin(
Builtins::kFunctionApply);
if (raw_frame->unchecked_code() == apply_builtin) {
PrintF("apply from ");
it.Advance();
raw_frame = it.frame();
}
}
JavaScriptFrame::PrintTop(stdout, false, true);
}
void CheckArrayAbuse(JSObject* obj, const char* op, uint32_t key) {
Object* raw_length = NULL;
const char* elements_type = "array";
if (obj->IsJSArray()) {
JSArray* array = JSArray::cast(obj);
raw_length = array->length();
} else {
raw_length = Smi::FromInt(obj->elements()->length());
elements_type = "object";
}
if (raw_length->IsNumber()) {
double n = raw_length->Number();
if (FastI2D(FastD2UI(n)) == n) {
int32_t int32_length = DoubleToInt32(n);
if (key >= static_cast<uint32_t>(int32_length)) {
PrintF("[OOB %s %s (%s length = %d, element accessed = %d) in ",
elements_type, op, elements_type,
static_cast<int>(int32_length),
static_cast<int>(key));
TraceTopFrame();
PrintF("]\n");
}
} else {
PrintF("[%s elements length not integer value in ", elements_type);
TraceTopFrame();
PrintF("]\n");
}
} else {
PrintF("[%s elements length not a number in ", elements_type);
TraceTopFrame();
PrintF("]\n");
}
}
// Base class for element handler implementations. Contains the // Base class for element handler implementations. Contains the
// the common logic for objects with different ElementsKinds. // the common logic for objects with different ElementsKinds.
// Subclasses must specialize method for which the element // Subclasses must specialize method for which the element
...@@ -570,6 +627,11 @@ class ElementsAccessorBase : public ElementsAccessor { ...@@ -570,6 +627,11 @@ class ElementsAccessorBase : public ElementsAccessor {
if (backing_store == NULL) { if (backing_store == NULL) {
backing_store = holder->elements(); backing_store = holder->elements();
} }
if (FLAG_trace_array_abuse) {
CheckArrayAbuse(holder, "element read", key);
}
return ElementsAccessorSubclass::GetImpl( return ElementsAccessorSubclass::GetImpl(
receiver, holder, key, backing_store); receiver, holder, key, backing_store);
} }
......
...@@ -197,6 +197,8 @@ class ElementsAccessor { ...@@ -197,6 +197,8 @@ class ElementsAccessor {
DISALLOW_COPY_AND_ASSIGN(ElementsAccessor); DISALLOW_COPY_AND_ASSIGN(ElementsAccessor);
}; };
void CheckArrayAbuse(JSObject* obj, const char* op, uint32_t key);
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_ELEMENTS_H_ #endif // V8_ELEMENTS_H_
...@@ -363,6 +363,7 @@ DEFINE_bool(cache_prototype_transitions, true, "cache prototype transitions") ...@@ -363,6 +363,7 @@ DEFINE_bool(cache_prototype_transitions, true, "cache prototype transitions")
// debug.cc // debug.cc
DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response") DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
DEFINE_bool(trace_array_abuse, false, "trace out-of-bounds array accesses")
DEFINE_bool(debugger_auto_break, true, DEFINE_bool(debugger_auto_break, true,
"automatically set the debug break flag when debugger commands are " "automatically set the debug break flag when debugger commands are "
"in the queue") "in the queue")
......
...@@ -10405,6 +10405,11 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, ...@@ -10405,6 +10405,11 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
HasDictionaryArgumentsElements() || HasDictionaryArgumentsElements() ||
(attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
Isolate* isolate = GetIsolate(); Isolate* isolate = GetIsolate();
if (FLAG_trace_array_abuse) {
if (IsExternalArrayElementsKind(GetElementsKind())) {
CheckArrayAbuse(this, "external elements write", index);
}
}
switch (GetElementsKind()) { switch (GetElementsKind()) {
case FAST_SMI_ELEMENTS: case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS: case FAST_ELEMENTS:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment