Page MenuHome GnuPG

left shift of negative value in iobuf.c
Closed, InvalidPublic

Description

Found using oss-fuzz

In file common/iobuf.c, function block_filter, line a->size = (size_t)iobuf_get (chain) << 24;and following

Patch should control each return of iobuf_get before doing the shift.

Bug can be reproduced by running
gpg --import crash-5f781765c3e418de81c4a5e6087b6c2beda9dbbd

Event Timeline

Sorry, I can replicate this with current 2.2 nor with master (on amd64 Linux):

~/b/gnupg-2.2/g10/gpg --import /tmp/crash-5f781765c3e418de81c4a5e6087b6c2beda9dbbd 
gpg: NOTE: THIS IS A DEVELOPMENT VERSION!
gpg: It is only intended for test purposes and should NOT be
gpg: used in a production environment or with production keys!
gpg: block_filter: invalid 4 byte length
gpg: encrypted_mdc packet with unknown version 0
gpg: read_block: read error: Invalid packet
gpg: block_filter: pending bytes!
gpg: import from '/tmp/crash-5f781765c3e418de81c4a5e6087b6c2beda9dbbd' failed: Invalid keyring
gpg: Total number processed: 0

and valgrind shows no problem either.

With this example, the problem happens at
a->size |= iobuf_get (chain) << 8;
iobuf_get (chain)returns -1 and -1 << 8 is not well defined.

It is not a big deal, since the following calls to iobuf_get (chain) return -1 as well
And so, we get the log block_filter: invalid 4 byte length

That is all intended. You can always create broken messages which don't result in _one_ clear error code.

The shifting is irrelevant because the value is not used and a property of iobuf_get is that it will keep on returning EOF. This is what is checked just the line below (which return GPG_ERR_BAD_DATA).