Bug 1504802 - Add a jsapi-test for a UTF-8 multi-unit code point within the line of context for a syntax error. r=arai
authorJeff Walden <jwalden@mit.edu>
Mon, 05 Nov 2018 18:55:56 -0800
changeset 503835 0fbfcab038431951b9c53b5ee669d01d7b336d03
parent 503834 971f97ac3013c6c8ee106a0b7c5699194c90b8ab
child 503836 72521d6e680f7a0b0771d56867393ec1cadd5989
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1504802
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1504802 - Add a jsapi-test for a UTF-8 multi-unit code point within the line of context for a syntax error. r=arai
js/src/jsapi-tests/testCompileUtf8.cpp
--- a/js/src/jsapi-tests/testCompileUtf8.cpp
+++ b/js/src/jsapi-tests/testCompileUtf8.cpp
@@ -11,16 +11,17 @@
 #include "jsfriendapi.h"
 
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/SourceText.h"
 #include "jsapi-tests/tests.h"
 #include "vm/ErrorReporting.h"
 
+using mozilla::ArrayEqual;
 using mozilla::ArrayLength;
 using mozilla::IsAsciiHexDigit;
 using mozilla::Utf8Unit;
 
 BEGIN_TEST(testUtf8BadBytes)
 {
     static const char badLeadingUnit[] = "var x = \x80";
     CHECK(testBadUtf8(badLeadingUnit,
@@ -200,37 +201,26 @@ isTooBigMessage(const char* str)
 
 static bool
 isNotShortestFormMessage(const char* str)
 {
     return isForbiddenCodePointMessage(str) &&
            contains(str, "it wasn't encoded in shortest possible form");
 }
 
-bool
-compileUtf8(const char* chars, size_t len, JS::MutableHandleScript script)
-{
-    JS::RealmOptions globalOptions;
-    JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
-						   JS::FireOnNewGlobalHook, globalOptions));
-    CHECK(global);
-
-    JSAutoRealm ar(cx, global);
-
-    JS::CompileOptions options(cx);
-    return JS::CompileUtf8DontInflate(cx, options, chars, len, script);
-}
-
 template<size_t N, typename TestMessage>
 bool
 testBadUtf8(const char (&chars)[N], unsigned errorNumber,
             TestMessage testMessage, const char* badBytes)
 {
     JS::Rooted<JSScript*> script(cx);
-    CHECK(!compileUtf8(chars, N - 1, &script));
+    {
+        JS::CompileOptions options(cx);
+        CHECK(!JS::CompileUtf8DontInflate(cx, options, chars, N - 1, &script));
+    }
 
     JS::RootedValue exn(cx);
     CHECK(JS_GetPendingException(cx, &exn));
     JS_ClearPendingException(cx);
 
     js::ErrorReport report(cx);
     CHECK(report.init(cx, exn, js::ErrorReport::WithSideEffects));
 
@@ -272,8 +262,66 @@ testBadUtf8(const char (&chars)[N], unsi
     CHECK(lineOfContext[lineOfContextLength] == '\0');
     CHECK(lineOfContextLength == expectedContextLen);
 
     CHECK(std::memcmp(lineOfContext, expectedContext, expectedContextLen * sizeof(char16_t)) == 0);
 
     return true;
 }
 END_TEST(testUtf8BadBytes)
+
+BEGIN_TEST(testMultiUnitUtf8InWindow)
+{
+    static const char firstInWindowIsMultiUnit[] =
+      "\xCF\x80\xCF\x80 = 6.283185307; @ bad starts HERE:\x80\xFF\xFF";
+    CHECK(testContext(firstInWindowIsMultiUnit,
+                      u"ππ = 6.283185307; @ bad starts HERE:"));
+
+    static const char atTokenOffsetIsMulti[] =
+      "var z = 💯";
+    CHECK(testContext(atTokenOffsetIsMulti,
+                      u"var z = 💯"));
+
+    static const char afterTokenOffsetIsMulti[] =
+      "var z = @💯💯💯X";
+    CHECK(testContext(afterTokenOffsetIsMulti,
+                      u"var z = @💯💯💯X"));
+
+    static const char atEndIsMulti[] =
+      "var z = @@💯💯💯";
+    CHECK(testContext(atEndIsMulti,
+                      u"var z = @@💯💯💯"));
+
+    return true;
+}
+
+template<size_t N, size_t ContextLenWithNull>
+bool
+testContext(const char (&chars)[N], const char16_t (&expectedContext)[ContextLenWithNull])
+{
+    JS::Rooted<JSScript*> script(cx);
+    {
+        JS::CompileOptions options(cx);
+        CHECK(!JS::CompileUtf8DontInflate(cx, options, chars, N - 1, &script));
+    }
+
+    JS::RootedValue exn(cx);
+    CHECK(JS_GetPendingException(cx, &exn));
+    JS_ClearPendingException(cx);
+
+    js::ErrorReport report(cx);
+    CHECK(report.init(cx, exn, js::ErrorReport::WithSideEffects));
+
+    const auto* errorReport = report.report();
+
+    CHECK(errorReport->errorNumber == JSMSG_ILLEGAL_CHARACTER);
+
+    const char16_t* lineOfContext = errorReport->linebuf();
+    size_t lineOfContextLength = errorReport->linebufLength();
+
+    CHECK(lineOfContext[lineOfContextLength] == '\0');
+    CHECK(lineOfContextLength == ContextLenWithNull - 1);
+
+    CHECK(ArrayEqual(lineOfContext, expectedContext, ContextLenWithNull));
+
+    return true;
+}
+END_TEST(testMultiUnitUtf8InWindow)