
클릭베이트. 그 CVE는 AI 쓰레기입니다.
클릭베이트성 저장소 이름이라 죄송하지만, 이 CVE는 순전히 LLM이 환각으로 만들어낸 쓰레기입니다. 주장이 이렇게 모순적인데도 CNA가 이를 받아들인 것을 보니 정말 안타깝습니다 💔
CVE-2026-51302는 실제가 아닙니다 😱
게시된 SQL은 AddressSanitizer에서 어떤 SQLite 3.41 릴리스에서도 use-after-free를 재현하지 않습니다. 더 중요한 것은, 명시된 근본 원인이 영향을 받는 소스와 완전히 호환되지 않는다는 점입니다:
exprComputeOperands()는 SQLite 3.41.0, 3.41.1 또는 3.41.2에 존재하지 않습니다;regFree1은 가상 머신 레지스터 식별자(정수)이지 힙 저장소를 가리키는 포인터가 아닙니다;sqlite3ReleaseTempReg()는 레지스터를 재사용 가능하게 만들 뿐 regFree1에 댕글링 C 포인터를 남기지 않습니다;exprComputeOperands()를 포함하는 소스 버전에서는 권고문에 명시된 순서와 달리 임시 레지스터가 해제되기 전에 피연산자가 계산됩니다; 그리고exprComputeOperands()가 도입된 최적화를 실행하지 않습니다.이 CVE 레코드는 기각되어야 하며, 저는 MITRE에 CNA 이의를 제기할 것입니다 😉
권고문은 영향을 받는 버전을 "SQLite 3.41"로 식별하며 다음 쿼리를 제공합니다:
SELECT CASE WHEN (1+3) THEN (5*8) ELSE (2/0) END FROM test;
이에 따르면 다음과 같이 주장합니다:
sqlite3ReleaseTempReg()가 regFree1과 연관된 힙 메모리를 해제한다;regFree1은 댕글링 참조로 남는다;exprComputeOperands()가 이후 해제된 메모리에 접근한다; 그리고SQLite 3.41.0 앨러머게이션은 함수를 다음과 같이 정의합니다:
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;
}
}
}
이 함수는 iReg를 int로 받습니다. 레지스터 번호를 다시 할당할 수 있도록 해당 정수를 pParse->aTempReg에 기록합니다:
SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
if( pParse->nTempReg==0 ){
return ++pParse->nMem;
}
return pParse->aTempReg[--pParse->nTempReg];
}
이는 VDBE 프로그램 생성 중 레지스터 수명 관리입니다. 권고문은 regFree1이 해제된 힙 저장소에 대한 잔존하는 포인터인 것처럼 설명하지만, 그렇지 않습니다:
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);
생성된 비교는 레지스터 식별자를 재사용을 위해 해제되기 전에 소비합니다.
Git 미러에 대한 blame 검색 결과 exprComputeOperands()는 다음 커밋으로 도입되었습니다:
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.
이 함수는 공식 SQLite 3.41 앨러머게이션 세 가지 모두에 존재하지 않습니다. SQLite 3.41의 취약점이 2025년에 도입된 함수를 통과하는 실행 경로를 가질 수는 없습니다. 에이, MITRE 정말요? 🥲
최신 SQLite 소스에서 sqlite3ExprIfTrue()의 축약된 호출 순서는 다음과 같습니다:
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()는 레지스터 식별자를 생성합니다. 호출자는 이를 소비한 후 해제합니다. 반면 권고문은 sqlite3ReleaseTempReg()가 먼저 실행되고 exprComputeOperands()가 나중에 해제된 객체에 접근한다고 주장합니다.
exprComputeOperands()는 다른 피연산자가 NULL일 때 값비싼 하위 쿼리 피연산자의 평가를 피하기 위해 도입되었습니다. 게시된 표현식:
CASE WHEN (1+3) THEN (5*8) ELSE (2/0) END
산술 연산과 CASE 표현식을 포함하지만 하위 쿼리 피연산자는 없습니다. 이 쿼리에 대해 제시된 근거는 함수의 호출 조건과 일치하지 않습니다.
참고로 VM입니다
Debian GNU/Linux 13 (trixie)
Clang 19.1.7
AddressSanitizer enabled
Optimisation level: -O1
Frame pointers retained
Sanitizer recovery disabled
앨러머게이션 SHA:
3.41.0 146ce189b67fdbefbf2d72cdc81e198d07ff643614cc9102e9bf063255e8e7e1
3.41.1 df0d54bf246521360c8148f64e7e5ad07a4665b4f902339e844f4c493d535ff5
3.41.2 01df06a84803c1ab4d62c64e995b151b2dbcf5dbc93bbc5eee213cb18225d987
3.53.3 646421e12aac110282ef8cc68f1a62d4bb15fc7b8f09da0b53e29ee690500431