Reviewers: danno, svenpanne,
Message:
This is a security issue for node.js, io.js and maybe chromium!
Description:
unicode-decoder: fix out-of-bands write in utf16
`WriteUtf16Slow` should not assume that the output buffer has enough
bytes to hold both words of surrogate pair. It should pass the number of
remaining bytes to the `Utf8::ValueOf` instead, just as we already do in
`Utf8DecoderBase::Reset`. Otherwise it will attempt to write the trail
uint16_t past the buffer boundary, leading to memory corruption and
possible crash.
Originally reported by: Kris Reeves <[email protected]>
BUG=
R=danno
R=svenpanne
Please review this at https://codereview.chromium.org/1226493003/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+22, -1 lines):
M src/unicode-decoder.cc
M test/cctest/test-api.cc
Index: src/unicode-decoder.cc
diff --git a/src/unicode-decoder.cc b/src/unicode-decoder.cc
index
a3bf829522688b27a84b74e3322eed5a0c4088f3..4e7ebb878669d7aa3fa276a061ac66044c63ac3a
100644
--- a/src/unicode-decoder.cc
+++ b/src/unicode-decoder.cc
@@ -59,7 +59,7 @@ void Utf8DecoderBase::WriteUtf16Slow(const uint8_t*
stream, uint16_t* data,
size_t data_length) {
while (data_length != 0) {
size_t cursor = 0;
- uint32_t character = Utf8::ValueOf(stream, Utf8::kMaxEncodedSize,
&cursor);
+ uint32_t character = Utf8::ValueOf(stream, data_length, &cursor);
// There's a total lack of bounds checking for stream
// as it was already done in Reset.
stream += cursor;
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index
4b911f95c8e8e60388f768230c2a51fd56dd66d2..2957cc06b1ae6cf8d66953b5e3520757018f5922
100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -7418,6 +7418,27 @@ THREADED_TEST(Utf16Symbol) {
}
+THREADED_TEST(Utf16MissingTrailing) {
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+
+ // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
+ int size = 1024 * 64;
+ uint8_t* buffer = new uint8_t[size];
+ for (int i = 0; i < size; i += 4) {
+ buffer[i] = 0xf0;
+ buffer[i + 1] = 0x9d;
+ buffer[i + 2] = 0x80;
+ buffer[i + 3] = 0x9e;
+ }
+
+ // Now invoke the decoder without last 3 bytes
+ v8::Handle<v8::String> str = v8::String::NewFromUtf8(
+ context->GetIsolate(), reinterpret_cast<char*>(buffer),
+ v8::String::kNormalString, size - 3);
+}
+
+
THREADED_TEST(ToArrayIndex) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.