From 97d4955666779dc5b0665e15dd951a5c12426a31 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Mon, 20 Mar 2023 09:27:19 -0400 Subject: [PATCH] Fix potential denial-of-service in flate stream code. --- CHANGES.md | 3 ++- pdfio-stream.c | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2b25bca..620c14a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,9 +2,10 @@ Changes in PDFio ================ -v1.1.1 (Month DD, YYYY) +v1.1.1 (March 20, 2023) ----------------------- +- CVE-2023-NNNNN: Fixed a potential denial-of-service with corrupt PDF files. - Fixed a build issue. diff --git a/pdfio-stream.c b/pdfio-stream.c index 45a21b0..2c6399a 100644 --- a/pdfio-stream.c +++ b/pdfio-stream.c @@ -1008,6 +1008,7 @@ stream_read(pdfio_stream_t *st, // I - Stream size_t bytes) // I - Number of bytes to read { ssize_t rbytes; // Bytes read + uInt avail_in, avail_out; // Previous flate values if (st->filter == PDFIO_FILTER_NONE) @@ -1060,11 +1061,19 @@ stream_read(pdfio_stream_t *st, // I - Stream st->flate.next_out = (Bytef *)buffer; st->flate.avail_out = (uInt)bytes; + avail_in = st->flate.avail_in; + avail_out = st->flate.avail_out; + if ((status = inflate(&(st->flate), Z_NO_FLUSH)) < Z_OK) { _pdfioFileError(st->pdf, "Unable to decompress stream data: %s", zstrerror(status)); return (-1); } + else if (avail_in == st->flate.avail_in && avail_out == st->flate.avail_out) + { + _pdfioFileError(st->pdf, "Corrupt stream data."); + return (-1); + } return (st->flate.next_out - (Bytef *)buffer); } @@ -1113,12 +1122,15 @@ stream_read(pdfio_stream_t *st, // I - Stream st->flate.avail_in = (uInt)rbytes; } + avail_in = st->flate.avail_in; + avail_out = st->flate.avail_out; + if ((status = inflate(&(st->flate), Z_NO_FLUSH)) < Z_OK) { _pdfioFileError(st->pdf, "Unable to decompress stream data: %s", zstrerror(status)); return (-1); } - else if (status == Z_STREAM_END) + else if (status == Z_STREAM_END || (avail_in == st->flate.avail_in && avail_out == st->flate.avail_out)) break; } @@ -1180,12 +1192,15 @@ stream_read(pdfio_stream_t *st, // I - Stream st->flate.avail_in = (uInt)rbytes; } + avail_in = st->flate.avail_in; + avail_out = st->flate.avail_out; + if ((status = inflate(&(st->flate), Z_NO_FLUSH)) < Z_OK) { _pdfioFileError(st->pdf, "Unable to decompress stream data: %s", zstrerror(status)); return (-1); } - else if (status == Z_STREAM_END) + else if (status == Z_STREAM_END || (avail_in == st->flate.avail_in && avail_out == st->flate.avail_out)) break; }