Bug 1289050 - Part 3: Use UTF8 variant of JS_ReportError after re-encoding string. r=jwalden
authorTooru Fujisawa <arai_a@mac.com>
Mon, 15 Aug 2016 19:20:04 +0900
changeset 361044 fd72da5a490517502ec2eca4bd5eedb9400c997c
parent 361043 b353e488f0eb8a6295db6275273157016963e31c
child 361045 125555035882e55c1abc8103be89e6ecf26c3ce1
push id1369
push userjlorenzo@mozilla.com
push dateMon, 27 Feb 2017 14:59:41 +0000
treeherdermozilla-release@d75a1dba431f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1289050
milestone52.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 1289050 - Part 3: Use UTF8 variant of JS_ReportError after re-encoding string. r=jwalden
ipc/testshell/XPCShellEnvironment.cpp
js/src/builtin/TestingFunctions.cpp
js/src/ctypes/Library.cpp
js/src/jscntxt.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/shell/OSObject.cpp
js/src/shell/js.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/wrappers/AddonWrapper.cpp
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -145,17 +145,20 @@ Load(JSContext *cx,
         JS::Rooted<JSString*> str(cx, JS::ToString(cx, args[i]));
         if (!str)
             return false;
         JSAutoByteString filename(cx, str);
         if (!filename)
             return false;
         FILE *file = fopen(filename.ptr(), "r");
         if (!file) {
-            JS_ReportError(cx, "cannot open file '%s' for reading", filename.ptr());
+            filename.clear();
+            if (!filename.encodeUtf8(cx, str))
+                return false;
+            JS_ReportErrorUTF8(cx, "cannot open file '%s' for reading", filename.ptr());
             return false;
         }
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename.ptr(), 1);
         JS::Rooted<JSScript*> script(cx);
         bool ok = JS::Compile(cx, options, file, &script);
         fclose(file);
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1542,24 +1542,27 @@ DumpHeap(JSContext* cx, unsigned argc, V
             }
         }
     }
 
     if (args.length() > i) {
         Value v = args[i];
         if (v.isString()) {
             if (!fuzzingSafe) {
-                JSString* str = v.toString();
+                RootedString str(cx, v.toString());
                 JSAutoByteString fileNameBytes;
                 if (!fileNameBytes.encodeLatin1(cx, str))
                     return false;
                 const char* fileName = fileNameBytes.ptr();
                 dumpFile = fopen(fileName, "w");
                 if (!dumpFile) {
-                    JS_ReportError(cx, "can't open %s", fileName);
+                    fileNameBytes.clear();
+                    if (!fileNameBytes.encodeUtf8(cx, str))
+                        return false;
+                    JS_ReportErrorUTF8(cx, "can't open %s", fileNameBytes.ptr());
                     return false;
                 }
             }
             ++i;
         }
     }
 
     if (i != args.length()) {
--- a/js/src/ctypes/Library.cpp
+++ b/js/src/ctypes/Library.cpp
@@ -146,35 +146,32 @@ Library::Create(JSContext* cx, Value pat
   }
 
   libSpec.value.pathname = pathBytes;
   libSpec.type = PR_LibSpec_Pathname;
 #endif
 
   PRLibrary* library = PR_LoadLibraryWithFlags(libSpec, 0);
 
+#ifndef XP_WIN
+  JS_free(cx, pathBytes);
+#endif
+
   if (!library) {
     char* error = (char*) JS_malloc(cx, PR_GetErrorTextLength() + 1);
     if (error)
       PR_GetErrorText(error);
 
-#ifdef XP_WIN
-    JS_ReportError(cx, "couldn't open library %hs: %s", pathChars, error);
-#else
-    JS_ReportError(cx, "couldn't open library %s: %s", pathBytes, error);
-    JS_free(cx, pathBytes);
-#endif
+    JSAutoByteString pathCharsUTF8;
+    if (pathCharsUTF8.encodeUtf8(cx, pathStr))
+      JS_ReportErrorUTF8(cx, "couldn't open library %s: %s", pathCharsUTF8.ptr(), error);
     JS_free(cx, error);
     return nullptr;
   }
 
-#ifndef XP_WIN
-  JS_free(cx, pathBytes);
-#endif
-
   // stash the library
   JS_SetReservedSlot(libraryObj, SLOT_LIBRARY, PrivateValue(library));
 
   return libraryObj;
 }
 
 bool
 Library::IsLibrary(JSObject* obj)
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -377,24 +377,21 @@ js::ReportUsageErrorASCII(JSContext* cx,
 
     RootedValue usage(cx);
     if (!JS_GetProperty(cx, callee, "usage", &usage))
         return;
 
     if (!usage.isString()) {
         JS_ReportErrorASCII(cx, "%s", msg);
     } else {
-        JSString* str = usage.toString();
-        if (!str->ensureFlat(cx))
+        RootedString usageStr(cx, usage.toString());
+        JSAutoByteString str;
+        if (!str.encodeUtf8(cx, usageStr))
             return;
-        AutoStableStringChars chars(cx);
-        if (!chars.initTwoByte(cx, str))
-            return;
-
-        JS_ReportError(cx, "%s. Usage: %hs", msg, chars.twoByteRange().start().get());
+        JS_ReportErrorUTF8(cx, "%s. Usage: %s", msg, str.ptr());
     }
 }
 
 bool
 js::PrintError(JSContext* cx, FILE* file, const char* message, JSErrorReport* report,
                bool reportWarnings)
 {
     if (!report) {
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -1331,28 +1331,28 @@ js::GetAllocationMetadata(JSObject* obj)
 
 JS_FRIEND_API(bool)
 js::ReportIsNotFunction(JSContext* cx, HandleValue v)
 {
     return ReportIsNotFunction(cx, v, -1);
 }
 
 JS_FRIEND_API(void)
-js::ReportErrorWithId(JSContext* cx, const char* msg, HandleId id)
+js::ReportASCIIErrorWithId(JSContext* cx, const char* msg, HandleId id)
 {
     RootedValue idv(cx);
     if (!JS_IdToValue(cx, id, &idv))
         return;
-    JSString* idstr = JS::ToString(cx, idv);
+    RootedString idstr(cx, JS::ToString(cx, idv));
     if (!idstr)
         return;
-    JSAutoByteString bytes(cx, idstr);
-    if (!bytes)
+    JSAutoByteString bytes;
+    if (!bytes.encodeUtf8(cx, idstr))
         return;
-    JS_ReportError(cx, msg, bytes.ptr());
+    JS_ReportErrorUTF8(cx, msg, bytes.ptr());
 }
 
 #ifdef DEBUG
 bool
 js::HasObjectMovedOp(JSObject* obj) {
     return !!GetObjectClass(obj)->extObjectMovedOp();
 }
 #endif
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -2775,17 +2775,17 @@ ForwardToNative(JSContext* cx, JSNative 
  */
 JS_FRIEND_API(bool)
 SetPropertyIgnoringNamedGetter(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
                                JS::HandleValue v, JS::HandleValue receiver,
                                JS::Handle<JS::PropertyDescriptor> ownDesc,
                                JS::ObjectOpResult& result);
 
 JS_FRIEND_API(void)
-ReportErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
+ReportASCIIErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
 
 // This function is for one specific use case, please don't use this for anything else!
 extern JS_FRIEND_API(bool)
 ExecuteInGlobalAndReturnScope(JSContext* cx, JS::HandleObject obj, JS::HandleScript script,
                               JS::MutableHandleObject scope);
 
 #if defined(XP_WIN) && defined(_WIN64)
 // Parameters use void* types to avoid #including windows.h. The return value of
--- a/js/src/shell/OSObject.cpp
+++ b/js/src/shell/OSObject.cpp
@@ -291,24 +291,30 @@ osfile_writeTypedArrayToFile(JSContext* 
     AutoCloseFile autoClose(file);
 
     TypedArrayObject* obj = &args[1].toObject().as<TypedArrayObject>();
 
     if (obj->isSharedMemory()) {
         // Must opt in to use shared memory.  For now, don't.
         //
         // See further comments in FileAsTypedArray, above.
-        JS_ReportError(cx, "can't write %s: shared memory buffer", filename.ptr());
+        filename.clear();
+        if (!filename.encodeUtf8(cx, str))
+            return false;
+        JS_ReportErrorUTF8(cx, "can't write %s: shared memory buffer", filename.ptr());
         return false;
     }
     void* buf = obj->viewDataUnshared();
     if (fwrite(buf, obj->bytesPerElement(), obj->length(), file) != obj->length() ||
         !autoClose.release())
     {
-        JS_ReportError(cx, "can't write %s", filename.ptr());
+        filename.clear();
+        if (!filename.encodeUtf8(cx, str))
+            return false;
+        JS_ReportErrorUTF8(cx, "can't write %s", filename.ptr());
         return false;
     }
 
     args.rval().setUndefined();
     return true;
 }
 
 /* static */ RCFile*
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1213,39 +1213,39 @@ AddPromiseReactions(JSContext* cx, unsig
 
 static bool
 Options(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     JS::ContextOptions oldContextOptions = JS::ContextOptionsRef(cx);
     for (unsigned i = 0; i < args.length(); i++) {
-        JSString* str = JS::ToString(cx, args[i]);
+        RootedString str(cx, JS::ToString(cx, args[i]));
         if (!str)
             return false;
         args[i].setString(str);
 
-        JSAutoByteString opt(cx, str);
-        if (!opt)
+        JSAutoByteString opt;
+        if (!opt.encodeUtf8(cx, str))
             return false;
 
         if (strcmp(opt.ptr(), "strict") == 0)
             JS::ContextOptionsRef(cx).toggleExtraWarnings();
         else if (strcmp(opt.ptr(), "werror") == 0)
             JS::ContextOptionsRef(cx).toggleWerror();
         else if (strcmp(opt.ptr(), "throw_on_asmjs_validation_failure") == 0)
             JS::ContextOptionsRef(cx).toggleThrowOnAsmJSValidationFailure();
         else if (strcmp(opt.ptr(), "strict_mode") == 0)
             JS::ContextOptionsRef(cx).toggleStrictMode();
         else {
-            JS_ReportError(cx,
-                           "unknown option name '%s'."
-                           " The valid names are strict,"
-                           " werror, and strict_mode.",
-                           opt.ptr());
+            JS_ReportErrorUTF8(cx,
+                               "unknown option name '%s'."
+                               " The valid names are strict,"
+                               " werror, and strict_mode.",
+                               opt.ptr());
             return false;
         }
     }
 
     char* names = strdup("");
     bool found = false;
     if (names && oldContextOptions.extraWarnings()) {
         names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict");
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -885,18 +885,20 @@ xpc::GlobalProperties::Parse(JSContext* 
     for (uint32_t i = 0; i < length; i++) {
         RootedValue nameValue(cx);
         ok = JS_GetElement(cx, obj, i, &nameValue);
         NS_ENSURE_TRUE(ok, false);
         if (!nameValue.isString()) {
             JS_ReportErrorASCII(cx, "Property names must be strings");
             return false;
         }
-        JSAutoByteString name(cx, nameValue.toString());
-        NS_ENSURE_TRUE(name, false);
+        RootedString nameStr(cx, nameValue.toString());
+        JSAutoByteString name;
+        if (!name.encodeUtf8(cx, nameStr))
+            return false;
         if (!strcmp(name.ptr(), "CSS")) {
             CSS = true;
         } else if (!strcmp(name.ptr(), "indexedDB")) {
             indexedDB = true;
         } else if (!strcmp(name.ptr(), "XMLHttpRequest")) {
             XMLHttpRequest = true;
         } else if (!strcmp(name.ptr(), "TextEncoder")) {
             TextEncoder = true;
@@ -924,17 +926,17 @@ xpc::GlobalProperties::Parse(JSContext* 
 #endif
         } else if (!strcmp(name.ptr(), "fetch")) {
             fetch = true;
         } else if (!strcmp(name.ptr(), "caches")) {
             caches = true;
         } else if (!strcmp(name.ptr(), "FileReader")) {
             fileReader = true;
         } else {
-            JS_ReportError(cx, "Unknown property name: %s", name.ptr());
+            JS_ReportErrorUTF8(cx, "Unknown property name: %s", name.ptr());
             return false;
         }
     }
     return true;
 }
 
 bool
 xpc::GlobalProperties::Define(JSContext* cx, JS::HandleObject obj)
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -352,18 +352,21 @@ Load(JSContext* cx, unsigned argc, Value
         str = ToString(cx, args[i]);
         if (!str)
             return false;
         JSAutoByteString filename(cx, str);
         if (!filename)
             return false;
         FILE* file = fopen(filename.ptr(), "r");
         if (!file) {
-            JS_ReportError(cx, "cannot open file '%s' for reading",
-                           filename.ptr());
+            filename.clear();
+            if (!filename.encodeUtf8(cx, str))
+                return false;
+            JS_ReportErrorUTF8(cx, "cannot open file '%s' for reading",
+                               filename.ptr());
             return false;
         }
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename.ptr(), 1)
                .setIsRunOnce(true);
         JS::Rooted<JSScript*> script(cx);
         JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
@@ -482,34 +485,36 @@ SendCommand(JSContext* cx, unsigned argc
 }
 
 static bool
 Options(JSContext* cx, unsigned argc, Value* vp)
 {
     JS::CallArgs args = CallArgsFromVp(argc, vp);
     ContextOptions oldContextOptions = ContextOptionsRef(cx);
 
+    RootedString str(cx);
+    JSAutoByteString opt;
     for (unsigned i = 0; i < args.length(); ++i) {
-        JSString* str = ToString(cx, args[i]);
+        str = ToString(cx, args[i]);
         if (!str)
             return false;
 
-        JSAutoByteString opt(cx, str);
-        if (!opt)
+        opt.clear();
+        if (!opt.encodeUtf8(cx, str))
             return false;
 
         if (strcmp(opt.ptr(), "strict") == 0)
             ContextOptionsRef(cx).toggleExtraWarnings();
         else if (strcmp(opt.ptr(), "werror") == 0)
             ContextOptionsRef(cx).toggleWerror();
         else if (strcmp(opt.ptr(), "strict_mode") == 0)
             ContextOptionsRef(cx).toggleStrictMode();
         else {
-            JS_ReportError(cx, "unknown option name '%s'. The valid names are "
-                           "strict, werror, and strict_mode.", opt.ptr());
+            JS_ReportErrorUTF8(cx, "unknown option name '%s'. The valid names are "
+                               "strict, werror, and strict_mode.", opt.ptr());
             return false;
         }
     }
 
     char* names = nullptr;
     if (oldContextOptions.extraWarnings()) {
         names = JS_sprintf_append(names, "%s", "strict");
         if (!names) {
@@ -527,17 +532,17 @@ Options(JSContext* cx, unsigned argc, Va
     if (names && oldContextOptions.strictMode()) {
         names = JS_sprintf_append(names, "%s%s", names ? "," : "", "strict_mode");
         if (!names) {
             JS_ReportOutOfMemory(cx);
             return false;
         }
     }
 
-    JSString* str = JS_NewStringCopyZ(cx, names);
+    str = JS_NewStringCopyZ(cx, names);
     free(names);
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
@@ -660,18 +665,18 @@ static const JSFunctionSpec glob_functio
 };
 
 static bool
 env_setProperty(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
                 ObjectOpResult& result)
 {
 /* XXX porting may be easy, but these don't seem to supply setenv by default */
 #if !defined SOLARIS
-    JSString* valstr;
-    JS::Rooted<JSString*> idstr(cx);
+    RootedString valstr(cx);
+    RootedString idstr(cx);
     int rv;
 
     RootedValue idval(cx);
     if (!JS_IdToValue(cx, id, &idval))
         return false;
 
     idstr = ToString(cx, idval);
     valstr = ToString(cx, vp);
@@ -701,17 +706,23 @@ env_setProperty(JSContext* cx, HandleObj
          */
         free(waste);
 #endif
     }
 #else
     rv = setenv(name.ptr(), value.ptr(), 1);
 #endif
     if (rv < 0) {
-        JS_ReportError(cx, "can't set envariable %s to %s", name.ptr(), value.ptr());
+        name.clear();
+        value.clear();
+        if (!name.encodeUtf8(cx, idstr))
+            return false;
+        if (!value.encodeUtf8(cx, valstr))
+            return false;
+        JS_ReportErrorUTF8(cx, "can't set envariable %s to %s", name.ptr(), value.ptr());
         return false;
     }
     vp.setString(valstr);
 #endif /* !defined SOLARIS */
     return result.succeed();
 }
 
 static bool
--- a/js/xpconnect/wrappers/AddonWrapper.cpp
+++ b/js/xpconnect/wrappers/AddonWrapper.cpp
@@ -226,33 +226,33 @@ AddonWrapper<Base>::defineProperty(JSCon
 {
     Rooted<PropertyDescriptor> interpDesc(cx);
     if (!InterposeProperty(cx, wrapper, nullptr, id, &interpDesc))
         return false;
 
     if (!interpDesc.object())
         return Base::defineProperty(cx, wrapper, id, desc, result);
 
-    js::ReportErrorWithId(cx, "unable to modify interposed property %s", id);
+    js::ReportASCIIErrorWithId(cx, "unable to modify interposed property %s", id);
     return false;
 }
 
 template<typename Base>
 bool
 AddonWrapper<Base>::delete_(JSContext* cx, HandleObject wrapper, HandleId id,
                             ObjectOpResult& result) const
 {
     Rooted<PropertyDescriptor> desc(cx);
     if (!InterposeProperty(cx, wrapper, nullptr, id, &desc))
         return false;
 
     if (!desc.object())
         return Base::delete_(cx, wrapper, id, result);
 
-    js::ReportErrorWithId(cx, "unable to delete interposed property %s", id);
+    js::ReportASCIIErrorWithId(cx, "unable to delete interposed property %s", id);
     return false;
 }
 
 #define AddonWrapperCC AddonWrapper<CrossCompartmentWrapper>
 #define AddonWrapperXrayXPCWN AddonWrapper<PermissiveXrayXPCWN>
 #define AddonWrapperXrayDOM AddonWrapper<PermissiveXrayDOM>
 
 template<> const AddonWrapperCC AddonWrapperCC::singleton(0);