Commit f7c85755 authored by whesse@chromium.org's avatar whesse@chromium.org

Prevent invalid pre-parsing data passed in through the API from crashing V8.

Review URL: http://codereview.chromium.org/2876046

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5030 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4798d2c4
......@@ -197,7 +197,8 @@ function FormatMessage(message) {
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];
......
......@@ -134,6 +134,7 @@ class Parser {
// Report syntax error
void ReportUnexpectedToken(Token::Value token);
void ReportInvalidPreparseData(Handle<String> name, bool* ok);
Handle<Script> script_;
Scanner scanner_;
......@@ -3263,6 +3264,15 @@ void Parser::ReportUnexpectedToken(Token::Value token) {
}
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) {
// PrimaryExpression ::
// 'this'
......@@ -3810,7 +3820,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
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();
......
......@@ -8557,6 +8557,43 @@ TEST(PreCompileDeserializationError) {
}
// 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
// the same results (at least for one trivial case).
TEST(PreCompileAPIVariationsAreSame) {
......
......@@ -63,7 +63,7 @@ function testArgumentCount(name, argc) {
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";
......
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