Re: BUG #16476: pgp_sym_encrypt_bytea with compress-level=6 : Wrong key or corrupt data
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: Michael Paquier <michael@paquier.xyz>
Cc: Mark Wong <mark@2ndquadrant.com>,
Kyotaro Horiguchi <horikyota.ntt@gmail.com>, jeff.janes@gmail.com,
frank.gagnepain@intm.fr, pgsql-bugs@lists.postgresql.org
Date: 2020-07-23T19:38:43Z
Lists: pgsql-bugs
I dug into this problem with access kindly provided by Mark Wong, and
verified that indeed the zlib on that machine acts a bit differently
from stock zlib. The problem we're facing turns out to be entirely
unrelated to the patch at hand; it's the *compression* side that is
misbehaving. After some digging in the code and reading the zlib.h
API spec carefully, the answer is that compress_process() completely
mishandles the situation where deflate() stops short of consuming all
the input that's supplied. It resets the next_in pointer so that
old data is reprocessed, rather than allowing the remaining unprocessed
data to be processed. We need to do this:
--- a/contrib/pgcrypto/pgp-compress.c
+++ b/contrib/pgcrypto/pgp-compress.c
@@ -114,10 +114,10 @@ compress_process(PushFilter *next, void *priv, const uint8 *data, int len)
/*
* process data
*/
- while (len > 0)
+ st->stream.next_in = unconstify(uint8 *, data);
+ st->stream.avail_in = len;
+ while (st->stream.avail_in > 0)
{
- st->stream.next_in = unconstify(uint8 *, data);
- st->stream.avail_in = len;
st->stream.next_out = st->buf;
st->stream.avail_out = st->buf_len;
res = deflate(&st->stream, 0);
@@ -131,7 +131,6 @@ compress_process(PushFilter *next, void *priv, const uint8 *data, int len)
if (res < 0)
return res;
}
- len = st->stream.avail_in;
}
return 0;
I suppose this has been broken since day one; it's a bit astonishing (and
disheartening) that nobody's reported a problem here before.
Anyway, with that corrected, the SLES zlib still produces different
output from stock zlib, and indeed seemingly is worse: the result
is noticeably larger than what stock zlib produces. It does decompress
back to the same thing, though, so this is a performance problem not
a data corruption issue. That does mean that the proposed test case
fails to exercise our empty-ending-block scenario with this version
of zlib. I don't think we really care about that, though.
I will go apply this fix, and then you can put back the fix for
the originally-reported problem. I still like Horiguchi-san's
fix better than what was committed, though.
regards, tom lane
Commits
-
Fix corner case with 16kB-long decompression in pgcrypto, take 2
- aaa132a65deb 9.5.23 landed
- 8a60f541f3e4 9.6.19 landed
- 9729f99798af 10.14 landed
- 202fc4ca531e 11.9 landed
- 5bd087eb5d77 12.4 landed
- 0caf1fc6e86a 13.0 landed
- a3ab7a707d9e 14.0 landed
-
Fix ancient violation of zlib's API spec.
- d0519e9fea96 9.5.23 landed
- ccf964a80100 9.6.19 landed
- d8ec3b1263d2 10.14 landed
- 475c69c97662 11.9 landed
- 3d4a778152ec 12.4 landed
- b9b610577d7f 14.0 landed
- 7dab4569d193 13.0 landed
-
Revert "Fix corner case with PGP decompression in pgcrypto"
- 43e21fd8f6e8 9.5.23 landed
- 11c320dcebc0 9.6.19 landed
- 9a3c895084c6 10.14 landed
- 6ae2d925b131 11.9 landed
- e30a63f258f5 12.4 landed
- 9f5162ef43c5 13.0 landed
- 38f60f174e32 14.0 landed
-
Fix corner case with PGP decompression in pgcrypto
- dbf17ca1bfab 9.5.23 landed
- e0cb8282d614 9.6.19 landed
- 5bfd0936b460 10.14 landed
- eceb415c6ff0 11.9 landed
- bba2e66aec4c 12.4 landed
- 35e142202b14 13.0 landed
- 9e108984fb35 14.0 landed