1From dc92574c10f3e2516ec6445b88c5d584f40df4e5 Mon Sep 17 00:00:00 2001
2From: Jay Berkenbilt <ejb@ql.org>
3Date: Mon, 4 Jan 2021 11:55:28 -0500
4Subject: [PATCH] Fix some pipelines to be safe if downstream write fails (fuzz
5 issue 28262)
6
7[Retrieved (and updated to remove updates on ChangeLog and fuzz) from:
8https://github.com/qpdf/qpdf/commit/dc92574c10f3e2516ec6445b88c5d584f40df4e5]
9Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
10---
11 ChangeLog                     |   6 ++++++
12 fuzz/qpdf_extra/28262.fuzz    | Bin 0 -> 40395 bytes
13 libqpdf/Pl_AES_PDF.cc         |   2 +-
14 libqpdf/Pl_ASCII85Decoder.cc  |   7 +++++--
15 libqpdf/Pl_ASCIIHexDecoder.cc |   6 ++++--
16 libqpdf/Pl_Count.cc           |   2 +-
17 6 files changed, 17 insertions(+), 6 deletions(-)
18 create mode 100644 fuzz/qpdf_extra/28262.fuzz
19
20diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc
21index 18cf3a4d..2865f804 100644
22--- a/libqpdf/Pl_AES_PDF.cc
23+++ b/libqpdf/Pl_AES_PDF.cc
24@@ -238,6 +238,6 @@ Pl_AES_PDF::flush(bool strip_padding)
25 	    }
26 	}
27     }
28-    getNext()->write(this->outbuf, bytes);
29     this->offset = 0;
30+    getNext()->write(this->outbuf, bytes);
31 }
32diff --git a/libqpdf/Pl_ASCII85Decoder.cc b/libqpdf/Pl_ASCII85Decoder.cc
33index b8df3e87..9d9f6704 100644
34--- a/libqpdf/Pl_ASCII85Decoder.cc
35+++ b/libqpdf/Pl_ASCII85Decoder.cc
36@@ -119,10 +119,13 @@ Pl_ASCII85Decoder::flush()
37
38     QTC::TC("libtests", "Pl_ASCII85Decoder partial flush",
39 	    (this->pos == 5) ? 0 : 1);
40-    getNext()->write(outbuf, this->pos - 1);
41-
42+    // Reset before calling getNext()->write in case that throws an
43+    // exception.
44+    auto t = this->pos - 1;
45     this->pos = 0;
46     memset(this->inbuf, 117, 5);
47+
48+    getNext()->write(outbuf, t);
49 }
50
51 void
52diff --git a/libqpdf/Pl_ASCIIHexDecoder.cc b/libqpdf/Pl_ASCIIHexDecoder.cc
53index f20a9769..7845268e 100644
54--- a/libqpdf/Pl_ASCIIHexDecoder.cc
55+++ b/libqpdf/Pl_ASCIIHexDecoder.cc
56@@ -97,12 +97,14 @@ Pl_ASCIIHexDecoder::flush()
57
58     QTC::TC("libtests", "Pl_ASCIIHexDecoder partial flush",
59 	    (this->pos == 2) ? 0 : 1);
60-    getNext()->write(&ch, 1);
61-
62+    // Reset before calling getNext()->write in case that throws an
63+    // exception.
64     this->pos = 0;
65     this->inbuf[0] = '0';
66     this->inbuf[1] = '0';
67     this->inbuf[2] = '\0';
68+
69+    getNext()->write(&ch, 1);
70 }
71
72 void
73diff --git a/libqpdf/Pl_Count.cc b/libqpdf/Pl_Count.cc
74index 8077092a..c35619b8 100644
75--- a/libqpdf/Pl_Count.cc
76+++ b/libqpdf/Pl_Count.cc
77@@ -27,8 +27,8 @@ Pl_Count::write(unsigned char* buf, size_t len)
78     if (len)
79     {
80 	this->m->count += QIntC::to_offset(len);
81-	getNext()->write(buf, len);
82 	this->m->last_char = buf[len - 1];
83+	getNext()->write(buf, len);
84     }
85 }
86
87