Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp
Warning:line 193, column 7
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_js_xpconnect_src1.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/xpconnect/src -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/xpconnect/src -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/xpconnect/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/xpcom/components -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/loader -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/caps -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/bindings -I /var/lib/jenkins/workspace/firefox-scan-build/dom/html -I /var/lib/jenkins/workspace/firefox-scan-build/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/layout/style -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/components -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-07-21-021012-413605-1 -x c++ Unified_cpp_js_xpconnect_src1.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "nsXULAppAPI.h"
8#include "jsapi.h"
9#include "jsfriendapi.h"
10#include "js/Array.h" // JS::NewArrayObject
11#include "js/CallAndConstruct.h" // JS_CallFunctionValue
12#include "js/CharacterEncoding.h"
13#include "js/CompilationAndEvaluation.h" // JS::Evaluate
14#include "js/ContextOptions.h"
15#include "js/Printf.h"
16#include "js/PropertyAndElement.h" // JS_DefineElement, JS_DefineFunctions, JS_DefineProperty
17#include "js/PropertySpec.h"
18#include "js/SourceText.h" // JS::SourceText
19#include "mozilla/ChaosMode.h"
20#include "mozilla/dom/AutoEntryScript.h"
21#include "mozilla/dom/ScriptSettings.h"
22#include "mozilla/IOInterposer.h"
23#include "mozilla/Preferences.h"
24#include "mozilla/Utf8.h" // mozilla::Utf8Unit
25#include "nsServiceManagerUtils.h"
26#include "nsComponentManagerUtils.h"
27#include "nsExceptionHandler.h"
28#include "nsIServiceManager.h"
29#include "nsIFile.h"
30#include "nsString.h"
31#include "nsIDirectoryService.h"
32#include "nsDirectoryServiceDefs.h"
33#include "nsAppDirectoryServiceDefs.h"
34#include "nscore.h"
35#include "nsArrayEnumerator.h"
36#include "nsCOMArray.h"
37#include "nsDirectoryServiceUtils.h"
38#include "nsCOMPtr.h"
39#include "nsJSPrincipals.h"
40#include "nsJSUtils.h"
41#include "xpcpublic.h"
42#include "xpcprivate.h"
43#include "BackstagePass.h"
44#include "nsIScriptSecurityManager.h"
45#include "nsIPrincipal.h"
46#include "nsJSUtils.h"
47
48#include "nsIXULRuntime.h"
49#include "nsIAppStartup.h"
50#include "Components.h"
51#include "ProfilerControl.h"
52
53#ifdef ANDROID
54# include <android/log.h>
55# include "XREShellData.h"
56#endif
57
58#ifdef XP_WIN
59# include "mozilla/mscom/ProcessRuntime.h"
60# include "mozilla/ScopeExit.h"
61# include "mozilla/widget/AudioSession.h"
62# include "mozilla/WinDllServices.h"
63# include "mozilla/WindowsBCryptInitialization.h"
64# include <windows.h>
65# if defined(MOZ_SANDBOX1)
66# include "XREShellData.h"
67# include "sandboxBroker.h"
68# endif
69#endif
70
71#ifdef MOZ_CODE_COVERAGE
72# include "mozilla/CodeCoverageHandler.h"
73#endif
74
75// all this crap is needed to do the interactive shell stuff
76#include <stdlib.h>
77#include <errno(*__errno_location ()).h>
78#ifdef HAVE_IO_H
79# include <io.h> /* for isatty() */
80#endif
81#ifdef HAVE_UNISTD_H1
82# include <unistd.h> /* for isatty() */
83#endif
84
85#ifdef ENABLE_TESTS1
86# include "xpctest_private.h"
87#endif
88
89// Fuzzing support for XPC runtime fuzzing
90#ifdef FUZZING_INTERFACES
91# include "xpcrtfuzzing/xpcrtfuzzing.h"
92# include "XREShellData.h"
93static bool fuzzDoDebug = !!getenv("MOZ_FUZZ_DEBUG");
94static bool fuzzHaveModule = !!getenv("FUZZER");
95#endif // FUZZING_INTERFACES
96
97using namespace mozilla;
98using namespace JS;
99using mozilla::dom::AutoEntryScript;
100using mozilla::dom::AutoJSAPI;
101
102class XPCShellDirProvider : public nsIDirectoryServiceProvider2 {
103 public:
104 NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override;
105 NS_DECL_NSIDIRECTORYSERVICEPROVIDERvirtual nsresult GetFile(const char * prop, bool *persistent,
nsIFile **_retval) override;
106 NS_DECL_NSIDIRECTORYSERVICEPROVIDER2virtual nsresult GetFiles(const char * prop, nsISimpleEnumerator
**_retval) override;
107
108 XPCShellDirProvider() = default;
109 ~XPCShellDirProvider() = default;
110
111 // The platform resource folder
112 void SetGREDirs(nsIFile* greDir);
113 void ClearGREDirs() {
114 mGREDir = nullptr;
115 mGREBinDir = nullptr;
116 }
117 // The application resource folder
118 void SetAppDir(nsIFile* appFile);
119 void ClearAppDir() { mAppDir = nullptr; }
120 // The app executable
121 void SetAppFile(nsIFile* appFile);
122 void ClearAppFile() { mAppFile = nullptr; }
123
124 private:
125 nsCOMPtr<nsIFile> mGREDir;
126 nsCOMPtr<nsIFile> mGREBinDir;
127 nsCOMPtr<nsIFile> mAppDir;
128 nsCOMPtr<nsIFile> mAppFile;
129};
130
131#ifdef XP_WIN
132class MOZ_STACK_CLASS AutoAudioSession {
133 public:
134 AutoAudioSession() { widget::StartAudioSession(); }
135
136 ~AutoAudioSession() { widget::StopAudioSession(); }
137};
138#endif
139
140#define EXITCODE_RUNTIME_ERROR3 3
141#define EXITCODE_FILE_NOT_FOUND4 4
142
143static FILE* gOutFile = nullptr;
144static FILE* gErrFile = nullptr;
145static FILE* gInFile = nullptr;
146
147static int gExitCode = 0;
148static bool gQuitting = false;
149static bool reportWarnings = true;
150static bool compileOnly = false;
151
152static JSPrincipals* gJSPrincipals = nullptr;
153static nsAutoString* gWorkingDirectory = nullptr;
154
155static bool GetLocationProperty(JSContext* cx, unsigned argc, Value* vp) {
156 CallArgs args = CallArgsFromVp(argc, vp);
157 if (!args.thisv().isObject()) {
158 JS_ReportErrorASCII(cx, "Unexpected this value for GetLocationProperty");
159 return false;
160 }
161#if !defined(XP_WIN) && !defined(XP_UNIX1)
162 // XXX: your platform should really implement this
163 return false;
164#else
165 JS::AutoFilename filename;
166 if (JS::DescribeScriptedCaller(cx, &filename) && filename.get()) {
167 NS_ConvertUTF8toUTF16 filenameString(filename.get());
168
169# if defined(XP_WIN)
170 // replace forward slashes with backslashes,
171 // since nsLocalFileWin chokes on them
172 char16_t* start = filenameString.BeginWriting();
173 char16_t* end = filenameString.EndWriting();
174
175 while (start != end) {
176 if (*start == L'/') {
177 *start = L'\\';
178 }
179 start++;
180 }
181# endif
182
183 nsCOMPtr<nsIFile> location;
184 nsresult rv =
185 NS_NewLocalFile(filenameString, false, getter_AddRefs(location));
186
187 if (!location && gWorkingDirectory) {
188 // could be a relative path, try appending it to the cwd
189 // and then normalize
190 nsAutoString absolutePath(*gWorkingDirectory);
191 absolutePath.Append(filenameString);
192
193 rv = NS_NewLocalFile(absolutePath, false, getter_AddRefs(location));
Value stored to 'rv' is never read
194 }
195
196 if (location) {
197 bool symlink;
198 // don't normalize symlinks, because that's kind of confusing
199 if (NS_SUCCEEDED(location->IsSymlink(&symlink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(location->IsSymlink
(&symlink))), 1)))
&& !symlink)
200 location->Normalize();
201 RootedObject locationObj(cx);
202 RootedObject scope(cx, JS::CurrentGlobalOrNull(cx));
203 rv = nsXPConnect::XPConnect()->WrapNative(
204 cx, scope, location, NS_GET_IID(nsIFile)(nsIFile::COMTypeInfo<nsIFile, void>::kIID), locationObj.address());
205 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && locationObj) {
206 args.rval().setObject(*locationObj);
207 }
208 }
209 }
210
211 return true;
212#endif
213}
214
215static bool GetLine(JSContext* cx, char* bufp, FILE* file, const char* prompt) {
216 fputs(prompt, gOutFile);
217 fflush(gOutFile);
218
219 char line[4096] = {'\0'};
220 while (true) {
221 if (fgets(line, sizeof line, file)) {
222 strcpy(bufp, line);
223 return true;
224 }
225 if (errno(*__errno_location ()) != EINTR4) {
226 return false;
227 }
228 }
229}
230
231static bool ReadLine(JSContext* cx, unsigned argc, Value* vp) {
232 CallArgs args = CallArgsFromVp(argc, vp);
233
234 // While 4096 might be quite arbitrary, this is something to be fixed in
235 // bug 105707. It is also the same limit as in ProcessFile.
236 char buf[4096];
237 RootedString str(cx);
238
239 /* If a prompt was specified, construct the string */
240 if (args.length() > 0) {
241 str = JS::ToString(cx, args[0]);
242 if (!str) {
243 return false;
244 }
245 } else {
246 str = JS_GetEmptyString(cx);
247 }
248
249 /* Get a line from the infile */
250 JS::UniqueChars strBytes = JS_EncodeStringToLatin1(cx, str);
251 if (!strBytes || !GetLine(cx, buf, gInFile, strBytes.get())) {
252 return false;
253 }
254
255 /* Strip newline character added by GetLine() */
256 unsigned int buflen = strlen(buf);
257 if (buflen == 0) {
258 if (feof(gInFile)) {
259 args.rval().setNull();
260 return true;
261 }
262 } else if (buf[buflen - 1] == '\n') {
263 --buflen;
264 }
265
266 /* Turn buf into a JSString */
267 str = JS_NewStringCopyN(cx, buf, buflen);
268 if (!str) {
269 return false;
270 }
271
272 args.rval().setString(str);
273 return true;
274}
275
276static bool Print(JSContext* cx, unsigned argc, Value* vp) {
277 CallArgs args = CallArgsFromVp(argc, vp);
278 args.rval().setUndefined();
279
280#ifdef FUZZING_INTERFACES
281 if (fuzzHaveModule && !fuzzDoDebug) {
282 // When fuzzing and not debugging, suppress any print() output,
283 // as it slows down fuzzing and makes libFuzzer's output hard
284 // to read.
285 return true;
286 }
287#endif // FUZZING_INTERFACES
288
289 RootedString str(cx);
290 nsAutoCString utf8output;
291
292 for (unsigned i = 0; i < args.length(); i++) {
293 str = ToString(cx, args[i]);
294 if (!str) {
295 return false;
296 }
297
298 JS::UniqueChars utf8str = JS_EncodeStringToUTF8(cx, str);
299 if (!utf8str) {
300 return false;
301 }
302
303 if (i) {
304 utf8output.Append(' ');
305 }
306 utf8output.Append(utf8str.get(), strlen(utf8str.get()));
307 }
308 utf8output.Append('\n');
309 fputs(utf8output.get(), gOutFile);
310 fflush(gOutFile);
311 return true;
312}
313
314static bool Dump(JSContext* cx, unsigned argc, Value* vp) {
315 CallArgs args = CallArgsFromVp(argc, vp);
316 args.rval().setUndefined();
317
318 if (!args.length()) {
319 return true;
320 }
321
322 RootedString str(cx, ToString(cx, args[0]));
323 if (!str) {
324 return false;
325 }
326
327 JS::UniqueChars utf8str = JS_EncodeStringToUTF8(cx, str);
328 if (!utf8str) {
329 return false;
330 }
331
332#ifdef ANDROID
333 __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", utf8str.get());
334#endif
335#ifdef XP_WIN
336 if (IsDebuggerPresent()) {
337 nsAutoJSString wstr;
338 if (!wstr.init(cx, str)) {
339 return false;
340 }
341 OutputDebugStringW(wstr.get());
342 }
343#endif
344 fputs(utf8str.get(), gOutFile);
345 fflush(gOutFile);
346 return true;
347}
348
349static bool Load(JSContext* cx, unsigned argc, Value* vp) {
350 CallArgs args = CallArgsFromVp(argc, vp);
351
352 JS::RootedObject thisObject(cx);
353 if (!args.computeThis(cx, &thisObject)) {
354 return false;
355 }
356 if (!JS_IsGlobalObject(thisObject)) {
357 JS_ReportErrorASCII(cx, "Trying to load() into a non-global object");
358 return false;
359 }
360
361 RootedString str(cx);
362 for (unsigned i = 0; i < args.length(); i++) {
363 str = ToString(cx, args[i]);
364 if (!str) {
365 return false;
366 }
367 JS::UniqueChars filename = JS_EncodeStringToUTF8(cx, str);
368 if (!filename) {
369 return false;
370 }
371 JS::CompileOptions options(cx);
372 options.setIsRunOnce(true).setSkipFilenameValidation(true);
373 JS::Rooted<JSScript*> script(
374 cx, JS::CompileUtf8Path(cx, options, filename.get()));
375 if (!script) {
376 return false;
377 }
378
379 if (!compileOnly) {
380 if (!JS_ExecuteScript(cx, script)) {
381 return false;
382 }
383 }
384 }
385 args.rval().setUndefined();
386 return true;
387}
388
389static bool Quit(JSContext* cx, unsigned argc, Value* vp) {
390 CallArgs args = CallArgsFromVp(argc, vp);
391
392 gExitCode = 0;
393 if (!ToInt32(cx, args.get(0), &gExitCode)) {
394 return false;
395 }
396
397 gQuitting = true;
398 // exit(0);
399 return false;
400}
401
402static bool DumpXPC(JSContext* cx, unsigned argc, Value* vp) {
403 JS::CallArgs args = CallArgsFromVp(argc, vp);
404
405 uint16_t depth = 2;
406 if (args.length() > 0) {
407 if (!JS::ToUint16(cx, args[0], &depth)) {
408 return false;
409 }
410 }
411
412 nsXPConnect::XPConnect()->DebugDump(int16_t(depth));
413 args.rval().setUndefined();
414 return true;
415}
416
417static bool GC(JSContext* cx, unsigned argc, Value* vp) {
418 CallArgs args = CallArgsFromVp(argc, vp);
419
420 JS_GC(cx);
421
422 args.rval().setUndefined();
423 return true;
424}
425
426#ifdef JS_GC_ZEAL1
427static bool GCZeal(JSContext* cx, unsigned argc, Value* vp) {
428 CallArgs args = CallArgsFromVp(argc, vp);
429 uint32_t zeal;
430 if (!ToUint32(cx, args.get(0), &zeal)) {
431 return false;
432 }
433
434 JS::SetGCZeal(cx, uint8_t(zeal), JS::ShellDefaultGCZealFrequency);
435 args.rval().setUndefined();
436 return true;
437}
438#endif
439
440static bool SendCommand(JSContext* cx, unsigned argc, Value* vp) {
441 CallArgs args = CallArgsFromVp(argc, vp);
442
443 if (args.length() == 0) {
444 JS_ReportErrorASCII(cx, "Function takes at least one argument!");
445 return false;
446 }
447
448 RootedString str(cx, ToString(cx, args[0]));
449 if (!str) {
450 JS_ReportErrorASCII(cx, "Could not convert argument 1 to string!");
451 return false;
452 }
453
454 if (args.get(1).isObject() && !JS_ObjectIsFunction(&args[1].toObject())) {
455 JS_ReportErrorASCII(cx, "Could not convert argument 2 to function!");
456 return false;
457 }
458
459 if (!XRE_SendTestShellCommand(
460 cx, str, args.length() > 1 ? args[1].address() : nullptr)) {
461 JS_ReportErrorASCII(cx, "Couldn't send command!");
462 return false;
463 }
464
465 args.rval().setUndefined();
466 return true;
467}
468
469static bool Options(JSContext* cx, unsigned argc, Value* vp) {
470 JS::CallArgs args = CallArgsFromVp(argc, vp);
471
472 RootedString str(cx);
473 JS::UniqueChars opt;
474 if (args.length() > 0) {
475 str = ToString(cx, args[0]);
476 if (!str) {
477 return false;
478 }
479
480 opt = JS_EncodeStringToUTF8(cx, str);
481 if (!opt) {
482 return false;
483 }
484
485 JS_ReportErrorUTF8(cx, "unknown option name '%s'.", opt.get());
486 return false;
487 }
488
489 args.rval().setString(JS_GetEmptyString(cx));
490 return true;
491}
492
493static PersistentRootedValue* sScriptedInterruptCallback = nullptr;
494
495static bool XPCShellInterruptCallback(JSContext* cx) {
496 MOZ_ASSERT(sScriptedInterruptCallback->initialized())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sScriptedInterruptCallback->initialized())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sScriptedInterruptCallback->initialized()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("sScriptedInterruptCallback->initialized()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 496); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sScriptedInterruptCallback->initialized()"
")"); do { *((volatile int*)__null) = 496; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
497 RootedValue callback(cx, *sScriptedInterruptCallback);
498
499 // If no interrupt callback was set by script, no-op.
500 if (callback.isUndefined()) {
501 return true;
502 }
503
504 MOZ_ASSERT(js::IsFunctionObject(&callback.toObject()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(js::IsFunctionObject(&callback.toObject()))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(js::IsFunctionObject(&callback.toObject())))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("js::IsFunctionObject(&callback.toObject())"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 504); AnnotateMozCrashReason("MOZ_ASSERT" "(" "js::IsFunctionObject(&callback.toObject())"
")"); do { *((volatile int*)__null) = 504; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
505
506 JSAutoRealm ar(cx, &callback.toObject());
507 RootedValue rv(cx);
508 if (!JS_CallFunctionValue(cx, nullptr, callback,
509 JS::HandleValueArray::empty(), &rv) ||
510 !rv.isBoolean()) {
511 NS_WARNING("Scripted interrupt callback failed! Terminating script.")NS_DebugBreak(NS_DEBUG_WARNING, "Scripted interrupt callback failed! Terminating script."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 511)
;
512 JS_ClearPendingException(cx);
513 return false;
514 }
515
516 return rv.toBoolean();
517}
518
519static bool SetInterruptCallback(JSContext* cx, unsigned argc, Value* vp) {
520 MOZ_ASSERT(sScriptedInterruptCallback->initialized())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sScriptedInterruptCallback->initialized())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sScriptedInterruptCallback->initialized()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("sScriptedInterruptCallback->initialized()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sScriptedInterruptCallback->initialized()"
")"); do { *((volatile int*)__null) = 520; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
521
522 // Sanity-check args.
523 JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
524 if (args.length() != 1) {
525 JS_ReportErrorASCII(cx, "Wrong number of arguments");
526 return false;
527 }
528
529 // Allow callers to remove the interrupt callback by passing undefined.
530 if (args[0].isUndefined()) {
531 *sScriptedInterruptCallback = UndefinedValue();
532 return true;
533 }
534
535 // Otherwise, we should have a function object.
536 if (!args[0].isObject() || !js::IsFunctionObject(&args[0].toObject())) {
537 JS_ReportErrorASCII(cx, "Argument must be a function");
538 return false;
539 }
540
541 *sScriptedInterruptCallback = args[0];
542
543 return true;
544}
545
546static bool SimulateNoScriptActivity(JSContext* cx, unsigned argc, Value* vp) {
547 // Sanity-check args.
548 JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
549 if (args.length() != 1 || !args[0].isInt32() || args[0].toInt32() < 0) {
550 JS_ReportErrorASCII(cx, "Expected a positive integer argument");
551 return false;
552 }
553
554 // This mimics mozilla::SpinEventLoopUntil but instead of spinning the
555 // event loop we sleep, to make sure we don't run script.
556 xpc::AutoScriptActivity asa(false);
557 PR_Sleep(PR_SecondsToInterval(args[0].toInt32()));
558
559 args.rval().setUndefined();
560 return true;
561}
562
563static bool RegisterAppManifest(JSContext* cx, unsigned argc, Value* vp) {
564 JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
565 if (args.length() != 1) {
566 JS_ReportErrorASCII(cx, "Wrong number of arguments");
567 return false;
568 }
569 if (!args[0].isObject()) {
570 JS_ReportErrorASCII(cx,
571 "Expected object as argument 1 to registerAppManifest");
572 return false;
573 }
574
575 Rooted<JSObject*> arg1(cx, &args[0].toObject());
576 nsCOMPtr<nsIFile> file;
577 nsresult rv = nsXPConnect::XPConnect()->WrapJS(cx, arg1, NS_GET_IID(nsIFile)(nsIFile::COMTypeInfo<nsIFile, void>::kIID),
578 getter_AddRefs(file));
579 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
580 XPCThrower::Throw(rv, cx);
581 return false;
582 }
583 rv = XRE_AddManifestLocation(NS_APP_LOCATION, file);
584 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
585 XPCThrower::Throw(rv, cx);
586 return false;
587 }
588 return true;
589}
590
591#ifdef ANDROID
592static bool ChangeTestShellDir(JSContext* cx, unsigned argc, Value* vp) {
593 // This method should only be used by testing/xpcshell/head.js to change to
594 // the correct directory on Android Remote XPCShell tests.
595 //
596 // TODO: Bug 1801725 - Find a more ergonomic way to do this than exposing
597 // identical methods in XPCShellEnvironment and XPCShellImpl to chdir on
598 // android for Remote XPCShell tests on Android.
599 CallArgs args = CallArgsFromVp(argc, vp);
600
601 if (args.length() != 1) {
602 JS_ReportErrorASCII(cx, "changeTestShellDir() takes one argument");
603 return false;
604 }
605
606 nsAutoJSCString path;
607 if (!path.init(cx, args[0])) {
608 JS_ReportErrorASCII(
609 cx, "changeTestShellDir(): could not convert argument 1 to string");
610 return false;
611 }
612
613 if (chdir(path.get())) {
614 JS_ReportErrorASCII(cx, "changeTestShellDir(): could not change directory");
615 return false;
616 }
617
618 return true;
619}
620#endif
621
622#ifdef ENABLE_TESTS1
623static bool RegisterXPCTestComponents(JSContext* cx, unsigned argc, Value* vp) {
624 JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
625 if (args.length() != 0) {
626 JS_ReportErrorASCII(cx, "Wrong number of arguments");
627 return false;
628 }
629 nsresult rv = xpcTestRegisterComponents();
630 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
631 XPCThrower::Throw(rv, cx);
632 return false;
633 }
634 return true;
635}
636#endif
637
638static const JSFunctionSpec glob_functions[] = {
639 // clang-format off
640 JS_FN("print", Print, 0,0){JSFunctionSpec::Name("print"), {Print, nullptr}, 0, 0, nullptr
}
,
641 JS_FN("readline", ReadLine, 1,0){JSFunctionSpec::Name("readline"), {ReadLine, nullptr}, 1, 0,
nullptr}
,
642 JS_FN("load", Load, 1,0){JSFunctionSpec::Name("load"), {Load, nullptr}, 1, 0, nullptr
}
,
643 JS_FN("quit", Quit, 0,0){JSFunctionSpec::Name("quit"), {Quit, nullptr}, 0, 0, nullptr
}
,
644 JS_FN("dumpXPC", DumpXPC, 1,0){JSFunctionSpec::Name("dumpXPC"), {DumpXPC, nullptr}, 1, 0, nullptr
}
,
645 JS_FN("dump", Dump, 1,0){JSFunctionSpec::Name("dump"), {Dump, nullptr}, 1, 0, nullptr
}
,
646 JS_FN("gc", GC, 0,0){JSFunctionSpec::Name("gc"), {GC, nullptr}, 0, 0, nullptr},
647#ifdef JS_GC_ZEAL1
648 JS_FN("gczeal", GCZeal, 1,0){JSFunctionSpec::Name("gczeal"), {GCZeal, nullptr}, 1, 0, nullptr
}
,
649#endif
650 JS_FN("options", Options, 0,0){JSFunctionSpec::Name("options"), {Options, nullptr}, 0, 0, nullptr
}
,
651 JS_FN("sendCommand", SendCommand, 1,0){JSFunctionSpec::Name("sendCommand"), {SendCommand, nullptr},
1, 0, nullptr}
,
652 JS_FN("atob", xpc::Atob, 1,0){JSFunctionSpec::Name("atob"), {xpc::Atob, nullptr}, 1, 0, nullptr
}
,
653 JS_FN("btoa", xpc::Btoa, 1,0){JSFunctionSpec::Name("btoa"), {xpc::Btoa, nullptr}, 1, 0, nullptr
}
,
654 JS_FN("setInterruptCallback", SetInterruptCallback, 1,0){JSFunctionSpec::Name("setInterruptCallback"), {SetInterruptCallback
, nullptr}, 1, 0, nullptr}
,
655 JS_FN("simulateNoScriptActivity", SimulateNoScriptActivity, 1,0){JSFunctionSpec::Name("simulateNoScriptActivity"), {SimulateNoScriptActivity
, nullptr}, 1, 0, nullptr}
,
656 JS_FN("registerAppManifest", RegisterAppManifest, 1, 0){JSFunctionSpec::Name("registerAppManifest"), {RegisterAppManifest
, nullptr}, 1, 0, nullptr}
,
657#ifdef ANDROID
658 JS_FN("changeTestShellDir", ChangeTestShellDir, 1,0){JSFunctionSpec::Name("changeTestShellDir"), {ChangeTestShellDir
, nullptr}, 1, 0, nullptr}
,
659#endif
660#ifdef ENABLE_TESTS1
661 JS_FN("registerXPCTestComponents", RegisterXPCTestComponents, 0, 0){JSFunctionSpec::Name("registerXPCTestComponents"), {RegisterXPCTestComponents
, nullptr}, 0, 0, nullptr}
,
662#endif
663 JS_FS_END{JSFunctionSpec::Name(nullptr), {nullptr, nullptr}, 0, 0, nullptr
}
664 // clang-format on
665};
666
667/***************************************************************************/
668
669typedef enum JSShellErrNum {
670#define MSG_DEF(name, number, count, exception, format) name = number,
671#include "jsshell.msg"
672#undef MSG_DEF
673 JSShellErr_Limit
674} JSShellErrNum;
675
676static const JSErrorFormatString jsShell_ErrorFormatString[JSShellErr_Limit] = {
677#define MSG_DEF(name, number, count, exception, format) {#name, format, count},
678#include "jsshell.msg"
679#undef MSG_DEF
680};
681
682static const JSErrorFormatString* my_GetErrorMessage(
683 void* userRef, const unsigned errorNumber) {
684 if (errorNumber == 0 || errorNumber >= JSShellErr_Limit) {
685 return nullptr;
686 }
687
688 return &jsShell_ErrorFormatString[errorNumber];
689}
690
691static bool ProcessUtf8Line(AutoJSAPI& jsapi, const char* buffer,
692 int startline) {
693 JSContext* cx = jsapi.cx();
694 JS::CompileOptions options(cx);
695 options.setFileAndLine("typein", startline)
696 .setIsRunOnce(true)
697 .setSkipFilenameValidation(true);
698
699 JS::SourceText<mozilla::Utf8Unit> srcBuf;
700 if (!srcBuf.init(cx, buffer, strlen(buffer), JS::SourceOwnership::Borrowed)) {
701 return false;
702 }
703
704 JS::RootedScript script(cx, JS::Compile(cx, options, srcBuf));
705 if (!script) {
706 return false;
707 }
708 if (compileOnly) {
709 return true;
710 }
711
712 JS::RootedValue result(cx);
713 if (!JS_ExecuteScript(cx, script, &result)) {
714 return false;
715 }
716
717 if (result.isUndefined()) {
718 return true;
719 }
720
721 RootedString str(cx, JS::ToString(cx, result));
722 if (!str) {
723 return false;
724 }
725
726 JS::UniqueChars bytes = JS_EncodeStringToLatin1(cx, str);
727 if (!bytes) {
728 return false;
729 }
730
731 fprintf(gOutFile, "%s\n", bytes.get());
732 return true;
733}
734
735static bool ProcessFile(AutoJSAPI& jsapi, const char* filename, FILE* file,
736 bool forceTTY) {
737 JSContext* cx = jsapi.cx();
738 JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
739 MOZ_ASSERT(global)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(global)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(global))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("global", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "global" ")")
; do { *((volatile int*)__null) = 739; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
740
741 if (forceTTY) {
742 file = stdinstdin;
743 } else if (!isatty(fileno(file))) {
744 /*
745 * It's not interactive - just execute it.
746 *
747 * Support the UNIX #! shell hack; gobble the first line if it starts
748 * with '#'.
749 */
750 int ch = fgetc(file);
751 if (ch == '#') {
752 while ((ch = fgetc(file)) != EOF(-1)) {
753 if (ch == '\n' || ch == '\r') {
754 break;
755 }
756 }
757 }
758 ungetc(ch, file);
759
760 JS::UniqueChars filenameUtf8 = JS::EncodeNarrowToUtf8(jsapi.cx(), filename);
761 if (!filenameUtf8) {
762 return false;
763 }
764
765 JS::RootedScript script(cx);
766 JS::RootedValue unused(cx);
767 JS::CompileOptions options(cx);
768 options.setFileAndLine(filenameUtf8.get(), 1)
769 .setIsRunOnce(true)
770 .setNoScriptRval(true)
771 .setSkipFilenameValidation(true);
772 script = JS::CompileUtf8File(cx, options, file);
773 if (!script) {
774 return false;
775 }
776 return compileOnly || JS_ExecuteScript(cx, script, &unused);
777 }
778
779 /* It's an interactive filehandle; drop into read-eval-print loop. */
780 int lineno = 1;
781 bool hitEOF = false;
782 do {
783 char buffer[4096];
784 char* bufp = buffer;
785 *bufp = '\0';
786
787 /*
788 * Accumulate lines until we get a 'compilable unit' - one that either
789 * generates an error (before running out of source) or that compiles
790 * cleanly. This should be whenever we get a complete statement that
791 * coincides with the end of a line.
792 */
793 int startline = lineno;
794 do {
795 if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
796 hitEOF = true;
797 break;
798 }
799 bufp += strlen(bufp);
800 lineno++;
801 } while (
802 !JS_Utf8BufferIsCompilableUnit(cx, global, buffer, strlen(buffer)));
803
804 if (!ProcessUtf8Line(jsapi, buffer, startline)) {
805 jsapi.ReportException();
806 }
807 } while (!hitEOF && !gQuitting);
808
809 fprintf(gOutFile, "\n");
810 return true;
811}
812
813static bool Process(AutoJSAPI& jsapi, const char* filename, bool forceTTY) {
814 FILE* file;
815
816 if (forceTTY || !filename || strcmp(filename, "-") == 0) {
817 file = stdinstdin;
818 } else {
819 file = fopen(filename, "r");
820 if (!file) {
821 /*
822 * Use Latin1 variant here because the encoding of the return value
823 * of strerror function can be non-UTF-8.
824 */
825 JS_ReportErrorNumberLatin1(jsapi.cx(), my_GetErrorMessage, nullptr,
826 JSSMSG_CANT_OPEN, filename, strerror(errno(*__errno_location ())));
827 gExitCode = EXITCODE_FILE_NOT_FOUND4;
828 return false;
829 }
830 }
831
832 bool ok = ProcessFile(jsapi, filename, file, forceTTY);
833 if (file != stdinstdin) {
834 fclose(file);
835 }
836 return ok;
837}
838
839static int usage() {
840 fprintf(gErrFile, "%s\n", JS_GetImplementationVersion());
841 fprintf(
842 gErrFile,
843 "usage: xpcshell [-g gredir] [-a appdir] [-r manifest]... [-WwxiCmIp] "
844 "[-f scriptfile] [-e script] [scriptfile] [scriptarg...]\n");
845 return 2;
846}
847
848static bool printUsageAndSetExitCode() {
849 gExitCode = usage();
850 return false;
851}
852
853static bool ProcessArgs(AutoJSAPI& jsapi, char** argv, int argc,
854 XPCShellDirProvider* aDirProvider) {
855 JSContext* cx = jsapi.cx();
856 const char rcfilename[] = "xpcshell.js";
857 FILE* rcfile;
858 int rootPosition;
859 JS::Rooted<JSObject*> argsObj(cx);
860 char* filename = nullptr;
861 bool isInteractive = true;
862 bool forceTTY = false;
863
864 rcfile = fopen(rcfilename, "r");
865 if (rcfile) {
866 printf("[loading '%s'...]\n", rcfilename);
867 bool ok = ProcessFile(jsapi, rcfilename, rcfile, false);
868 fclose(rcfile);
869 if (!ok) {
870 return false;
871 }
872 }
873
874 JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
875
876 /*
877 * Scan past all optional arguments so we can create the arguments object
878 * before processing any -f options, which must interleave properly with
879 * -v and -w options. This requires two passes, and without getopt, we'll
880 * have to keep the option logic here and in the second for loop in sync.
881 * First of all, find out the first argument position which will be passed
882 * as a script file to be executed.
883 */
884 for (rootPosition = 0; rootPosition < argc; rootPosition++) {
885 if (argv[rootPosition][0] != '-' || argv[rootPosition][1] == '\0') {
886 ++rootPosition;
887 break;
888 }
889
890 bool isPairedFlag =
891 argv[rootPosition][0] != '\0' &&
892 (argv[rootPosition][1] == 'v' || argv[rootPosition][1] == 'f' ||
893 argv[rootPosition][1] == 'e');
894 if (isPairedFlag && rootPosition < argc - 1) {
895 ++rootPosition; // Skip over the 'foo' portion of |-v foo|, |-f foo|, or
896 // |-e foo|.
897 }
898 }
899
900 /*
901 * Create arguments early and define it to root it, so it's safe from any
902 * GC calls nested below, and so it is available to -f <file> arguments.
903 */
904 argsObj = JS::NewArrayObject(cx, 0);
905 if (!argsObj) {
906 return 1;
907 }
908 if (!JS_DefineProperty(cx, global, "arguments", argsObj, 0)) {
909 return 1;
910 }
911
912 for (int j = 0, length = argc - rootPosition; j < length; j++) {
913 RootedString str(cx, JS_NewStringCopyZ(cx, argv[rootPosition++]));
914 if (!str || !JS_DefineElement(cx, argsObj, j, str, JSPROP_ENUMERATE)) {
915 return 1;
916 }
917 }
918
919 for (int i = 0; i < argc; i++) {
920 if (argv[i][0] != '-' || argv[i][1] == '\0') {
921 filename = argv[i++];
922 isInteractive = false;
923 break;
924 }
925 switch (argv[i][1]) {
926 case 'W':
927 reportWarnings = false;
928 break;
929 case 'w':
930 reportWarnings = true;
931 break;
932 case 'x':
933 break;
934 case 'd':
935 /* This used to try to turn on the debugger. */
936 break;
937 case 'm':
938 break;
939 case 'f':
940 if (++i == argc) {
941 return printUsageAndSetExitCode();
942 }
943 if (!Process(jsapi, argv[i], false)) {
944 return false;
945 }
946 /*
947 * XXX: js -f foo.js should interpret foo.js and then
948 * drop into interactive mode, but that breaks test
949 * harness. Just execute foo.js for now.
950 */
951 isInteractive = false;
952 break;
953 case 'i':
954 isInteractive = forceTTY = true;
955 break;
956 case 'e': {
957 RootedValue rval(cx);
958
959 if (++i == argc) {
960 return printUsageAndSetExitCode();
961 }
962
963 JS::CompileOptions opts(cx);
964 opts.setSkipFilenameValidation(true);
965 opts.setFileAndLine("-e", 1);
966
967 JS::SourceText<mozilla::Utf8Unit> srcBuf;
968 if (srcBuf.init(cx, argv[i], strlen(argv[i]),
969 JS::SourceOwnership::Borrowed)) {
970 JS::Evaluate(cx, opts, srcBuf, &rval);
971 }
972
973 isInteractive = false;
974 break;
975 }
976 case 'C':
977 compileOnly = true;
978 isInteractive = false;
979 break;
980 default:
981 return printUsageAndSetExitCode();
982 }
983 }
984
985 if (filename || isInteractive) {
986 return Process(jsapi, filename, forceTTY);
987 }
988 return true;
989}
990
991/***************************************************************************/
992
993static bool GetCurrentWorkingDirectory(nsAString& workingDirectory) {
994#if !defined(XP_WIN) && !defined(XP_UNIX1)
995 // XXX: your platform should really implement this
996 return false;
997#elif XP_WIN
998 DWORD requiredLength = GetCurrentDirectoryW(0, nullptr);
999 workingDirectory.SetLength(requiredLength);
1000 GetCurrentDirectoryW(workingDirectory.Length(),
1001 (LPWSTR)workingDirectory.BeginWriting());
1002 // we got a trailing null there
1003 workingDirectory.SetLength(requiredLength);
1004 workingDirectory.Replace(workingDirectory.Length() - 1, 1, L'\\');
1005#elif defined(XP_UNIX1)
1006 nsAutoCString cwd;
1007 // 1024 is just a guess at a sane starting value
1008 size_t bufsize = 1024;
1009 char* result = nullptr;
1010 while (result == nullptr) {
1011 cwd.SetLength(bufsize);
1012 result = getcwd(cwd.BeginWriting(), cwd.Length());
1013 if (!result) {
1014 if (errno(*__errno_location ()) != ERANGE34) {
1015 return false;
1016 }
1017 // need to make the buffer bigger
1018 bufsize *= 2;
1019 }
1020 }
1021 // size back down to the actual string length
1022 cwd.SetLength(strlen(result) + 1);
1023 cwd.Replace(cwd.Length() - 1, 1, '/');
1024 CopyUTF8toUTF16(cwd, workingDirectory);
1025#endif
1026 return true;
1027}
1028
1029static JSSecurityCallbacks shellSecurityCallbacks;
1030
1031int XRE_XPCShellMain(int argc, char** argv, char** envp,
1032 const XREShellData* aShellData) {
1033 MOZ_ASSERT(aShellData)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aShellData)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aShellData))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aShellData", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aShellData"
")"); do { *((volatile int*)__null) = 1033; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1034
1035 JSContext* cx;
1036 int result = 0;
1037 nsresult rv;
1038
1039#ifdef ANDROID
1040 gOutFile = aShellData->outFile;
1041 gErrFile = aShellData->errFile;
1042#else
1043 gOutFile = stdoutstdout;
1044 gErrFile = stderrstderr;
1045#endif
1046 gInFile = stdinstdin;
1047
1048 NS_LogInit();
1049
1050 mozilla::LogModule::Init(argc, argv);
1051
1052 // This guard ensures that all threads that attempt to register themselves
1053 // with the IOInterposer will be properly tracked.
1054 mozilla::AutoIOInterposer ioInterposerGuard;
1055 ioInterposerGuard.Init();
1056
1057 XRE_InitCommandLine(argc, argv);
1058
1059 char aLocal;
1060 profiler_init(&aLocal);
1061
1062#ifdef MOZ_ASAN_REPORTER
1063 PR_SetEnv("MOZ_DISABLE_ASAN_REPORTER=1");
1064#endif
1065
1066 if (PR_GetEnv("MOZ_CHAOSMODE")) {
1067 ChaosFeature feature = ChaosFeature::Any;
1068 long featureInt = strtol(PR_GetEnv("MOZ_CHAOSMODE"), nullptr, 16);
1069 if (featureInt) {
1070 // NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
1071 feature = static_cast<ChaosFeature>(featureInt);
1072 }
1073 ChaosMode::SetChaosFeature(feature);
1074 }
1075
1076 if (ChaosMode::isActive(ChaosFeature::Any)) {
1077 printf_stderr(
1078 "*** You are running in chaos test mode. See ChaosMode.h. ***\n");
1079 }
1080
1081#ifdef XP_WIN
1082 // Some COM settings are global to the process and must be set before any non-
1083 // trivial COM is run in the application. Since these settings may affect
1084 // stability, we should instantiate COM ASAP so that we can ensure that these
1085 // global settings are configured before anything can interfere.
1086 mscom::ProcessRuntime mscom;
1087
1088# ifdef MOZ_SANDBOX1
1089 nsAutoString binDirPath;
1090# endif
1091#endif
1092
1093 // The provider needs to outlive the call to shutting down XPCOM.
1094 XPCShellDirProvider dirprovider;
1095
1096 { // Start scoping nsCOMPtrs
1097 nsCOMPtr<nsIFile> appFile;
1098 rv = XRE_GetBinaryPath(getter_AddRefs(appFile));
1099 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1100 printf("Couldn't find application file.\n");
1101 return 1;
1102 }
1103 nsCOMPtr<nsIFile> appDir;
1104 rv = appFile->GetParent(getter_AddRefs(appDir));
1105 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1106 printf("Couldn't get application directory.\n");
1107 return 1;
1108 }
1109
1110#if defined(XP_WIN) && defined(MOZ_SANDBOX1)
1111 // We need the binary directory to initialize the windows sandbox.
1112 MOZ_ALWAYS_SUCCEEDS(appDir->GetPath(binDirPath))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(appDir->GetPath(binDirPath))), 1)))), 1))) { } else { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(appDir->GetPath(binDirPath))" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1112); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(appDir->GetPath(binDirPath))" ")"); do
{ *((volatile int*)__null) = 1112; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
1113#endif
1114
1115 dirprovider.SetAppFile(appFile);
1116
1117 nsCOMPtr<nsIFile> greDir;
1118 if (argc > 1 && !strcmp(argv[1], "-g")) {
1119 if (argc < 3) {
1120 return usage();
1121 }
1122
1123 rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(greDir));
1124 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1125 printf("Couldn't use given GRE dir.\n");
1126 return 1;
1127 }
1128
1129 dirprovider.SetGREDirs(greDir);
1130
1131 argc -= 2;
1132 argv += 2;
1133 } else {
1134#ifdef XP_MACOSX
1135 // On OSX, the GreD needs to point to Contents/Resources in the .app
1136 // bundle. Libraries will be loaded at a relative path to GreD, i.e.
1137 // ../MacOS.
1138 nsCOMPtr<nsIFile> tmpDir;
1139 XRE_GetFileFromPath(argv[0], getter_AddRefs(greDir));
1140 greDir->GetParent(getter_AddRefs(tmpDir));
1141 tmpDir->Clone(getter_AddRefs(greDir));
1142 tmpDir->SetNativeLeafName("Resources"_ns);
1143 bool dirExists = false;
1144 tmpDir->Exists(&dirExists);
1145 if (dirExists) {
1146 greDir = tmpDir.forget();
1147 }
1148 dirprovider.SetGREDirs(greDir);
1149#else
1150 nsAutoString workingDir;
1151 if (!GetCurrentWorkingDirectory(workingDir)) {
1152 printf("GetCurrentWorkingDirectory failed.\n");
1153 return 1;
1154 }
1155 rv = NS_NewLocalFile(workingDir, true, getter_AddRefs(greDir));
1156 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1157 printf("NS_NewLocalFile failed.\n");
1158 return 1;
1159 }
1160#endif
1161 }
1162
1163 if (argc > 1 && !strcmp(argv[1], "-a")) {
1164 if (argc < 3) {
1165 return usage();
1166 }
1167
1168 nsCOMPtr<nsIFile> dir;
1169 rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(dir));
1170 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1171 appDir = dir;
1172 dirprovider.SetAppDir(appDir);
1173 }
1174 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1175 printf("Couldn't use given appdir.\n");
1176 return 1;
1177 }
1178 argc -= 2;
1179 argv += 2;
1180 }
1181
1182 while (argc > 1 && !strcmp(argv[1], "-r")) {
1183 if (argc < 3) {
1184 return usage();
1185 }
1186
1187 nsCOMPtr<nsIFile> lf;
1188 rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(lf));
1189 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1190 printf("Couldn't get manifest file.\n");
1191 return 1;
1192 }
1193 XRE_AddManifestLocation(NS_APP_LOCATION, lf);
1194
1195 argc -= 2;
1196 argv += 2;
1197 }
1198
1199 const char* val = getenv("MOZ_CRASHREPORTER");
1200 if (val && *val && !CrashReporter::IsDummy()) {
1201 rv = CrashReporter::SetExceptionHandler(greDir, true);
1202 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1203 printf("CrashReporter::SetExceptionHandler failed!\n");
1204 return 1;
1205 }
1206 MOZ_ASSERT(CrashReporter::GetEnabled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(CrashReporter::GetEnabled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(CrashReporter::GetEnabled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("CrashReporter::GetEnabled()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CrashReporter::GetEnabled()"
")"); do { *((volatile int*)__null) = 1206; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1207 }
1208
1209 if (argc > 1 && !strcmp(argv[1], "--greomni")) {
1210 nsCOMPtr<nsIFile> greOmni;
1211 XRE_GetFileFromPath(argv[2], getter_AddRefs(greOmni));
1212 XRE_InitOmnijar(greOmni, greOmni);
1213 argc -= 2;
1214 argv += 2;
1215 }
1216
1217 rv = NS_InitXPCOM(nullptr, appDir, &dirprovider);
1218 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1219 printf("NS_InitXPCOM failed!\n");
1220 return 1;
1221 }
1222
1223 // xpc::ErrorReport::LogToConsoleWithStack needs this to print errors
1224 // to stderr.
1225 Preferences::SetBool("browser.dom.window.dump.enabled", true);
1226 Preferences::SetBool("devtools.console.stdout.chrome", true);
1227
1228 AutoJSAPI jsapi;
1229 jsapi.Init();
1230 cx = jsapi.cx();
1231
1232 // Override the default XPConnect interrupt callback. We could store the
1233 // old one and restore it before shutting down, but there's not really a
1234 // reason to bother.
1235 sScriptedInterruptCallback = new PersistentRootedValue;
1236 sScriptedInterruptCallback->init(cx, UndefinedValue());
1237
1238 JS_AddInterruptCallback(cx, XPCShellInterruptCallback);
1239
1240 argc--;
1241 argv++;
1242
1243 nsCOMPtr<nsIPrincipal> systemprincipal;
1244 // Fetch the system principal and store it away in a global, to use for
1245 // script compilation in Load() and ProcessFile() (including interactive
1246 // eval loop)
1247 {
1248 nsCOMPtr<nsIScriptSecurityManager> securityManager =
1249 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1", &rv);
1250 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && securityManager) {
1251 rv = securityManager->GetSystemPrincipal(
1252 getter_AddRefs(systemprincipal));
1253 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1254 fprintf(gErrFile,
1255 "+++ Failed to obtain SystemPrincipal from "
1256 "ScriptSecurityManager service.\n");
1257 } else {
1258 // fetch the JS principals and stick in a global
1259 gJSPrincipals = nsJSPrincipals::get(systemprincipal);
1260 JS_HoldPrincipals(gJSPrincipals);
1261 }
1262 } else {
1263 fprintf(gErrFile,
1264 "+++ Failed to get ScriptSecurityManager service, running "
1265 "without principals");
1266 }
1267 }
1268
1269 const JSSecurityCallbacks* scb = JS_GetSecurityCallbacks(cx);
1270 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(scb)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(scb))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("scb" " (" "We are assuming that nsScriptSecurityManager::Init() has been run"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "scb" ") (" "We are assuming that nsScriptSecurityManager::Init() has been run"
")"); do { *((volatile int*)__null) = 1272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1271 scb,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(scb)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(scb))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("scb" " (" "We are assuming that nsScriptSecurityManager::Init() has been run"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "scb" ") (" "We are assuming that nsScriptSecurityManager::Init() has been run"
")"); do { *((volatile int*)__null) = 1272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1272 "We are assuming that nsScriptSecurityManager::Init() has been run")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(scb)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(scb))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("scb" " (" "We are assuming that nsScriptSecurityManager::Init() has been run"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "scb" ") (" "We are assuming that nsScriptSecurityManager::Init() has been run"
")"); do { *((volatile int*)__null) = 1272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1273 shellSecurityCallbacks = *scb;
1274 JS_SetSecurityCallbacks(cx, &shellSecurityCallbacks);
1275
1276 auto backstagePass = MakeRefPtr<BackstagePass>();
1277
1278 // Make the default XPCShell global use a fresh zone (rather than the
1279 // System Zone) to improve cross-zone test coverage.
1280 JS::RealmOptions options;
1281 options.creationOptions().setNewCompartmentAndZone();
1282 xpc::SetPrefableRealmOptions(options);
1283
1284 // Even if we're building in a configuration where source is
1285 // discarded, there's no reason to do that on XPCShell, and doing so
1286 // might break various automation scripts.
1287 options.behaviors().setDiscardSource(false);
1288
1289 JS::Rooted<JSObject*> glob(cx);
1290 rv = xpc::InitClassesWithNewWrappedGlobal(
1291 cx, static_cast<nsIGlobalObject*>(backstagePass), systemprincipal, 0,
1292 options, &glob);
1293 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1294 return 1;
1295 }
1296
1297 // Initialize e10s check on the main thread, if not already done
1298 BrowserTabsRemoteAutostart();
1299#if defined(XP_WIN)
1300 // Plugin may require audio session if installed plugin can initialize
1301 // asynchronized.
1302 AutoAudioSession audioSession;
1303
1304 // Ensure that DLL Services are running
1305 RefPtr<DllServices> dllSvc(DllServices::Get());
1306 dllSvc->StartUntrustedModulesProcessor(true);
1307 auto dllServicesDisable =
1308 MakeScopeExit([&dllSvc]() { dllSvc->DisableFull(); });
1309
1310# if defined(MOZ_SANDBOX1)
1311 // Required for sandboxed child processes.
1312 if (aShellData->sandboxBrokerServices) {
1313 SandboxBroker::Initialize(aShellData->sandboxBrokerServices, binDirPath);
1314 SandboxBroker::GeckoDependentInitialize();
1315 } else {
1316 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed "
"processes will fail to start.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1318)
1317 "Failed to initialize broker services, sandboxed "NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed "
"processes will fail to start.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1318)
1318 "processes will fail to start.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed "
"processes will fail to start.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1318)
;
1319 }
1320# endif // defined(MOZ_SANDBOX)
1321
1322 {
1323 DebugOnly<bool> result = WindowsBCryptInitialization();
1324 MOZ_ASSERT(result)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(result)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(result))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("result", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "result" ")"
); do { *((volatile int*)__null) = 1324; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1325 }
1326#endif // defined(XP_WIN)
1327
1328#ifdef MOZ_CODE_COVERAGE
1329 CodeCoverageHandler::Init();
1330#endif
1331
1332 {
1333 if (!glob) {
1334 return 1;
1335 }
1336
1337 nsCOMPtr<nsIAppStartup> appStartup(components::AppStartup::Service());
1338 if (!appStartup) {
1339 return 1;
1340 }
1341 appStartup->DoneStartingUp();
1342
1343 backstagePass->SetGlobalObject(glob);
1344
1345 JSAutoRealm ar(cx, glob);
1346
1347 if (!JS_InitReflectParse(cx, glob)) {
1348 return 1;
1349 }
1350
1351 if (!JS_DefineFunctions(cx, glob, glob_functions)) {
1352 return 1;
1353 }
1354
1355 nsAutoString workingDirectory;
1356 if (GetCurrentWorkingDirectory(workingDirectory)) {
1357 gWorkingDirectory = &workingDirectory;
1358 }
1359
1360 JS_DefineProperty(cx, glob, "__LOCATION__", GetLocationProperty, nullptr,
1361 0);
1362
1363 {
1364#ifdef FUZZING_INTERFACES
1365 if (fuzzHaveModule) {
1366 // argv[0] was removed previously, but libFuzzer expects it
1367 argc++;
1368 argv--;
1369
1370 result = FuzzXPCRuntimeStart(&jsapi, &argc, &argv, aShellData);
1371 } else {
1372#endif
1373 // We are almost certainly going to run script here, so we need an
1374 // AutoEntryScript. This is Gecko-specific and not in any spec.
1375 AutoEntryScript aes(backstagePass, "xpcshell argument processing");
1376
1377 // If an exception is thrown, we'll set our return code
1378 // appropriately, and then let the AutoEntryScript destructor report
1379 // the error to the console.
1380 if (!ProcessArgs(aes, argv, argc, &dirprovider)) {
1381 if (gExitCode) {
1382 result = gExitCode;
1383 } else if (gQuitting) {
1384 result = 0;
1385 } else {
1386 result = EXITCODE_RUNTIME_ERROR3;
1387 }
1388 }
1389#ifdef FUZZING_INTERFACES
1390 }
1391#endif
1392 }
1393
1394 // Signal that we're now shutting down.
1395 nsCOMPtr<nsIObserver> obs = do_QueryInterface(appStartup);
1396 if (obs) {
1397 obs->Observe(nullptr, "quit-application-forced", nullptr);
1398 }
1399
1400 JS_DropPrincipals(cx, gJSPrincipals);
1401 JS_SetAllNonReservedSlotsToUndefined(glob);
1402 JS::RootedObject lexicalEnv(cx, JS_GlobalLexicalEnvironment(glob));
1403 JS_SetAllNonReservedSlotsToUndefined(lexicalEnv);
1404 JS_GC(cx);
1405 }
1406 JS_GC(cx);
1407
1408 dirprovider.ClearGREDirs();
1409 dirprovider.ClearAppDir();
1410 dirprovider.ClearAppFile();
1411 } // this scopes the nsCOMPtrs
1412
1413 if (!XRE_ShutdownTestShell()) {
1414 NS_ERROR("problem shutting down testshell")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "problem shutting down testshell"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1414); MOZ_PretendNoReturn(); } while (0)
;
1415 }
1416
1417 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
1418 rv = NS_ShutdownXPCOM(nullptr);
1419 MOZ_ASSERT(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"NS_ShutdownXPCOM failed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "NS_ShutdownXPCOM failed" ")"); do { *((volatile int*)
__null) = 1419; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1420
1421 // Shut down the crashreporter service to prevent leaking some strings it
1422 // holds.
1423 if (CrashReporter::GetEnabled()) {
1424 CrashReporter::UnsetExceptionHandler();
1425 }
1426
1427 // This must precede NS_LogTerm(), otherwise xpcshell return non-zero
1428 // during some tests, which causes failures.
1429 profiler_shutdown();
1430
1431 NS_LogTerm();
1432
1433 XRE_DeinitCommandLine();
1434
1435 return result;
1436}
1437
1438void XPCShellDirProvider::SetGREDirs(nsIFile* greDir) {
1439 mGREDir = greDir;
1440 mGREDir->Clone(getter_AddRefs(mGREBinDir));
1441
1442#ifdef XP_MACOSX
1443 nsAutoCString leafName;
1444 mGREDir->GetNativeLeafName(leafName);
1445 if (leafName.EqualsLiteral("Resources")) {
1446 mGREBinDir->SetNativeLeafName("MacOS"_ns);
1447 }
1448#endif
1449}
1450
1451void XPCShellDirProvider::SetAppFile(nsIFile* appFile) { mAppFile = appFile; }
1452
1453void XPCShellDirProvider::SetAppDir(nsIFile* appDir) { mAppDir = appDir; }
1454
1455NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
1456XPCShellDirProvider::AddRef() { return 2; }
1457
1458NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
1459XPCShellDirProvider::Release() { return 1; }
1460
1461NS_IMPL_QUERY_INTERFACE(XPCShellDirProvider, nsIDirectoryServiceProvider,nsresult XPCShellDirProvider::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1462); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<XPCShellDirProvider, nsIDirectoryServiceProvider
>, int32_t( reinterpret_cast<char*>(static_cast<nsIDirectoryServiceProvider
*>((XPCShellDirProvider*)0x1000)) - reinterpret_cast<char
*>((XPCShellDirProvider*)0x1000))}, {&mozilla::detail::
kImplementedIID<XPCShellDirProvider, nsIDirectoryServiceProvider2
>, int32_t( reinterpret_cast<char*>(static_cast<nsIDirectoryServiceProvider2
*>((XPCShellDirProvider*)0x1000)) - reinterpret_cast<char
*>((XPCShellDirProvider*)0x1000))}, {&mozilla::detail::
kImplementedIID<XPCShellDirProvider, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIDirectoryServiceProvider*>((XPCShellDirProvider
*)0x1000))) - reinterpret_cast<char*>((XPCShellDirProvider
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
1462 nsIDirectoryServiceProvider2)nsresult XPCShellDirProvider::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src/XPCShellImpl.cpp"
, 1462); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<XPCShellDirProvider, nsIDirectoryServiceProvider
>, int32_t( reinterpret_cast<char*>(static_cast<nsIDirectoryServiceProvider
*>((XPCShellDirProvider*)0x1000)) - reinterpret_cast<char
*>((XPCShellDirProvider*)0x1000))}, {&mozilla::detail::
kImplementedIID<XPCShellDirProvider, nsIDirectoryServiceProvider2
>, int32_t( reinterpret_cast<char*>(static_cast<nsIDirectoryServiceProvider2
*>((XPCShellDirProvider*)0x1000)) - reinterpret_cast<char
*>((XPCShellDirProvider*)0x1000))}, {&mozilla::detail::
kImplementedIID<XPCShellDirProvider, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIDirectoryServiceProvider*>((XPCShellDirProvider
*)0x1000))) - reinterpret_cast<char*>((XPCShellDirProvider
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
1463
1464NS_IMETHODIMPnsresult
1465XPCShellDirProvider::GetFile(const char* prop, bool* persistent,
1466 nsIFile** result) {
1467 if (mGREDir && !strcmp(prop, NS_GRE_DIR"GreD")) {
1468 *persistent = true;
1469 return mGREDir->Clone(result);
1470 } else if (mGREBinDir && !strcmp(prop, NS_GRE_BIN_DIR"GreBinD")) {
1471 *persistent = true;
1472 return mGREBinDir->Clone(result);
1473 } else if (mAppFile && !strcmp(prop, XRE_EXECUTABLE_FILE"XREExeF")) {
1474 *persistent = true;
1475 return mAppFile->Clone(result);
1476 } else if (mGREDir && !strcmp(prop, NS_APP_PREF_DEFAULTS_50_DIR"PrfDef")) {
1477 nsCOMPtr<nsIFile> file;
1478 *persistent = true;
1479 if (NS_FAILED(mGREDir->Clone(getter_AddRefs(file)))((bool)(__builtin_expect(!!(NS_FAILED_impl(mGREDir->Clone(
getter_AddRefs(file)))), 0)))
||
1480 NS_FAILED(file->AppendNative("defaults"_ns))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->AppendNative
("defaults"_ns))), 0)))
||
1481 NS_FAILED(file->AppendNative("pref"_ns))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->AppendNative
("pref"_ns))), 0)))
)
1482 return NS_ERROR_FAILURE;
1483 file.forget(result);
1484 return NS_OK;
1485 }
1486
1487 return NS_ERROR_FAILURE;
1488}
1489
1490NS_IMETHODIMPnsresult
1491XPCShellDirProvider::GetFiles(const char* prop, nsISimpleEnumerator** result) {
1492 if (mGREDir && !strcmp(prop, "ChromeML")) {
1493 nsCOMArray<nsIFile> dirs;
1494
1495 nsCOMPtr<nsIFile> file;
1496 mGREDir->Clone(getter_AddRefs(file));
1497 file->AppendNative("chrome"_ns);
1498 dirs.AppendObject(file);
1499
1500 nsresult rv =
1501 NS_GetSpecialDirectory(NS_APP_CHROME_DIR"AChrom", getter_AddRefs(file));
1502 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1503 dirs.AppendObject(file);
1504 }
1505
1506 return NS_NewArrayEnumerator(result, dirs, NS_GET_IID(nsIFile)(nsIFile::COMTypeInfo<nsIFile, void>::kIID));
1507 } else if (!strcmp(prop, NS_APP_PREFS_DEFAULTS_DIR_LIST"PrefDL")) {
1508 nsCOMArray<nsIFile> dirs;
1509 nsCOMPtr<nsIFile> appDir;
1510 bool exists;
1511 if (mAppDir && NS_SUCCEEDED(mAppDir->Clone(getter_AddRefs(appDir)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mAppDir->Clone
(getter_AddRefs(appDir)))), 1)))
&&
1512 NS_SUCCEEDED(appDir->AppendNative("defaults"_ns))((bool)(__builtin_expect(!!(!NS_FAILED_impl(appDir->AppendNative
("defaults"_ns))), 1)))
&&
1513 NS_SUCCEEDED(appDir->AppendNative("preferences"_ns))((bool)(__builtin_expect(!!(!NS_FAILED_impl(appDir->AppendNative
("preferences"_ns))), 1)))
&&
1514 NS_SUCCEEDED(appDir->Exists(&exists))((bool)(__builtin_expect(!!(!NS_FAILED_impl(appDir->Exists
(&exists))), 1)))
&& exists) {
1515 dirs.AppendObject(appDir);
1516 return NS_NewArrayEnumerator(result, dirs, NS_GET_IID(nsIFile)(nsIFile::COMTypeInfo<nsIFile, void>::kIID));
1517 }
1518 return NS_ERROR_FAILURE;
1519 }
1520 return NS_ERROR_FAILURE;
1521}