diff --git a/contrib/pgcrypto/expected/pgp-compression.out b/contrib/pgcrypto/expected/pgp-compression.out
index 32b350b8fe..d4c57feba3 100644
--- a/contrib/pgcrypto/expected/pgp-compression.out
+++ b/contrib/pgcrypto/expected/pgp-compression.out
@@ -48,3 +48,33 @@ select pgp_sym_decrypt(
  Secret message
 (1 row)
 
+-- check corner case involving an input string of 16kB, as per bug #16476.
+SELECT setseed(0);
+ setseed 
+---------
+ 
+(1 row)
+
+WITH random_string AS
+(
+  -- This generates a random string of 16366 bytes.  This is chosen
+  -- as random so that it does not get compressed, and the decompression
+  -- would work on a string with the same length as the origin, making the
+  -- test behavior more predictible.  lpad() ensures that the generated
+  -- hexadecimal value is completed by extra zero characters if random()
+  -- has generated a value strictly lower than 16.
+  SELECT string_agg(decode(lpad(to_hex((random()*256)::int), 2, '0'), 'hex'), '') as bytes
+    FROM generate_series(0, 16365)
+)
+SELECT bytes =
+    pgp_sym_decrypt_bytea(
+      pgp_sym_encrypt_bytea(bytes, 'key',
+                            'compress-algo=1,compress-level=1'),
+                            'key', 'expect-compress-algo=1')
+    AS is_same
+  FROM random_string;
+ is_same 
+---------
+ t
+(1 row)
+
diff --git a/contrib/pgcrypto/pgp-compress.c b/contrib/pgcrypto/pgp-compress.c
index 0505bdee92..a37595dcc9 100644
--- a/contrib/pgcrypto/pgp-compress.c
+++ b/contrib/pgcrypto/pgp-compress.c
@@ -243,6 +243,20 @@ decompress_read(void *priv, PullFilter *src, int len,
 	struct DecomprData *dec = priv;
 
 restart:
+	if (dec->stream.avail_in == 0)
+	{
+		uint8	   *tmp;
+
+		res = pullf_read(src, 8192, &tmp);
+		if (res < 0)
+			return res;
+
+		Assert(res != Z_STREAM_END || dec->buf_data > 0);
+
+		dec->stream.next_in = tmp;
+		dec->stream.avail_in = res;
+	}
+
 	if (dec->buf_data > 0)
 	{
 		if (len > dec->buf_data)
@@ -256,17 +270,6 @@ restart:
 	if (dec->eof)
 		return 0;
 
-	if (dec->stream.avail_in == 0)
-	{
-		uint8	   *tmp;
-
-		res = pullf_read(src, 8192, &tmp);
-		if (res < 0)
-			return res;
-		dec->stream.next_in = tmp;
-		dec->stream.avail_in = res;
-	}
-
 	dec->stream.next_out = dec->buf;
 	dec->stream.avail_out = dec->buf_len;
 	dec->pos = dec->buf;
diff --git a/contrib/pgcrypto/sql/pgp-compression.sql b/contrib/pgcrypto/sql/pgp-compression.sql
index ca9ee1fc00..87c59c6cab 100644
--- a/contrib/pgcrypto/sql/pgp-compression.sql
+++ b/contrib/pgcrypto/sql/pgp-compression.sql
@@ -28,3 +28,24 @@ select pgp_sym_decrypt(
 	pgp_sym_encrypt('Secret message', 'key',
 			'compress-algo=2, compress-level=0'),
 	'key', 'expect-compress-algo=0');
+
+-- check corner case involving an input string of 16kB, as per bug #16476.
+SELECT setseed(0);
+WITH random_string AS
+(
+  -- This generates a random string of 16366 bytes.  This is chosen
+  -- as random so that it does not get compressed, and the decompression
+  -- would work on a string with the same length as the origin, making the
+  -- test behavior more predictible.  lpad() ensures that the generated
+  -- hexadecimal value is completed by extra zero characters if random()
+  -- has generated a value strictly lower than 16.
+  SELECT string_agg(decode(lpad(to_hex((random()*256)::int), 2, '0'), 'hex'), '') as bytes
+    FROM generate_series(0, 16365)
+)
+SELECT bytes =
+    pgp_sym_decrypt_bytea(
+      pgp_sym_encrypt_bytea(bytes, 'key',
+                            'compress-algo=1,compress-level=1'),
+                            'key', 'expect-compress-algo=1')
+    AS is_same
+  FROM random_string;
