diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2023-02-14 16:03:40 +0000 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2023-02-14 16:03:40 +0000 |
commit | 03e485b0a99d4cd94011f3d217be77de25ac8c4c (patch) | |
tree | be92945b6d1ac0bd8754df93b66d16744e95b300 /pdf | |
parent | 372b7efe8d597b56fb96bf6137af42a48e644fb4 (diff) | |
download | ghostpdl-03e485b0a99d4cd94011f3d217be77de25ac8c4c.tar.gz |
GhostPDF - spot errors in hex strings in fonts/CMaps
This was inspired by OSS-fuzz bug #55443, the PDF file has a CMap which
is corrupted, a hex string defining an entry in the CMap has some
garbage inserted into it.
This causes the CMap to have an extremely large range, which takes a
very long time to work through. Short-circuiting this by detecting the
error in the hex string makes the file complete much more quickly. Since
the CMap is corrupted the result is always going to be incorrect anyway
and at least this way we stop processing it more quickly.
Because CMaps and fonts use the same parser, this then exhibited an
error with a lot of fonts, particularly the PostScript emitted by
ps2write. It turns out that the eexec encrypted portion of the font has
rubbish following the 'currentfile closefile' and in some cases this
included an opening hex string marker '<' followed by non-hex data.
Obviously we shouldn't be processing that, I think we're lucky to have
got away with it to date. To fix the problem, create an operator for
fonts to deal with the 'closefile', and have that consume all the
remaining data in the buffer.
Diffstat (limited to 'pdf')
-rw-r--r-- | pdf/pdf_fontps.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/pdf/pdf_fontps.c b/pdf/pdf_fontps.c index f8e0fe82b..fea853d16 100644 --- a/pdf/pdf_fontps.c +++ b/pdf/pdf_fontps.c @@ -206,10 +206,16 @@ pdfi_pscript_interpret(pdf_ps_ctx_t *cs, byte *pdfpsbuf, int64_t buflen) for (i = 0; i < len; i += 2) { hbuf[0] = s[i]; hbuf[1] = s[i + 1]; + if (!ishex(hbuf[0]) || !ishex(hbuf[1])) { + code = gs_note_error(gs_error_typecheck); + break; + } *s2++ = (decodehex(hbuf[0]) << 4) | decodehex(hbuf[1]); } - pdfpsbuf++; /* move past the trailing '>' */ - code = pdf_ps_stack_push_string(cs, s, len >> 1); + if (i >= len) { + pdfpsbuf++; /* move past the trailing '>' */ + code = pdf_ps_stack_push_string(cs, s, len >> 1); + } } break; case '>': /* For hex strings, this should be handled above */ @@ -1212,6 +1218,12 @@ pdf_ps_put_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) return code; } +static int +pdf_ps_closefile_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + return bufend - buf; +} + static pdf_ps_oper_list_t ps_font_oper_list[] = { {PDF_PS_OPER_NAME_AND_LEN("RD"), pdf_ps_RD_oper_func}, {PDF_PS_OPER_NAME_AND_LEN("-|"), pdf_ps_RD_oper_func}, @@ -1236,6 +1248,7 @@ static pdf_ps_oper_list_t ps_font_oper_list[] = { {PDF_PS_OPER_NAME_AND_LEN("for"), pdf_ps_pop4_oper_func}, {PDF_PS_OPER_NAME_AND_LEN("put"), pdf_ps_put_oper_func}, {PDF_PS_OPER_NAME_AND_LEN("StandardEncoding"), pdf_ps_standardencoding_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("closefile"), pdf_ps_closefile_oper_func}, {NULL, 0, NULL} }; |