From c16f92caa3eca9bce0048b48dc920fe55e781731 Mon Sep 17 00:00:00 2001
From: John Thacker <johnthacker@gmail.com>
Date: Sat, 21 Mar 2026 15:30:05 +0000
Subject: [PATCH] sbc codec: Fix heap buffer overflow and possible infinite
 loop

Check for a 0 or negative return value (error) from sbc_decode and
break out of the loop.

Decrement the remaining size for the input and output buffers to
prevent a heap buffer overflow

Thanks to Duc Anh Nguyen for the report and POC and proposed fix,
which I verified manually and tweaked, adding the infinite loop
check.

Fix #21103

AI-Assisted: probably (the report and POC looks AI-assisted)


(cherry picked from commit db67edfd7422454472ec9eec14781a1d46835872)

Co-authored-by: John Thacker <johnthacker@gmail.com>
---
 plugins/codecs/sbc/sbc.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

Index: wireshark-3.6.24/plugins/codecs/sbc/sbc.c
===================================================================
--- wireshark-3.6.24.orig/plugins/codecs/sbc/sbc.c
+++ wireshark-3.6.24/plugins/codecs/sbc/sbc.c
@@ -84,10 +84,10 @@ static size_t
 codec_sbc_decode(void *ctx, const void *input, size_t inputSizeBytes, void *output,
         size_t *outputSizeBytes)
 {
-    size_t         size_in = (size_t) inputSizeBytes;
+    size_t         size_in = inputSizeBytes;
     size_t         size_out = SBC_BUFFER;
     size_t         len;
-    size_t         framelen;
+    ssize_t        framelen;
     size_t         xframe_pos = 0;
     const guint8  *data_in  = (const guint8 *) input;
     guint8        *data_out = (guint8 *) output;
@@ -95,17 +95,35 @@ codec_sbc_decode(void *ctx, const void *
     guint8        *i_data;
     guint8         tmp;
 
+    /* XXX - This should presumably call sbc_parse on the input to set the
+     * various parameters the first time, then return the value from
+     * sbc_get_codesize() (uncompressed block size) as the necessary
+     * output size. See the opus codec. */
     if (!output || !outputSizeBytes) {
         return size_out;
     }
 
+    /* XXX - Why ask libsbc to provide Big Endian output and then always
+     * byte swap below? That seems wasteful on Little Endian and just wrong
+     * on Big Endian. sbc_init sets sbc->endian correctly depending on how
+     * the library was compiled. */
     sbc->endian = SBC_BE;
 
     *outputSizeBytes = 0;
     while (xframe_pos < inputSizeBytes) {
         framelen = sbc_decode(sbc, data_in, size_in, data_out, size_out, &len);
+        if (framelen <= 0) {
+            // Error
+            break;
+        }
         xframe_pos += framelen;
         data_in += framelen;
+        size_in -= framelen;
+        if (len > size_out) {
+            // Not enough room in output (multiple frames?)
+            break;
+        }
+        size_out -= len;
         *outputSizeBytes += len;
 
         for (i_data = data_out; i_data < data_out + len; i_data += 2) {
