[value-serializer] Verify deserialized JSRegExp flags
One of the serializer fuzzers passes in random data to the deserializer, which can then be used to deserialize a JSRegExp instance with random flag contents. This can cause issues since the JSRegExp::Flag enum statically contains kDotAll - but it is only valid to set kDotAll iff FLAG_harmony_regexp_dotall is set. This CL verifies deserialized flags before constructing the JSRegExp and bails out if they are invalid. R=jbroman@chromium.org,yangguo@chromium.org BUG=chromium:719280 Review-Url: https://codereview.chromium.org/2870743004 Cr-Commit-Position: refs/heads/master@{#45222}
This commit is contained in:
parent
0679765daf
commit
540419b660
@ -1463,11 +1463,22 @@ MaybeHandle<JSRegExp> ValueDeserializer::ReadJSRegExp() {
|
||||
uint32_t raw_flags;
|
||||
Handle<JSRegExp> regexp;
|
||||
if (!ReadString().ToHandle(&pattern) ||
|
||||
!ReadVarint<uint32_t>().To(&raw_flags) ||
|
||||
!ReadVarint<uint32_t>().To(&raw_flags)) {
|
||||
return MaybeHandle<JSRegExp>();
|
||||
}
|
||||
|
||||
// Ensure the deserialized flags are valid. The context behind this is that
|
||||
// the JSRegExp::Flags enum statically includes kDotAll, but it is only valid
|
||||
// to set kDotAll if FLAG_harmony_regexp_dotall is enabled. Fuzzers don't
|
||||
// know about this and happily set kDotAll anyways, leading to CHECK failures
|
||||
// later on.
|
||||
uint32_t flags_mask = static_cast<uint32_t>(-1) << JSRegExp::FlagCount();
|
||||
if ((raw_flags & flags_mask) ||
|
||||
!JSRegExp::New(pattern, static_cast<JSRegExp::Flags>(raw_flags))
|
||||
.ToHandle(®exp)) {
|
||||
return MaybeHandle<JSRegExp>();
|
||||
}
|
||||
|
||||
AddObjectWithID(id, regexp);
|
||||
return regexp;
|
||||
}
|
||||
|
@ -1603,6 +1603,44 @@ TEST_F(ValueSerializerTest, DecodeRegExp) {
|
||||
});
|
||||
}
|
||||
|
||||
// Tests that invalid flags are not accepted by the deserializer. In particular,
|
||||
// the dotAll flag ('s') is only valid when the corresponding flag is enabled.
|
||||
TEST_F(ValueSerializerTest, DecodeRegExpDotAll) {
|
||||
i::FLAG_harmony_regexp_dotall = false;
|
||||
DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x1f},
|
||||
[this](Local<Value> value) {
|
||||
ASSERT_TRUE(value->IsRegExp());
|
||||
EXPECT_TRUE(EvaluateScriptForResultBool(
|
||||
"Object.getPrototypeOf(result) === RegExp.prototype"));
|
||||
EXPECT_TRUE(EvaluateScriptForResultBool(
|
||||
"result.toString() === '/foo/gimuy'"));
|
||||
});
|
||||
InvalidDecodeTest(
|
||||
{0xff, 0x09, 0x3f, 0x00, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x3f});
|
||||
InvalidDecodeTest(
|
||||
{0xff, 0x09, 0x3f, 0x00, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x7f});
|
||||
|
||||
i::FLAG_harmony_regexp_dotall = true;
|
||||
DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x1f},
|
||||
[this](Local<Value> value) {
|
||||
ASSERT_TRUE(value->IsRegExp());
|
||||
EXPECT_TRUE(EvaluateScriptForResultBool(
|
||||
"Object.getPrototypeOf(result) === RegExp.prototype"));
|
||||
EXPECT_TRUE(EvaluateScriptForResultBool(
|
||||
"result.toString() === '/foo/gimuy'"));
|
||||
});
|
||||
DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x3f},
|
||||
[this](Local<Value> value) {
|
||||
ASSERT_TRUE(value->IsRegExp());
|
||||
EXPECT_TRUE(EvaluateScriptForResultBool(
|
||||
"Object.getPrototypeOf(result) === RegExp.prototype"));
|
||||
EXPECT_TRUE(EvaluateScriptForResultBool(
|
||||
"result.toString() === '/foo/gimsuy'"));
|
||||
});
|
||||
InvalidDecodeTest(
|
||||
{0xff, 0x09, 0x3f, 0x00, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x7f});
|
||||
}
|
||||
|
||||
TEST_F(ValueSerializerTest, RoundTripMap) {
|
||||
RoundTripTest(
|
||||
"(() => { var m = new Map(); m.set(42, 'foo'); return m; })()",
|
||||
|
Loading…
Reference in New Issue
Block a user