Bug 726502 - nsDeviceMotion::DeviceMotionChanged may index out of bounds mWindowListeners array. r=smaug
authorDoug Turner <dougt@dougt.org>
Fri, 09 Mar 2012 08:41:25 -0800
changeset 88692 6737b6762eb8cc365fb7a3effa586ce66b7e34e4
parent 88691 b9357da14ab8c2abd0d378f8539ddea88d1ad7f7
child 88693 e372bfbf40c5afb86d9da513f166cc928302e656
push id22217
push userdougt@mozilla.com
push dateSat, 10 Mar 2012 19:12:53 +0000
treeherdermozilla-central@6737b6762eb8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs726502
milestone13.0a1
first release with
nightly linux32
6737b6762eb8 / 13.0a1 / 20120311031030 / files
nightly linux64
6737b6762eb8 / 13.0a1 / 20120311031030 / files
nightly mac
6737b6762eb8 / 13.0a1 / 20120311031030 / files
nightly win32
6737b6762eb8 / 13.0a1 / 20120311031030 / files
nightly win64
6737b6762eb8 / 13.0a1 / 20120311031030 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 726502 - nsDeviceMotion::DeviceMotionChanged may index out of bounds mWindowListeners array. r=smaug
dom/system/nsDeviceMotion.cpp
--- a/dom/system/nsDeviceMotion.cpp
+++ b/dom/system/nsDeviceMotion.cpp
@@ -194,22 +194,25 @@ NS_IMETHODIMP nsDeviceMotion::RemoveList
 
   mListeners.RemoveObject(aListener);
   StartDisconnectTimer();
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDeviceMotion::AddWindowListener(nsIDOMWindow *aWindow)
 {
+  if (mWindowListeners.IndexOf(aWindow) != NoIndex)
+      return NS_OK;
+
   if (mStarted == false) {
     mStarted = true;
     Startup();
   }
-  if (mWindowListeners.IndexOf(aWindow) == NoIndex)
-    mWindowListeners.AppendElement(aWindow);
+
+  mWindowListeners.AppendElement(aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDeviceMotion::RemoveWindowListener(nsIDOMWindow *aWindow)
 {
   if (mWindowListeners.IndexOf(aWindow) == NoIndex)
     return NS_OK;
 
@@ -219,38 +222,44 @@ NS_IMETHODIMP nsDeviceMotion::RemoveWind
 }
 
 NS_IMETHODIMP
 nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z)
 {
   if (!mEnabled)
     return NS_ERROR_NOT_INITIALIZED;
 
-  for (PRUint32 i = mListeners.Count(); i > 0 ; ) {
+  nsCOMArray<nsIDeviceMotionListener> listeners = mListeners;
+  for (PRUint32 i = listeners.Count(); i > 0 ; ) {
     --i;
     nsRefPtr<nsDeviceMotionData> a = new nsDeviceMotionData(type, x, y, z);
-    mListeners[i]->OnMotionChange(a);
+    listeners[i]->OnMotionChange(a);
   }
 
-  for (PRUint32 i = mWindowListeners.Length(); i > 0 ; ) {
+  nsCOMArray<nsIDOMWindow> windowListeners;
+  for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) {
+    windowListeners.AppendObject(mWindowListeners[i]);
+  }
+
+  for (PRUint32 i = windowListeners.Count(); i > 0 ; ) {
     --i;
 
     // check to see if this window is in the background.  if
     // it is, don't send any device motion to it.
-    nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(mWindowListeners[i]);
+    nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(windowListeners[i]);
     if (!pwindow ||
         !pwindow->GetOuterWindow() ||
         pwindow->GetOuterWindow()->IsBackground())
       continue;
 
     nsCOMPtr<nsIDOMDocument> domdoc;
-    mWindowListeners[i]->GetDocument(getter_AddRefs(domdoc));
+    windowListeners[i]->GetDocument(getter_AddRefs(domdoc));
 
     if (domdoc) {
-      nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mWindowListeners[i]);
+      nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(windowListeners[i]);
       if (type == nsIDeviceMotionData::TYPE_ACCELERATION)
         FireDOMMotionEvent(domdoc, target, x, y, z);
       else if (type == nsIDeviceMotionData::TYPE_ORIENTATION)
         FireDOMOrientationEvent(domdoc, target, x, y, z);
     }
   }
   return NS_OK;
 }