From db4e21fea6c156f8b2b710937cbee1e7e8d7b7c2 Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Tue, 17 Apr 2018 02:32:23 +0800 Subject: Limit xref parser to read entry contents. Previously if an xref entry looked like: 0000000000 65535 f 1 0 n 2 the xref entry parsing would try to access the scratch buffer outside of the part populated by the read leading to possibly using uninitalized data. --- source/pdf/pdf-xref.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'source') diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c index 2d26cdd1..158ffbf5 100644 --- a/source/pdf/pdf-xref.c +++ b/source/pdf/pdf-xref.c @@ -833,7 +833,7 @@ pdf_read_old_xref(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf) pdf_xref_entry *table; pdf_token tok; size_t n; - char *s; + char *s, *e; xref_len = pdf_xref_size_from_old_trailer(ctx, doc, buf); @@ -885,24 +885,40 @@ pdf_read_old_xref(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf) if (n != 20-carried) fz_throw(ctx, FZ_ERROR_GENERIC, "unexpected EOF in xref table"); n += carried; + buf->scratch[n] = '\0'; if (!entry->type) { s = buf->scratch; + e = s + n; + + entry->num = start + i; /* broken pdfs where line start with white space */ - while (*s != '\0' && iswhite(*s)) + while (s < e && iswhite(*s)) s++; - entry->ofs = fz_atoi64(s); - entry->gen = fz_atoi(s + 11); - entry->num = start + i; - entry->type = s[17]; - if (s[17] != 'f' && s[17] != 'n' && s[17] != 'o') - fz_throw(ctx, FZ_ERROR_GENERIC, "unexpected xref type: 0x%x (%d %d R)", s[17], entry->num, entry->gen); + if (s == e || !isdigit(*s)) + fz_throw(ctx, FZ_ERROR_GENERIC, "xref offset missing"); + while (s < e && isdigit(*s)) + entry->ofs = entry->ofs * 10 + *s++ - '0'; + + while (s < e && iswhite(*s)) + s++; + if (s == e || !isdigit(*s)) + fz_throw(ctx, FZ_ERROR_GENERIC, "xref generation number missing"); + while (s < e && isdigit(*s)) + entry->gen = entry->gen * 10 + *s++ - '0'; + + while (s < e && iswhite(*s)) + s++; + if (s == e || (*s != 'f' && *s != 'n' && *s != 'o')) + fz_throw(ctx, FZ_ERROR_GENERIC, "unexpected xref type: 0x%x (%d %d R)", s == e ? 0 : *s, entry->num, entry->gen); + entry->type = *s++; + /* If the last byte of our buffer isn't an EOL (or space), carry one byte forward */ - carried = s[19] > 32; + carried = buf->scratch[19] > 32; if (carried) - s[0] = s[19]; + buf->scratch[0] = buf->scratch[19]; } } if (carried) -- cgit v1.2.3