
Clickbait. La CVE es basura de IA.
perdón por el nombre clickbait del repo, pero este CVE es basura completa y absoluta alucinada por un LLM; honestamente, es triste ver que un CNA acepte esto con lo inconsistentes que son las afirmaciones 💔
CVE-2026-51302 no es real 😱
El SQL publicado no reproduce un use-after-free en ninguna versión de SQLite 3.41 bajo AddressSanitizer. Más importante aún, la causa raíz declarada es totalmente incompatible con el código fuente afectado:
exprComputeOperands() no existe en SQLite 3.41.0, 3.41.1 ni 3.41.2;regFree1 es un identificador entero de registro de la máquina virtual, no un puntero a almacenamiento del heap;sqlite3ReleaseTempReg() deja un registro disponible para su reutilización y no deja un puntero C colgante en regFree1;exprComputeOperands(), los operandos se calculan antes de liberar los registros temporales, al contrario de la secuencia indicada en el aviso; yexprComputeOperands().Este registro CVE debería rechazarse y voy a plantear una disputa CNA ante MITRE 😉
El aviso identifica la versión afectada como "SQLite 3.41" y proporciona esta consulta:
SELECT CASE WHEN (1+3) THEN (5*8) ELSE (2/0) END FROM test;
Afirma que:
sqlite3ReleaseTempReg() libera memoria del heap asociada a regFree1;regFree1 permanece como una referencia colgante;exprComputeOperands() accede posteriormente a la memoria liberada; yLa amalgamación de SQLite 3.41.0 define la función de la siguiente manera:
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
if( iReg ){
sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0, 0);
if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
pParse->aTempReg[pParse->nTempReg++] = iReg;
}
}
}
La función recibe iReg como un int. Registra ese entero en pParse->aTempReg para que el número de registro pueda asignarse de nuevo:
SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
if( pParse->nTempReg==0 ){
return ++pParse->nMem;
}
return pParse->aTempReg[--pParse->nTempReg];
}
Esto es gestión del ciclo de vida de los registros durante la generación de programas VDBE. El aviso describe regFree1 como si fuera un puntero superviviente a almacenamiento del heap liberado. No lo es:
int regFree1 = 0, regFree2 = 0;
int r1, r2;
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1);
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2);
codeCompare(pParse, pL, pR, opx, r1, r2, addrDone, p5, isCommuted);
sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ReleaseTempReg(pParse, regFree2);
La comparación generada consume los identificadores de registro antes de que se liberen para su reutilización.
Una búsqueda con blame en el espejo de Git reveló que exprComputeOperands() fue introducida por:
e24f20a4f5a6d26cdaece58eff77619a4ee757b9
2025-06-30T10:30:47Z
Factor out the code that tries to avoid evaluating subquery operands if the other operand is NULL into a subroutine, so that it can be more easily reused by other parts of the code generator.
La función está ausente de las tres amalgamaciones oficiales de SQLite 3.41. Una vulnerabilidad en SQLite 3.41 no puede seguir una ruta de ejecución a través de una función que fue introducida en 2025, vamos, ¿en serio MITRE? 🥲
En el código fuente moderno de SQLite, el orden de llamada abreviado en sqlite3ExprIfTrue() es:
addrIsNull = exprComputeOperands(
pParse, pExpr, &r1, &r2, ®Free1, ®Free2);
codeCompare(
pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr, EP_Commuted));
/* Other switch cases and generated-bytecode handling occur here. */
sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ReleaseTempReg(pParse, regFree2);
exprComputeOperands() genera los identificadores de registro. El llamador los consume y luego los libera. El aviso, en cambio, afirma que sqlite3ReleaseTempReg() se ejecuta primero y que exprComputeOperands() accede después al objeto liberado.
exprComputeOperands() se introdujo para evitar evaluar un operando de subconsulta costoso cuando el otro operando es NULL. La expresión publicada:
CASE WHEN (1+3) THEN (5*8) ELSE (2/0) END
contiene operaciones aritméticas y una expresión CASE, pero ningún operando de subconsulta. La justificación dada para esta consulta no se corresponde con las condiciones de llamada de la función.
por cierto, vm
Debian GNU/Linux 13 (trixie)
Clang 19.1.7
AddressSanitizer enabled
Optimisation level: -O1
Frame pointers retained
Sanitizer recovery disabled
SHAs de las amalgamaciones:
3.41.0 146ce189b67fdbefbf2d72cdc81e198d07ff643614cc9102e9bf063255e8e7e1
3.41.1 df0d54bf246521360c8148f64e7e5ad07a4665b4f902339e844f4c493d535ff5
3.41.2 01df06a84803c1ab4d62c64e995b151b2dbcf5dbc93bbc5eee213cb18225d987
3.53.3 646421e12aac110282ef8cc68f1a62d4bb15fc7b8f09da0b53e29ee690500431