common: Don't incorrectly reject 4 GB - 1 sized packets.
authorNeal H. Walfield <neal@g10code.com>
Fri, 21 Aug 2015 09:55:15 +0000 (11:55 +0200)
committerNeal H. Walfield <neal@g10code.com>
Fri, 21 Aug 2015 12:21:13 +0000 (14:21 +0200)
* g10/parse-packet.c (parse): Don't reject 4 GB - 1 sized packets.
Add the constraint that the type must be 63.
* kbx/keybox-openpgp.c (next_packet): Likewise.
* tests/openpgp/4gb-packet.asc: New file.
* tests/openpgp/4gb-packet.test: New file.
* tests/openpgp/Makefile.am (TESTS): Add 4gb-packet.test.
(TEST_FILES): Add 4gb-packet.asc.

--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
g10/parse-packet.c
kbx/keybox-openpgp.c
tests/openpgp/4gb-packet.asc [new file with mode: 0644]
tests/openpgp/4gb-packet.test [new file with mode: 0755]
tests/openpgp/Makefile.am

index bc99653..edebbe7 100644 (file)
@@ -643,7 +643,14 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
        }
     }
 
        }
     }
 
-  if (pktlen == (unsigned long) (-1))
+  /* Sometimes the decompressing layer enters an error state in which
+     it simply outputs 0xff for every byte read.  If we have a stream
+     of 0xff bytes, then it will be detected as a new format packet
+     with type 63 and a 4-byte encoded length that is 4G-1.  Since
+     packets with type 63 are private and we use them as a control
+     packet, which won't be 4 GB, we reject such packets as
+     invalid.  */
+  if (pkttype == 63 && pktlen == 0xFFFFFFFF)
     {
       /* With some probability this is caused by a problem in the
        * the uncompressing layer - in some error cases it just loops
     {
       /* With some probability this is caused by a problem in the
        * the uncompressing layer - in some error cases it just loops
index 2cac242..a5f602b 100644 (file)
@@ -139,7 +139,14 @@ next_packet (unsigned char const **bufptr, size_t *buflen,
       return gpg_error (GPG_ERR_UNEXPECTED);
     }
 
       return gpg_error (GPG_ERR_UNEXPECTED);
     }
 
-  if (pktlen == (unsigned long)(-1))
+  if (pkttype == 63 && pktlen == 0xFFFFFFFF)
+    /* Sometimes the decompressing layer enters an error state in
+       which it simply outputs 0xff for every byte read.  If we have a
+       stream of 0xff bytes, then it will be detected as a new format
+       packet with type 63 and a 4-byte encoded length that is 4G-1.
+       Since packets with type 63 are private and we use them as a
+       control packet, which won't be 4 GB, we reject such packets as
+       invalid.  */
     return gpg_error (GPG_ERR_INV_PACKET);
 
   if (pktlen > len)
     return gpg_error (GPG_ERR_INV_PACKET);
 
   if (pktlen > len)
diff --git a/tests/openpgp/4gb-packet.asc b/tests/openpgp/4gb-packet.asc
new file mode 100644 (file)
index 0000000..7e5d6f3
Binary files /dev/null and b/tests/openpgp/4gb-packet.asc differ
diff --git a/tests/openpgp/4gb-packet.test b/tests/openpgp/4gb-packet.test
new file mode 100755 (executable)
index 0000000..f8e43c8
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+. $srcdir/defs.inc || exit 3
+
+# GnuPG through 2.1.7 would incorrect mark packets whose size is
+# 2^32-1 as invalid and exit with status code 2.
+i=$srcdir/4gb-packet.asc
+
+if ! $GPG --list-packets $i
+then
+  echo Failed to parse 4GB packet.
+  exit 1
+else
+  echo Can parse 4GB packets.
+  exit 0
+fi
index dae8c11..4fdb0a6 100644 (file)
@@ -38,7 +38,7 @@ TESTS = version.test mds.test \
        armdetachm.test detachm.test genkey1024.test \
        conventional.test conventional-mdc.test \
        multisig.test verify.test armor.test \
        armdetachm.test detachm.test genkey1024.test \
        conventional.test conventional-mdc.test \
        multisig.test verify.test armor.test \
-       import.test ecc.test finish.test
+       import.test ecc.test 4gb-packet.test finish.test
 
 
 TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \
 
 
 TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \
@@ -46,7 +46,7 @@ TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \
             pubring.pkr.asc secring.skr.asc secdemo.asc pubdemo.asc \
              gpg.conf.tmpl gpg-agent.conf.tmpl \
             bug537-test.data.asc bug894-test.asc \
             pubring.pkr.asc secring.skr.asc secdemo.asc pubdemo.asc \
              gpg.conf.tmpl gpg-agent.conf.tmpl \
             bug537-test.data.asc bug894-test.asc \
-            bug1223-good.asc bug1223-bogus.asc
+            bug1223-good.asc bug1223-bogus.asc 4gb-packet.asc
 
 data_files = data-500 data-9000 data-32000 data-80000 plain-large
 
 
 data_files = data-500 data-9000 data-32000 data-80000 plain-large