From 52afb20701c7f67cf1aa27046378835be1af2f1c Mon Sep 17 00:00:00 2001
From: AliceLR <[EMAIL REDACTED]>
Date: Fri, 5 Jun 2026 06:33:32 +0300
Subject: [PATCH] stb_vorbis: Increase setup_malloc() size parameter to uint64
Expands the setup_malloc size parameter, and various calculations
that the Vorbis spec allows to exceed 32 bits, to uint64. setup_malloc
and setup_temp_malloc still reject allocations that exceed INT_MAX,
as the underlying memory fields are still 32 bit signed integers.
Reference issue: https://github.com/libxmp/libxmp/issues/996
Reference issue: https://github.com/nothings/stb/issues/1947
Reference issue: https://github.com/nothings/stb/issues/1933
Also see : https://github.com/nothings/stb/issues/1168#issuecomment-1082625780
Mainstream P/R : https://github.com/nothings/stb/pull/1960
---
src/decoder_stb_vorbis.c | 1 +
src/stb_vorbis/stb_vorbis.h | 48 ++++++++++++++++++++++++++-----------
2 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/src/decoder_stb_vorbis.c b/src/decoder_stb_vorbis.c
index eea7dc09f..3a15e734f 100644
--- a/src/decoder_stb_vorbis.c
+++ b/src/decoder_stb_vorbis.c
@@ -70,6 +70,7 @@ typedef Uint16 uint16;
typedef Sint16 int16;
typedef Uint32 uint32;
typedef Sint32 int32;
+typedef Uint64 uint64;
#include "stb_vorbis/stb_vorbis.h"
diff --git a/src/stb_vorbis/stb_vorbis.h b/src/stb_vorbis/stb_vorbis.h
index fca54cdb1..3ab0e7edd 100644
--- a/src/stb_vorbis/stb_vorbis.h
+++ b/src/stb_vorbis/stb_vorbis.h
@@ -652,13 +652,28 @@ enum STBVorbisError
#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG)
#ifndef STB_VORBIS_STDINT_DEFINED /* for using SDL types */
+#if defined B_BEOS_VERSION
+ #include <SupportDefs.h>
+#elif defined __amigaos4__
+ #include <exec/types.h>
+#elif defined _arch_dreamcast /* KallistiOS */
+ #include <arch/types.h>
+#else
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint32;
typedef signed int int32;
-#endif
+#ifdef _MSC_VER /* MSVC6 has no long long */
+typedef unsigned __int64 uint64;
+#elif defined(_LP64) || defined(__LP64__)
+typedef unsigned long uint64;
+#else
+typedef unsigned long long uint64;
+#endif /* uint64 */
+#endif /* !BeOS && !AmigaOS4 && !KallistiOS */
+#endif /* !STB_VORBIS_STDINT_DEFINED */
#ifdef __has_feature
#if __has_feature(undefined_behavior_sanitizer)
@@ -710,7 +725,7 @@ typedef struct
uint8 lookup_type;
uint8 sequence_p;
uint8 sparse;
- uint32 lookup_values;
+ uint64 lookup_values; /* entries (24 bits) * dimensions (16 bits) */
codetype *multiplicands;
uint32 *codewords;
#ifdef STB_VORBIS_FAST_HUFFMAN_SHORT
@@ -996,14 +1011,15 @@ static void *make_block_array(void *mem, int count, int size)
}
}
-static void *setup_malloc(vorb *f, int sz)
+static void *setup_malloc(vorb *f, uint64 siz)
{
- if (sz <= 0 || INT_MAX - 7 < sz) return NULL;
+ int sz = (int)siz;
+ if (sz <= 0 || (uint64)INT_MAX - 7 < siz) return NULL;
sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs.
f->setup_memory_required += sz;
if (f->alloc.alloc_buffer) {
void *p = (char *) f->alloc.alloc_buffer + f->setup_offset;
- if (f->setup_offset + sz > f->temp_offset) return NULL;
+ if (f->temp_offset < sz || f->temp_offset - sz < f->setup_offset) return NULL;
f->setup_offset += sz;
return p;
}
@@ -1016,19 +1032,20 @@ static void setup_free(vorb *f, void *p)
free(p);
}
-static void *setup_temp_malloc(vorb *f, int sz)
+static void *setup_temp_malloc(vorb *f, uint64 siz)
{
- if (sz <= 0 || INT_MAX - 7 < sz) return NULL;
+ int sz = (int)siz;
+ if (sz <= 0 || (uint64)INT_MAX - 7 < siz) return NULL;
sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs.
if (f->alloc.alloc_buffer) {
- if (f->temp_offset - sz < f->setup_offset) return NULL;
+ if (f->temp_offset < sz || f->temp_offset - sz < f->setup_offset) return NULL;
f->temp_offset -= sz;
return (char *) f->alloc.alloc_buffer + f->temp_offset;
}
return malloc(sz);
}
-static void setup_temp_free(vorb *f, void **_p, int sz)
+static void setup_temp_free(vorb *f, void **_p, uint64 sz)
{
void *p = *_p;
*_p = NULL;
@@ -4014,9 +4031,12 @@ static int start_decoder(vorb *f)
if (values < 0) return error(f, VORBIS_invalid_setup);
c->lookup_values = (uint32) values;
} else {
- /* unsigned multiply to suppress (legitimate) warning.
- * https://github.com/nothings/stb/issues/1168 */
- c->lookup_values = (unsigned)c->entries * (unsigned)c->dimensions;
+ /* changed to unsigned multiply for:
+ * https://github.com/nothings/stb/issues/1168
+ * https://github.com/nothings/stb/issues/1947
+ * https://github.com/nothings/stb/issues/1933
+ * https://github.com/libxmp/libxmp/issues/996 */
+ c->lookup_values = (uint64)c->entries * (uint64)c->dimensions;
}
if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup);
mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values);
@@ -4035,9 +4055,9 @@ static int start_decoder(vorb *f)
// pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop
if (sparse) {
if (c->sorted_entries == 0) goto skip;
- c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions);
+ c->multiplicands = (codetype *) setup_malloc(f, (uint64) sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions);
} else
- c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions);
+ c->multiplicands = (codetype *) setup_malloc(f, (uint64) sizeof(c->multiplicands[0]) * c->entries * c->dimensions);
if (c->multiplicands == NULL) return error(f, VORBIS_outofmem);
len = sparse ? c->sorted_entries : c->entries;
for (j=0; j < len; ++j) {