Incorrect implementation of `ccv_bfloat_to_double`
Author: hgarrereynCreated Sep 29, 2025Updated Sep 29, 2025
Hi, it looks like ccv_bfloat_to_double is implemented incorrectly.
Specifically, this is the current implementation: https://github.com/liuliu/ccv/blob/a1a8e06afe7d40d1f053f494da602f9a72c41617/lib/ccv_util.c#L1819-L1830
Inside the loop, it always unconditionally accesses h[1] (i.e. the same element is repeatedly converted to a double), instead of indexing using the index variable (i.e. h[i]).
For cases where there is only one element, this causes a buffer OOB read (see below testcase), but also this would likely cause functional issues.
(found via automated fuzzing)
testcase.cpp
#include <cstdint>
extern "C" {
#include "/fuzz/install/include/ccv.h"
}
int main() {
uint16_t b[1] = { 0x1234 };
double d[1];
ccv_bfloat_to_double(b, d, 1); // Triggers ASan OOB read in ccv_bfloat_to_double
return 0;
}crash report
{
"Date": "2025-09-29T02:18:53.599961+00:00",
"Uname": "Linux 795a6a8d1cfb 5.15.0-156-generic #166-Ubuntu SMP Sat Aug 9 00:02:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux",
"OS": "Ubuntu",
"OSRelease": "22.04",
"Architecture": "amd64",
"ExecutablePath": "/tmp/tmpsldzq0as/reproducer",
"ProcEnviron": [
"LIBAFL_EDGES_MAP_SIZE=800000",
"PWD=/fuzz/workspace",
"CXX=gf_libafl_cxx",
"GRAPHFUZZ_USE_ASAN=1",
"HOME=/root",
"ASAN_OPTIONS=hard_rss_limit_mb=1024:detect_leaks=0",
"TERM=xterm-256color",
"SHLVL=1",
"LD_LIBRARY_PATH=/fuzz/install/lib",
"PATH=/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"CC=gf_libafl_cc",
"DEBIAN_FRONTEND=noninteractive",
"OLDPWD=/fuzz/src/lib",
"_=/usr/local/bin/agfi"
],
"ProcCmdline": "/tmp/tmpsldzq0as/reproducer",
"Stdin": "",
"ProcStatus": [],
"ProcMaps": [],
"ProcFiles": [],
"NetworkConnections": [],
"CrashSeverity": {
"Type": "NOT_EXPLOITABLE",
"ShortDescription": "stack-buffer-overflow(read)",
"Description": "Stack buffer overflow",
"Explanation": "The target reads data past the end, or before the beginning, of the intended stack buffer."
},
"Stacktrace": [
" #0 0x5555556948d8 in ccv_bfloat_to_double /fuzz/src/lib/ccv_util.c",
" #1 0x55555565c4d2 in main /tmp/tmpsldzq0as/reproducer.cpp:8:3",
" #2 0x7ffff5619d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
" #3 0x7ffff5619e3f in __libc_start_main csu/../csu/libc-start.c:392:3",
" #4 0x5555555812f4 in _start (/tmp/tmpsldzq0as/reproducer+0x2d2f4) (BuildId: dd32829972587349cd60b31f65a72ede5f40cb37)"
],
"Registers": {},
"Disassembly": [],
"Package": "",
"PackageVersion": "",
"PackageArchitecture": "",
"PackageDescription": "",
"AsanReport": [
"==219==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffff3600022 at pc 0x5555556948d9 bp 0x7fffffffea10 sp 0x7fffffffea08",
"READ of size 2 at 0x7ffff3600022 thread T0",
" #0 0x5555556948d8 in ccv_bfloat_to_double /fuzz/src/lib/ccv_util.c",
" #1 0x55555565c4d2 in main /tmp/tmpsldzq0as/reproducer.cpp:8:3",
" #2 0x7ffff5619d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
" #3 0x7ffff5619e3f in __libc_start_main csu/../csu/libc-start.c:392:3",
" #4 0x5555555812f4 in _start (/tmp/tmpsldzq0as/reproducer+0x2d2f4) (BuildId: dd32829972587349cd60b31f65a72ede5f40cb37)",
"",
"Address 0x7ffff3600022 is located in stack of thread T0 at offset 34 in frame",
" #0 0x55555565c3ff in main /tmp/tmpsldzq0as/reproducer.cpp:5",
"",
" This frame has 2 object(s):",
" [32, 34) 'b' (line 6) <== Memory access at offset 34 overflows this variable",
" [48, 56) 'd' (line 7)",
"HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork",
" (longjmp and C++ exceptions *are* supported)",
"SUMMARY: AddressSanitizer: stack-buffer-overflow /fuzz/src/lib/ccv_util.c in ccv_bfloat_to_double",
"Shadow bytes around the buggy address:",
" 0x7ffff35ffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
" 0x7ffff35ffe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
" 0x7ffff35ffe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
" 0x7ffff35fff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
" 0x7ffff35fff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
"=>0x7ffff3600000: f1 f1 f1 f1[02]f2 00 f3 f3 f3 f3 f3 00 00 00 00",
" 0x7ffff3600080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
" 0x7ffff3600100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
" 0x7ffff3600180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
" 0x7ffff3600200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
" 0x7ffff3600280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
"Shadow byte legend (one shadow byte represents 8 application bytes):",
" Addressable: 00",
" Partially addressable: 01 02 03 04 05 06 07",
" Heap left redzone: fa",
" Freed heap region: fd",
" Stack left redzone: f1",
" Stack mid redzone: f2",
" Stack right redzone: f3",
" Stack after return: f5",
" Stack use after scope: f8",
" Global redzone: f9",
" Global init order: f6",
" Poisoned by user: f7",
" Container overflow: fc",
" Array cookie: ac",
" Intra object redzone: bb",
" ASan internal: fe",
" Left alloca redzone: ca",
" Right alloca redzone: cb",
"==219==ABORTING"
],
"MsanReport": [],
"UbsanReport": [],
"LuaReport": [],
"PythonReport": [],
"GoReport": [],
"JavaReport": [],
"RustReport": [],
"JsReport": [],
"CSharpReport": [],
"CrashLine": "/fuzz/src/lib/ccv_util.c",
"Source": []
}Source: liuliu/ccv