Revision: 5030
Author: [email protected]
Date: Wed Jul 7 03:28:22 2010
Log: Prevent invalid pre-parsing data passed in through the API from
crashing V8.
Review URL: http://codereview.chromium.org/2876046
http://code.google.com/p/v8/source/detail?r=5030
Modified:
/branches/bleeding_edge/src/messages.js
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/test/cctest/test-api.cc
/branches/bleeding_edge/test/mjsunit/fuzz-natives.js
=======================================
--- /branches/bleeding_edge/src/messages.js Fri Jul 2 07:36:34 2010
+++ /branches/bleeding_edge/src/messages.js Wed Jul 7 03:28:22 2010
@@ -197,7 +197,8 @@
obj_ctor_property_non_object: "Object.%0 called on non-object",
array_indexof_not_defined: "Array.getIndexOf: Argument undefined",
object_not_extensible: "Can't add property %0, object is not
extensible",
- illegal_access: "illegal access"
+ illegal_access: "Illegal access",
+ invalid_preparser_data: "Invalid preparser data for
function %0"
};
}
var format = kMessages[message.type];
=======================================
--- /branches/bleeding_edge/src/parser.cc Tue Jun 8 05:04:49 2010
+++ /branches/bleeding_edge/src/parser.cc Wed Jul 7 03:28:22 2010
@@ -134,6 +134,7 @@
// Report syntax error
void ReportUnexpectedToken(Token::Value token);
+ void ReportInvalidPreparseData(Handle<String> name, bool* ok);
Handle<Script> script_;
Scanner scanner_;
@@ -3261,6 +3262,15 @@
ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
}
}
+
+
+void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
+ SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
+ const char* element[1] = { *name_string };
+ ReportMessage("invalid_preparser_data",
+ Vector<const char*>(element, 1));
+ *ok = false;
+}
Expression* Parser::ParsePrimaryExpression(bool* ok) {
@@ -3810,7 +3820,14 @@
Handle<FixedArray> this_property_assignments;
if (is_lazily_compiled && pre_data() != NULL) {
FunctionEntry entry = pre_data()->GetFunctionEnd(start_pos);
+ if (!entry.is_valid()) {
+ ReportInvalidPreparseData(name, CHECK_OK);
+ }
int end_pos = entry.end_pos();
+ if (end_pos <= start_pos) {
+ // End position greater than end of stream is safe, and hard to
check.
+ ReportInvalidPreparseData(name, CHECK_OK);
+ }
Counters::total_preparse_skipped.Increment(end_pos - start_pos);
scanner_.SeekForward(end_pos);
materialized_literal_count = entry.literal_count();
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Fri Jul 2 07:36:34 2010
+++ /branches/bleeding_edge/test/cctest/test-api.cc Wed Jul 7 03:28:22 2010
@@ -8555,6 +8555,43 @@
delete sd;
}
+
+
+// Attempts to deserialize bad data.
+TEST(PreCompileInvalidPreparseDataError) {
+ v8::V8::Initialize();
+ v8::HandleScope scope;
+ LocalContext context;
+
+ const char* script = "function foo(){ return 5;}\n"
+ "function bar(){ return 6 + 7;} foo();";
+ v8::ScriptData* sd =
+ v8::ScriptData::PreCompile(script, i::StrLength(script));
+ CHECK(!sd->HasError());
+ // ScriptDataImpl private implementation details
+ const int kUnsignedSize = sizeof(unsigned);
+ const int kHeaderSize = 4;
+ const int kFunctionEntrySize = 4;
+ const int kFunctionEntryStartOffset = 0;
+ const int kFunctionEntryEndOffset = 1;
+ unsigned* sd_data =
+ reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
+ CHECK_EQ(sd->Length(),
+ (kHeaderSize + 2 * kFunctionEntrySize) * kUnsignedSize);
+
+ // Overwrite function bar's end position with 0.
+ sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset]
= 0;
+ Local<String> source = String::New(script);
+ Local<Script> compiled_script = Script::New(source, NULL, sd);
+
+ // Overwrite function bar's start position with 200. The function entry
+ // will not be found when searching for it by position.
+ sd_data[kHeaderSize + 1 * kFunctionEntrySize +
kFunctionEntryStartOffset] =
+ 200;
+ compiled_script = Script::New(source, NULL, sd);
+
+ delete sd;
+}
// Verifies that the Handle<String> and const char* versions of the API
produce
=======================================
--- /branches/bleeding_edge/test/mjsunit/fuzz-natives.js Tue May 4
06:07:36 2010
+++ /branches/bleeding_edge/test/mjsunit/fuzz-natives.js Wed Jul 7
03:28:22 2010
@@ -63,7 +63,7 @@
try {
func = makeFunction(name, i);
} catch (e) {
- if (e != "SyntaxError: illegal access") throw e;
+ if (e != "SyntaxError: Illegal access") throw e;
}
if (func === null && i == argc) {
throw "unexpected exception";
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev