# HG changeset patch # User Gabriele Svelto # Date 1539256502 0 # Node ID b791c9a47d33088319ad53b32d0756ec014dfdb7 # Parent 15c8e7919a34f8c87e46c410b30605b0cc6a82ce Bug 1390547 - Escape MozCrashReason when writing out a crash report r=ted Differential Revision: https://phabricator.services.mozilla.com/D7256 diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp --- a/toolkit/crashreporter/nsExceptionHandler.cpp +++ b/toolkit/crashreporter/nsExceptionHandler.cpp @@ -863,16 +863,52 @@ LaunchCrashReporterActivity(XP_CHAR* aPr Unused << HANDLE_EINTR(sys_waitpid(pid, &status, __WALL)); } return true; } #endif +void +WriteEscapedMozCrashReason(PlatformWriter& aWriter) +{ + const char *reason; + size_t len; + char *rust_panic_reason; + bool rust_panic = get_rust_panic_reason(&rust_panic_reason, &len); + + if (rust_panic) { + reason = rust_panic_reason; + } else if (gMozCrashReason != nullptr) { + reason = gMozCrashReason; + len = strlen(reason); + } else { + return; // No crash reason, bail out + } + + WriteString(aWriter, AnnotationToString(Annotation::MozCrashReason)); + WriteLiteral(aWriter, "="); + + // The crash reason might be non-null-terminated in the case of a rust panic, + // it has also not being escaped so escape it one character at a time and + // write out the resulting string. + for (size_t i = 0; i < len; i++) { + if (reason[i] == '\\') { + WriteLiteral(aWriter, "\\\\"); + } else if (reason[i] == '\n') { + WriteLiteral(aWriter, "\\n"); + } else { + aWriter.WriteBuffer(reason + i, 1); + } + } + + WriteLiteral(aWriter, "\n"); +} + static bool MinidumpCallback( #ifdef XP_LINUX const MinidumpDescriptor& descriptor, #else const XP_CHAR* dump_path, const XP_CHAR* minidump_id, #endif @@ -1058,28 +1094,18 @@ MinidumpCallback( if (apiData.Valid()) { DllBlocklist_WriteNotes(apiData.Handle()); DllBlocklist_WriteNotes(eventFile.Handle()); } #endif WriteGlobalMemoryStatus(&apiData, &eventFile); #endif // XP_WIN - char* rust_panic_reason; - size_t rust_panic_len; - if (get_rust_panic_reason(&rust_panic_reason, &rust_panic_len)) { - // rust_panic_reason is not null-terminated. - WriteAnnotation(apiData, Annotation::MozCrashReason, rust_panic_reason, - rust_panic_len); - WriteAnnotation(eventFile, Annotation::MozCrashReason, rust_panic_reason, - rust_panic_len); - } else if (gMozCrashReason) { - WriteAnnotation(apiData, Annotation::MozCrashReason, gMozCrashReason); - WriteAnnotation(eventFile, Annotation::MozCrashReason, gMozCrashReason); - } + WriteEscapedMozCrashReason(apiData); + WriteEscapedMozCrashReason(eventFile); if (oomAllocationSizeBuffer[0]) { WriteAnnotation(apiData, Annotation::OOMAllocationSize, oomAllocationSizeBuffer); WriteAnnotation(eventFile, Annotation::OOMAllocationSize, oomAllocationSizeBuffer); } @@ -1263,25 +1289,17 @@ PrepareChildExceptionTimeAnnotations(voi XP_STOA(gOOMAllocationSize, oomAllocationSizeBuffer, 10); } if (oomAllocationSizeBuffer[0]) { WriteAnnotation(apiData, Annotation::OOMAllocationSize, oomAllocationSizeBuffer); } - char* rust_panic_reason; - size_t rust_panic_len; - if (get_rust_panic_reason(&rust_panic_reason, &rust_panic_len)) { - // rust_panic_reason is not null-terminated. - WriteAnnotation(apiData, Annotation::MozCrashReason, rust_panic_reason, - rust_panic_len); - } else if (gMozCrashReason) { - WriteAnnotation(apiData, Annotation::MozCrashReason, gMozCrashReason); - } + WriteEscapedMozCrashReason(apiData); std::function getThreadAnnotationCB = [&] (const char * aValue) -> void { if (aValue) { WriteAnnotation(apiData, Annotation::ThreadIdNameMapping, aValue); } }; GetFlatThreadAnnotation(getThreadAnnotationCB, true); @@ -3000,17 +3018,17 @@ static bool IsDataEscaped(char* aData) { if (strchr(aData, '\n')) { // There should not be any newlines return false; } char* pos = aData; while ((pos = strchr(pos, '\\'))) { - if (*(pos + 1) != '\\') { + if (*(pos + 1) != '\\' && *(pos + 1) != 'n') { return false; } // Add 2 to account for the second pos pos += 2; } return true; } diff --git a/toolkit/crashreporter/test/unit/test_crash_rust_panic.js b/toolkit/crashreporter/test/unit/test_crash_rust_panic_multiline.js copy from toolkit/crashreporter/test/unit/test_crash_rust_panic.js copy to toolkit/crashreporter/test/unit/test_crash_rust_panic_multiline.js --- a/toolkit/crashreporter/test/unit/test_crash_rust_panic.js +++ b/toolkit/crashreporter/test/unit/test_crash_rust_panic_multiline.js @@ -1,11 +1,11 @@ function run_test() { // Try crashing with a Rust panic do_crash(function() { - Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2).rustPanic("OH NO"); + Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2).rustPanic("OH NO\nOH NOES!"); }, function(mdump, extra) { - Assert.equal(extra.MozCrashReason, "OH NO"); + Assert.equal(extra.MozCrashReason, "OH NO\nOH NOES!"); }, // process will exit with a zero exit status true); } diff --git a/toolkit/crashreporter/test/unit/xpcshell.ini b/toolkit/crashreporter/test/unit/xpcshell.ini --- a/toolkit/crashreporter/test/unit/xpcshell.ini +++ b/toolkit/crashreporter/test/unit/xpcshell.ini @@ -3,16 +3,17 @@ head = head_crashreporter.js skip-if = toolkit == 'android' support-files = crasher_subprocess_head.js crasher_subprocess_tail.js [test_crash_moz_crash.js] [test_crash_purevirtual.js] [test_crash_rust_panic.js] +[test_crash_rust_panic_multiline.js] [test_crash_after_js_oom_reported.js] [test_crash_after_js_oom_recovered.js] [test_crash_after_js_oom_reported_2.js] [test_crash_after_js_large_allocation_failure.js] [test_crash_after_js_large_allocation_failure_reporting.js] [test_crash_oom.js] [test_oom_annotation_windows.js] skip-if = os != 'win' diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic.js b/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic_multiline.js copy from toolkit/crashreporter/test/unit_ipc/test_content_rust_panic.js copy to toolkit/crashreporter/test/unit_ipc/test_content_rust_panic_multiline.js --- a/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic.js +++ b/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic_multiline.js @@ -7,15 +7,15 @@ function run_test() { return; } // Try crashing with a Rust panic do_triggered_content_crash( function() { Cc["@mozilla.org/xpcom/debug;1"] .getService(Ci.nsIDebug2) - .rustPanic("OH NO"); + .rustPanic("OH NO\nOH NOES!"); }, function(mdump, extra) { - Assert.equal(extra.MozCrashReason, "OH NO"); + Assert.equal(extra.MozCrashReason, "OH NO\nOH NOES!"); } ); } diff --git a/toolkit/crashreporter/test/unit_ipc/xpcshell.ini b/toolkit/crashreporter/test/unit_ipc/xpcshell.ini --- a/toolkit/crashreporter/test/unit_ipc/xpcshell.ini +++ b/toolkit/crashreporter/test/unit_ipc/xpcshell.ini @@ -7,9 +7,10 @@ support-files = !/toolkit/crashreporter/test/unit/head_crashreporter.js [test_content_annotation.js] [test_content_exception_time_annotation.js] [test_content_oom_annotation_windows.js] skip-if = os != 'win' [test_content_memory_list.js] skip-if = os != 'win' -[test_content_rust_panic.js] \ No newline at end of file +[test_content_rust_panic.js] +[test_content_rust_panic_multiline.js]