High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionIncorrect boundary conditions in the Audio/Video: Playback component
ComponentDOM
Bug ClassLogic Error
Tracker2047802
Fix commita336a4e2973a (firefox) +34/-14
CISA KEVNot listed
CreditedSteven Julian
Disclosed2026-07-21

Changed Functions

FunctionChangeNotes
if
dom/media/platforms/android/AndroidDataEncoder.cpp
modified
if
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SampleBuffer.java
modified

Files Changed

  • dom/media/platforms/android/AndroidDataEncoder.cpp
  • dom/media/platforms/android/RemoteDataDecoder.cpp
  • mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SampleBuffer.java
diff --git a/dom/media/platforms/android/AndroidDataEncoder.cpp b/dom/media/platforms/android/AndroidDataEncoder.cpp
index 73d9e910b1e..01d98d729a6 100644
--- a/dom/media/platforms/android/AndroidDataEncoder.cpp
+++ b/dom/media/platforms/android/AndroidDataEncoder.cpp
@@ -276,8 +276,8 @@ static RefPtr<MediaByteBuffer> ExtractCodecConfig(
   auto config = MakeRefPtr<MediaByteBuffer>(aSize);
   config->SetLength(aSize);
   NS_ENSURE_SUCCESS(
-      aBuffer->NativeCopy(reinterpret_cast<jlong>(config->Elements()), aOffset,
-                          aSize),
+      aBuffer->NativeCopy(reinterpret_cast<jlong>(config->Elements()),
+                          config->Length(), aOffset, aSize),
       nullptr);
   if (!aAsAVCC) {
     return config;
@@ -385,7 +385,7 @@ RefPtr<MediaRawData> AndroidDataEncoder::GetOutputData(
   }
 
   NS_ENSURE_SUCCESS(aBuffer->NativeCopy(reinterpret_cast<jlong>(writer->Data()),
-                                        aOffset, aSize),
+                                        writer->Size(), aOffset, aSize),
                     nullptr);
   output->mKeyframe = aIsKeyFrame;
 
@@ -421,7 +421,7 @@ RefPtr<MediaRawData> AndroidDataEncoder::GetOutputDataH264(
 
   NS_ENSURE_SUCCESS(
       aBuffer->NativeCopy(reinterpret_cast<jlong>(writer->Data() + prependSize),
-                          aOffset, aSize),
+                          writer->Size() - prependSize, aOffset, aSize),
       nullptr);
 
   if (asAVCC && !AnnexB::ConvertSampleToAVCC(output, avccHeader)) {
diff --git a/dom/media/platforms/android/RemoteDataDecoder.cpp b/dom/media/platforms/android/RemoteDataDecoder.cpp
index 01d57d39aae..9e0a1453558 100644
--- a/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -842,8 +842,9 @@ class RemoteAudioDecoder final : public RemoteDataDecoder {
         LOG("OOM while allocating temporary output buffer");
         return;
       }
-      nsresult rv = aBuffer->NativeCopy(reinterpret_cast<jlong>(audio.get()),
-                                        offset, size);
+      nsresult rv =
+          aBuffer->NativeCopy(reinterpret_cast<jlong>(audio.get()),
+                              audio.Length() * sampleSize, offset, size);
       if (NS_FAILED(rv)) {
         LOG("Fail to copy audio buffer");
         Error(MediaResult(rv, __func__));
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SampleBuffer.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SampleBuffer.java
index 62a9c38a559..e9d7cb60031 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SampleBuffer.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SampleBuffer.java
@@ -50,11 +50,27 @@ public final class SampleBuffer implements Parcelable {
     return mSharedMem != null ? mSharedMem.getSize() : 0;
   }
 
+  private void checkBounds(
+      final int offset, final int size, final int inCapacity, final int outCapacity)
+      throws IOException {
+    if (mSharedMem == null || !mSharedMem.isValid()) {
+      throw new IOException("Invalid state.");
+    }
+    if (offset < 0 || size < 0) {
+      throw new IOException("Illegal source offset/size");
+    }
+    final long inEnd = (long) offset + size;
+    if (inEnd > inCapacity || size > outCapacity) {
+      throw new IOException("Out-of-bound: buffer too small.");
+    }
+  }
+
   public void readFromByteBuffer(final ByteBuffer src, final int offset, final int size)
       throws IOException {
     if (!src.isDirect()) {
       throw new IOException("SharedMemBuffer only support reading from direct byte buffer.");
     }
+    checkBounds(offset, size, src.capacity(), capacity());
     try {
       nativeReadFromDirectBuffer(src, mSharedMem.getPointer(), offset, size);
       mSharedMem.flush();
@@ -72,6 +88,7 @@ public final class SampleBuffer implements Parcelable {
     if (!dest.isDirect()) {
       throw new IOException("SharedMemBuffer only support writing to direct byte buffer.");
     }
+    checkBounds(offset, size, capacity(), dest.capacity());
     try {
       nativeWriteToDirectBuffer(mSharedMem.getPointer(), dest, offset, size);
     } catch (final NullPointerException e) {
@@ -83,16 +100,18 @@ public final class SampleBuffer implements Parcelable {
       long src, ByteBuffer dest, int offset, int size);
 
   @WrapForJNI(exceptionMode = "nsresult")
-  public void nativeCopy(final long dest, final int offset, final int size) throws IOException {
-    if (mSharedMem == null || !mSharedMem.isValid()) {
-      throw new IOException("Invalid state.");
-    }
-    if (offset + size > mSharedMem.getSize()) {
-      throw new IOException("Out-of-bound: buffer too small.");
+  public void nativeCopy(final long dest, final int destCapacity, final int offset, final int size)
+      throws IOException {
+    if (dest == 0) {
+      throw new IOException("Null destination pointer.");
     }
+    checkBounds(offset, size, capacity(), destCapacity);
     try {
-      final long src = mSharedMem.getPointer() + offset;
-      nativeMemcpy(dest, src, size);
+      final long src = mSharedMem.getPointer();
+      if (src == 0) {
+        throw new IOException("Shared memory not mapped.");
+      }
+      nativeMemcpy(dest, src + offset, size);
     } catch (final NullPointerException e) {
       throw new IOException(e);
     }
Loading diff…