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 @@
#include "objects.h"
#include "elements.h"
#include "utils.h"
#include "v8conversions.h"
// Each concrete ElementsAccessor can handle exactly one ElementsKind,
// several abstract ElementsAccessor classes are used to allow sharing
......@@ -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
// the common logic for objects with different ElementsKinds.
// Subclasses must specialize method for which the element
......@@ -570,6 +627,11 @@ class ElementsAccessorBase : public ElementsAccessor {
if (backing_store == NULL) {
backing_store = holder->elements();
}
if (FLAG_trace_array_abuse) {
CheckArrayAbuse(holder, "element read", key);
}
return ElementsAccessorSubclass::GetImpl(
receiver, holder, key, backing_store);
}
......
......@@ -197,6 +197,8 @@ class ElementsAccessor {
DISALLOW_COPY_AND_ASSIGN(ElementsAccessor);
};
void CheckArrayAbuse(JSObject* obj, const char* op, uint32_t key);
} } // namespace v8::internal
#endif // V8_ELEMENTS_H_
......@@ -363,6 +363,7 @@ DEFINE_bool(cache_prototype_transitions, true, "cache prototype transitions")
// debug.cc
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,
"automatically set the debug break flag when debugger commands are "
"in the queue")
......
......@@ -10405,6 +10405,11 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
HasDictionaryArgumentsElements() ||
(attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
Isolate* isolate = GetIsolate();
if (FLAG_trace_array_abuse) {
if (IsExternalArrayElementsKind(GetElementsKind())) {
CheckArrayAbuse(this, "external elements write", index);
}
}
switch (GetElementsKind()) {
case FAST_SMI_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