
Aviso y reproductor de AddressSanitizer para un desbordamiento de búfer en el heap de SQLAR de SQLite desencadenado por un valor SZ manipulado que causa una asignación truncada y una escritura fuera de los límites en zlib.
CVE-2026-39113 es un desbordamiento de búfer en el montón en la extensión SQLAR opcional de SQLite. En una aplicación que haya cargado la extensión, un atacante que pueda invocar sqlar_uncompress() con un blob comprimido controlado y un tamaño controlado puede hacer que zlib escriba más allá de una asignación en el montón en un sistema LP64. Se trata de un fallo de límites de seguridad de memoria dentro del proceso anfitrión; no es un problema de análisis de archivos de base de datos de SQLite, ni una omisión de autenticación, ni una falla accesible en todos los despliegues predeterminados de SQLite.
El comportamiento vulnerable se introdujo el 2026-03-11 mediante el commit de Git 169f68e (check-in de Fossil 8bdc0d485e3ad0c7...) y se corrigió el 2026-04-01 mediante el commit de Git 34e139d (check-in de Fossil 6194f3b5314ef98b...). El alcance afectado comprende las instantáneas de código fuente y las compilaciones personalizadas desde 169f68e hasta el padre de 34e139d. No se verificó que ninguna versión oficial de SQLite fuera vulnerable: SQLite 3.52.0 es anterior a la introducción, y SQLite 3.53.0 contiene tanto el cambio que introdujo el fallo como la corrección. Por lo tanto, SQLite 3.53.0 es la primera versión oficial que contiene el código corregido, no una versión afectada.
Revisé la revisión vulnerable exacta, los cambios que introdujeron y corrigieron el fallo, y las instantáneas de las versiones 3.52.0 y 3.53.0. También inspeccioné la salida conservada de una ejecución autorizada en un entorno desechable WSL2 Ubuntu 24.04. AddressSanitizer detectó un desbordamiento de búfer en el montón seguido de la terminación del proceso, lo que confirma la corrupción nativa del montón y la denegación de servicio. No se demostró la ejecución de código.
SQLAR es un formato de archivo de SQLite. La extensión opcional en ext/misc/sqlar.c registra sqlar_compress() y sqlar_uncompress() como funciones SQL. No forma parte de todas las aplicaciones que usan SQLite; la ruta vulnerable requiere que la extensión esté presente y cargada.
Para este informe, Mallory controla el blob y los argumentos SZ suministrados a:
SELECT sqlar_uncompress(?1, ?2);
El entorno probado tenía un int de 32 bits, un sqlite3_int64 de 64 bits y un uLongf de zlib de 64 bits. La función debería asignar al menos tanta memoria como zlib tiene permitido escribir. En su lugar, el código fuente vulnerable convierte el tamaño de 64 bits al tipo de parámetro de 32 bits de sqlite3_malloc() mientras conserva el valor completo para uncompress().
La instantánea de código fuente vulnerable imprimió Configuring SQLite version 3.53.0 durante la configuración. Esa cadena de versión de desarrollo no debe confundirse con la versión oficial SQLite 3.53.0, con fecha 2026-04-09, cuyo código fuente contiene la corrección.
En la revisión evaluada, sqlarUncompressFunc() en ext/misc/sqlar.c lee el tamaño controlado por el atacante como un entero de 64 bits:
sqlite3_int64 sz;
sz = sqlite3_value_int64(argv[1]);
Si sz es positivo y difiere de la longitud del blob de entrada, el mismo valor se usa de dos maneras incompatibles:
uLongf szf = sz;
const Bytef *pData = sqlite3_value_blob(argv[0]);
Bytef *pOut = sqlite3_malloc(sz);
if( pOut==0 ){
sqlite3_result_error_nomem(context);
}else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
sqlite3_result_error(context, "error in uncompress()", -1);
}
En esta revisión, SQLite declara sqlite3_malloc(int). En la compilación LP64 probada, el valor 4294967328 (0x100000020) de la PoC se convirtió en 32 al pasarse a esa API, mientras que szf conservó el valor completo de 64 bits. Por lo tanto, SQLite realizó una asignación pequeña, pero a zlib se le indicó que el búfer de salida podía contener más de 4 GiB. Al descomprimir un blob de 42 bytes que representaba 4096 bytes de datos se cruzó el límite de la asignación.
El desajuste entró en el proyecto cuando el cambio del 2026-03-11 reemplazó sqlite3_value_int() por sqlite3_value_int64() sin cambiar la API de asignación. La revisión del código fuente de SQLite 3.52.0 muestra la lectura anterior de 32 bits, por lo que el desajuste entre el ancho completo y la asignación corta no estaba presente allí. La corrección del 2026-04-01 cambió la asignación a sqlite3_malloc64(sz). La revisión del código fuente de la etiqueta oficial 3.53.0 confirma esa llamada corregida.
La primitiva demostrada es una escritura fuera de los límites en el montón dentro del proceso que aloja SQLite. La ejecución conservada muestra a AddressSanitizer detectando la primera escritura inválida de un byte inmediatamente después de una región de montón de 40 bytes asignada mediante sqlite3_malloc(), seguida de un aborto. Esto respalda directamente el bloqueo del proceso y la denegación de servicio.
La explotación requiere todo lo siguiente:
sqlar_uncompress() con un blob y un valor SZ controlados;int sea de 32 bits mientras que sqlite3_int64 y uLongf de zlib sean de 64 bits; yLa PoC controla los bytes descomprimidos, lo cual es relevante para la gravedad de la corrupción nativa del montón. Sin embargo, convertir esta primitiva en ejecución de código dependería de la distribución del asignador, del estado del proceso circundante, de las mitigaciones y de una vía adecuada a nivel de aplicación. No se probó ni demostró ninguna cadena de ese tipo, por lo que este informe no afirma la ejecución de código.
La ejecución conservada no incluyó un control negativo en tiempo de ejecución contra la revisión corregida. Dos controles a nivel de código fuente acotan la explicación: SQLite 3.52.0 lee el tamaño con la API de 32 bits, y el código fuente oficial de 3.53.0 asigna con sqlite3_malloc64(). Estas comprobaciones respaldan la identificación de la introducción y la corrección, pero no se presentan como pruebas ejecutadas contra el objetivo corregido. Se desconoce la prevalencia de aplicaciones que cargan esta extensión opcional.
El repositorio incluye:
poc/verify_sqlar_poc.c, que crea una carga útil de 4096 bytes, la comprime, carga sqlar.so y fija SZ = 4294967328;poc/reproduce.sh, que clona revisiones fijadas de SQLite y zlib, las compila con AddressSanitizer, compila la extensión y el banco de pruebas, y ejecuta el disparador; yevidence/asan-summary.txt, un resumen normalizado de rutas de la ejecución autorizada observada.Ejecute el reproductor únicamente en un entorno Linux o WSL desechable. Intencionalmente provoca corrupción de memoria y un aborto de AddressSanitizer. El script requiere git, make, un compilador de C, herramientas de compilación estándar y acceso a la red:
chmod +x poc/reproduce.sh
./poc/reproduce.sh
El reproductor se ejecutó nuevamente el 2026-08-21 en Ubuntu 24.04 bajo WSL2 y produjo el mismo hallazgo de AddressSanitizer. Su salida relevante fue:
env: sizeof(int)=4 sizeof(sqlite3_int64)=8 sizeof(uLongf)=8
payload: plain=4096 compressed=42 evil_sz=4294967328 low32=32
ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 1
#0 inflate_fast zlib/inffast.c:252
#4 uncompress zlib/uncompr.c:100
#5 sqlarUncompressFunc sqlite/ext/misc/sqlar.c:97
The write occurred immediately after a 40-byte heap region.
SUMMARY: AddressSanitizer: heap-buffer-overflow in inflate_fast
ABORTING
PoC exit status: 1
Esta salida muestra los anchos de tipo incompatibles y el tamaño manipulado, la escritura de zlib, la llamada desde sqlarUncompressFunc() y la violación del límite de la asignación. El script de reproducción elimina su directorio temporal de compilación al salir a menos que se establezca KEEP_BUILD=1.
El proyecto upstream corrigió la asignación vulnerable en el commit 34e139d:
- Bytef *pOut = sqlite3_malloc(sz);
+ Bytef *pOut = sqlite3_malloc64(sz);
Esto mantiene el ancho de la asignación coherente con el valor positivo sz de 64 bits retenido en uLongf szf y pasado a zlib. El código corregido está presente en la versión oficial SQLite 3.53.0. Los usuarios de instantáneas de código fuente o compilaciones personalizadas que contengan el intervalo vulnerable deben actualizar a 34e139d o posterior. Las aplicaciones que no requieran SQLAR deben evitar cargar la extensión, y las aplicaciones que sí la usen deben impedir que llamadores no confiables suministren argumentos arbitrarios a sqlar_uncompress().
Una prueba de regresión específica debería ejercitar la función SQL con un blob comprimido válido y un valor SZ superior a INT_MAX cuyos 32 bits inferiores sean pequeños. Debería verificar que la compilación corregida no realiza una asignación truncada y debería conservar los casos de descompresión exitosa ordinaria y de errores de entrada inválida como controles.
CVE-2026-39113 afecta únicamente a las instantáneas de código fuente y a las compilaciones personalizadas de SQLite desde 169f68e hasta el padre de 34e139d cuando la extensión SQLAR opcional está cargada y las llamadas controladas por el atacante llegan a sqlar_uncompress() en una compilación LP64. Un tamaño de 64 bits se redujo mediante sqlite3_malloc(int) mientras que zlib conservó el valor completo, lo que produjo un desbordamiento de búfer en el montón confirmado por AddressSanitizer y un aborto del proceso. No se verificó que ninguna versión oficial de SQLite fuera vulnerable, y no se demostró la ejecución de código. El cambio upstream a sqlite3_malloc64(sz) está presente en la versión oficial SQLite 3.53.0 y elimina el desajuste del ancho de asignación.