Created attachment 26787 [details] Proof of concept # Title: Stack-based buffer overflow in pdf_write_cmap # Date Found: 2025-05-12 # Version: Tested on commit e77e13e11708335555a27ea0c5ec7c005d159049 # Author: Piotr Kajda # Tested On: Arch Linux I have discovered a stack-based buffer overflow in the pdf_write_cmap function located in devices/vector/gdevpdtw.c at line 797. There is no check of cmap name size before memcpy to statically allocated buffer. I have attached poc.pdf which triggers the bug. Step to reproduce with asan output: sanbin/gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=test.pdf poc.pdf ================================================================= ==21330==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x72118034ff38 at pc 0x721186cfaf59 bp 0x7fffe0101430 sp 0x7fffe0100bd8 WRITE of size 218 at 0x72118034ff38 thread T0 #0 0x721186cfaf58 in memcpy /usr/src/debug/gcc/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:115 #1 0x6069115184d9 in pdf_write_cmap devices/vector/gdevpdtw.c:797 #2 0x6069114e2599 in pdf_cmap_alloc devices/vector/gdevpdtf.c:1280 #3 0x6069114b4e4a in attach_cmap_resource devices/vector/gdevpdtc.c:310 #4 0x6069114bb721 in scan_cmap_text devices/vector/gdevpdtc.c:823 #5 0x6069114bcf7d in process_cmap_text devices/vector/gdevpdtc.c:968 #6 0x606911512779 in pdf_text_process devices/vector/gdevpdtt.c:3832 #7 0x60691191d8b1 in gs_text_process base/gstext.c:682 #8 0x606912171377 in pdfi_show_simple pdf/pdf_text.c:436 #9 0x606912173ede in pdfi_show_Tr_preserve pdf/pdf_text.c:806 #10 0x60691217468b in pdfi_show pdf/pdf_text.c:857 #11 0x6069121789e5 in pdfi_TJ pdf/pdf_text.c:1270 #12 0x60691204715e in pdfi_interpret_stream_operator pdf/pdf_int.c:1669 #13 0x60691204aa23 in pdfi_interpret_content_stream pdf/pdf_int.c:2148 #14 0x6069120b2a31 in pdfi_process_page_contents pdf/pdf_page.c:135 #15 0x6069120b2cb3 in pdfi_process_one_page pdf/pdf_page.c:159 #16 0x6069120ba987 in pdfi_page_render pdf/pdf_page.c:1029 #17 0x60691200be94 in zPDFdrawpage psi/zpdfops.c:963 #18 0x606911df1e90 in do_call_operator psi/interp.c:91 #19 0x606911dffcae in interp psi/interp.c:1772 #20 0x606911df3cb9 in gs_call_interp psi/interp.c:535 #21 0x606911df32dc in gs_interpret psi/interp.c:488 #22 0x606911dc5f89 in gs_main_interpret psi/imain.c:257 #23 0x606911dcae38 in gs_main_run_string_end psi/imain.c:945 #24 0x606911dca7e4 in gs_main_run_string_with_length psi/imain.c:889 #25 0x606911dca756 in gs_main_run_string psi/imain.c:870 #26 0x606911dd7dd5 in run_string psi/imainarg.c:1188 #27 0x606911dd7ae3 in runarg psi/imainarg.c:1147 #28 0x606911dd7341 in argproc psi/imainarg.c:1069 #29 0x606911dd1632 in gs_main_init_with_args01 psi/imainarg.c:250 #30 0x606911dd1b9f in gs_main_init_with_args psi/imainarg.c:304 #31 0x606911ddd5b9 in psapi_init_with_args psi/psapi.c:294 #32 0x6069121d9476 in gsapi_init_with_args psi/iapi.c:253 #33 0x606910894721 in main psi/gs.c:104 #34 0x721185a35487 (/usr/lib/libc.so.6+0x27487) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0) #35 0x721185a3554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 0b707b217b15b106c25fe51df3724b25848310c0) #36 0x606910894404 in _start (/home/zxcv/ghostpdl_org/sanbin/gs+0x3af404) (BuildId: 27a3edd0d99c18eca2535260d6c81a6aa7d42689) Address 0x72118034ff38 is located in stack of thread T0 at offset 824 in frame #0 0x6069115180f5 in pdf_write_cmap devices/vector/gdevpdtw.c:772 My fix: diff --git a/devices/vector/gdevpdtw.c b/devices/vector/gdevpdtw.c index ced15c9b2..4c433ccd4 100644 --- a/devices/vector/gdevpdtw.c +++ b/devices/vector/gdevpdtw.c @@ -794,6 +794,10 @@ pdf_write_cmap(gx_device_pdf *pdev, const gs_cmap_t *pcmap, if (code < 0) return code; buf[0] = '/'; + + if(pcmap->CMapName.size >= sizeof(buf)) + return_error(gs_error_limitcheck); + memcpy(buf + 1, pcmap->CMapName.data, pcmap->CMapName.size); code = cos_dict_put_c_key_string(pcd, "/CMapName", buf, pcmap->CMapName.size + 1);
Fixed in commit 0cae41b23a9669e801211dd4cf97b6dadd6dbdd7 There's nothing wrong with the proposed patch, but this deals with the problem in (I think) a neater way using dynamic allocation. Previously a lengthy CMap name could easily cause an error writing the CIDSystemInfo which would be ignored and produce an invalid PDF file.