Resumen
El fallo está en el motor de almacenamiento CONNECT de MariaDB, concretamente en la función TYPVAL<double>::SetValue_char() del fichero storage/connect/value.cpp. Esta función convierte a número el texto de un campo DOUBLE y, para ello, lo copia antes a un búfer local de 64 bytes en la pila.
La copia en sí está bien acotada: nunca pasa de 31 bytes. El problema es la línea siguiente, la que coloca el terminador de cadena. En lugar de usar la longitud realmente copiada, usa n, que es el ancho declarado del campo en SQL:
bool TYPVAL<double>::SetValue_char(const char *p, int n){
if (p && n > 0) {
char buf[64];
for (; n > 0 && *p == ' '; p++)
n--;
memcpy(buf, p, MY_MIN(n, 31));
buf[n] = '\0';
Como SQL admite anchos de hasta 255, una columna DOUBLE(255,30) hace que se ejecute buf[255] = '\0' sobre un búfer de 64 posiciones: un byte 0x00 escrito hasta 191 bytes más allá del final del búfer, según el investigador. El caso tiene asignado el CVE-2026-107815.
Cómo llega el ancho declarado hasta ahí
El investigador siguió el valor desde la definición de la tabla hasta la línea vulnerable, y en ningún punto se recorta:
- La capa SQL acepta
DOUBLE(255,30)y fijafield_lengtha 255 (sql/field.cc). - CONNECT copia ese ancho tal cual (
ha_connect.cc). - El ancho pasa a ser el campo
Longde la columna, también sin cambios (reldef.cpp,colblk.cpp,tabdos.cpp). DOSCOL::ReadColumn()asignafield = Longy lo pasa directamente al parser del valor (tabdos.cpp):
case TYPE_DOUBLE:
if (!(err = Value->SetValue_char(p, field))) {
Pasos de reproducción
El reporte no incluye el SQL ni el fichero DOS del PoC en el propio texto: están en dos gists que aportó el investigador.
- Compilar MariaDB con AddressSanitizer (ASAN). Dockerfile del investigador: https://gist.github.com/dldLambda/58ad85abfb9bc65d661a69faba7523e0
- Ejecutar su script
PoC.sh, que lleva en sus parámetros de arranque tanto el disparador como la configuración: https://gist.github.com/dldLambda/f4bc2a9c343bb28404989dba2628d2bf - Lo que dispara el fallo es leer de vuelta una columna
DOUBLE(M,D)con un ancho grande (por ejemploDOUBLE(255,30)) de una tabla CONNECT conTABLE_TYPE='DOS'. - Con ASAN, el servidor informa de un
stack-buffer-overflowde escritura de 1 byte en la líneabuf[n] = '\0'deTYPVAL<double>::SetValue_char. Sin ASAN, el servidor se cae.
Impacto
Un atacante que pueda provocar esa lectura consigue tumbar el servidor MariaDB, es decir, una denegación de servicio. El reporte solo describe este impacto (caída del servidor); no plantea ejecución de código ni detalla qué privilegios hacen falta para crear la tabla CONNECT.
Qué aprender de este caso
- Cuando una función acota la copia con
MIN(n, límite), revisa todas las líneas siguientes que usann: aquí elmemcpyestaba bien limitado, pero el terminadorbuf[n] = '\0'usaba la longitud sin recortar. Lo correcto es guardar la longitud acotada en una variable y usar solo esa. - En código que convierte texto a número con un búfer fijo en pila, busca de dónde sale la longitud: si viene de metadatos que controla el usuario (como el ancho declarado de una columna SQL), trátala como entrada no confiable aunque haya atravesado varias capas internas.
- Los motores de almacenamiento que leen ficheros externos (como CONNECT con tablas DOS) son buen objetivo para fuzzing: combinar anchos de columna extremos, que la capa SQL acepta, con compilación bajo ASAN destapa escrituras de un solo byte que sin sanitizador pasarían desapercibidas o solo causarían caídas difíciles de diagnosticar.