Bug 1604429 - Check for the uninitialized-lexical MagicValue in the component loader. r=kmag
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 18 Dec 2019 19:02:01 +0000
changeset 507743 f1a6d6a378bdb570d45c638d9690370e15310956
parent 507742 96b4fd2ee4bc3221210b71537cc11fc0ef08ee92
child 507744 5c1f0479e011c12dfdbfb4f7c9ec15e6653f0b07
push id36932
push useraciure@mozilla.com
push dateThu, 19 Dec 2019 21:52:02 +0000
treeherdermozilla-central@8e1b11b00157 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1604429, 1603373
milestone73.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 1604429 - Check for the uninitialized-lexical MagicValue in the component loader. r=kmag Bug 1603373 tightened up JS engine assertions around this, but that broke Thunderbird tests. Differential Revision: https://phabricator.services.mozilla.com/D57443
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/tests/unit/test_uninitialized_lexical.js
js/xpconnect/tests/unit/uninitialized_lexical.jsm
js/xpconnect/tests/unit/xpcshell.ini
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -84,16 +84,18 @@ static LazyLogModule gJSCLLog("JSCompone
 #define ERROR_NO_TARGET_OBJECT "%s - Couldn't find target object for import."
 #define ERROR_NOT_PRESENT "%s - EXPORTED_SYMBOLS is not present."
 #define ERROR_NOT_AN_ARRAY "%s - EXPORTED_SYMBOLS is not an array."
 #define ERROR_GETTING_ARRAY_LENGTH \
   "%s - Error getting array length of EXPORTED_SYMBOLS."
 #define ERROR_ARRAY_ELEMENT "%s - EXPORTED_SYMBOLS[%d] is not a string."
 #define ERROR_GETTING_SYMBOL "%s - Could not get symbol '%s'."
 #define ERROR_SETTING_SYMBOL "%s - Could not set symbol '%s' on target object."
+#define ERROR_UNINITIALIZED_SYMBOL \
+  "%s - Symbol '%s' accessed before initialization. Cyclic import?"
 
 static bool Dump(JSContext* cx, unsigned argc, Value* vp) {
   if (!nsJSUtils::DumpEnabled()) {
     return true;
   }
 
   CallArgs args = CallArgsFromVp(argc, vp);
 
@@ -1222,16 +1224,28 @@ nsresult mozJSComponentLoader::ExtractEx
       JS::UniqueChars bytes = JS_EncodeStringToUTF8(cx, symbolStr);
       if (!bytes) {
         return NS_ERROR_FAILURE;
       }
       return ReportOnCallerUTF8(cxhelper, ERROR_GETTING_SYMBOL, aInfo,
                                 bytes.get());
     }
 
+    // It's possible |value| is the uninitialized lexical MagicValue when
+    // there's a cyclic import: const obj = ChromeUtils.import("parent.jsm").
+    if (value.isMagic(JS_UNINITIALIZED_LEXICAL)) {
+      RootedString symbolStr(cx, JSID_TO_STRING(symbolId));
+      JS::UniqueChars bytes = JS_EncodeStringToUTF8(cx, symbolStr);
+      if (!bytes) {
+        return NS_ERROR_FAILURE;
+      }
+      return ReportOnCallerUTF8(cxhelper, ERROR_UNINITIALIZED_SYMBOL, aInfo,
+                                bytes.get());
+    }
+
     if (value.isUndefined()) {
       missing = true;
     }
 
     if (!JS_SetPropertyById(cx, aExports, symbolId, value)) {
       RootedString symbolStr(cx, JSID_TO_STRING(symbolId));
       JS::UniqueChars bytes = JS_EncodeStringToUTF8(cx, symbolStr);
       if (!bytes) {
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/unit/test_uninitialized_lexical.js
@@ -0,0 +1,7 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+Assert.throws(() => ChromeUtils.import("resource://test/uninitialized_lexical.jsm"),
+              /Symbol 'foo' accessed before initialization/,
+              "Uninitialized lexicals result in an exception");
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/unit/uninitialized_lexical.jsm
@@ -0,0 +1,2 @@
+var EXPORTED_SYMBOLS = ["foo"];
+const foo = ChromeUtils.import("resource://test/uninitialized_lexical.jsm");
--- a/js/xpconnect/tests/unit/xpcshell.ini
+++ b/js/xpconnect/tests/unit/xpcshell.ini
@@ -14,16 +14,17 @@ support-files =
   environment_script.js
   environment_loadscript.jsm
   environment_checkscript.jsm
   file_simple_script.js
   importer.jsm
   recursive_importA.jsm
   recursive_importB.jsm
   syntax_error.jsm
+  uninitialized_lexical.jsm
 
 [test_allowWaivers.js]
 [test_bogus_files.js]
 [test_bug408412.js]
 [test_bug451678.js]
 [test_bug604362.js]
 [test_bug677864.js]
 [test_bug711404.js]
@@ -147,8 +148,9 @@ head = head_watchdog.js
 [test_function_names.js]
 [test_FrameScriptEnvironment.js]
 [test_SubscriptLoaderEnvironment.js]
 [test_SubscriptLoaderSandboxEnvironment.js]
 [test_SubscriptLoaderJSMEnvironment.js]
 [test_ComponentEnvironment.js]
 [test_wrapped_js_enumerator.js]
 [test_uawidget_scope.js]
+[test_uninitialized_lexical.js]