diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-01-04 15:22:13 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-01-04 15:24:57 +0100 |
commit | 49be4f7b82eba2363bb8d4090950dad976a77a3a (patch) | |
tree | 4b4dc9d143b89529cdf5aef2ac55f4f02617d59d | |
parent | 65ee81db857d3b44cec76aa94361abe5427430d8 (diff) | |
download | gnutls-tmp-fix-openpgp-issues.tar.gz |
opencdk: added error checking in the stream reading functionstmp-fix-openpgp-issues
This addresses an out of memory error. Issue found using oss-fuzz:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=337
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r-- | lib/opencdk/read-packet.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/lib/opencdk/read-packet.c b/lib/opencdk/read-packet.c index b999e1c000..fa4c604d81 100644 --- a/lib/opencdk/read-packet.c +++ b/lib/opencdk/read-packet.c @@ -42,6 +42,7 @@ static int stream_read(cdk_stream_t s, void *buf, size_t buflen, size_t * r_nread) { int res = cdk_stream_read(s, buf, buflen); + if (res > 0) { *r_nread = res; return 0; @@ -55,13 +56,13 @@ stream_read(cdk_stream_t s, void *buf, size_t buflen, size_t * r_nread) static u32 read_32(cdk_stream_t s) { byte buf[4]; - size_t nread; + size_t nread = 0; assert(s != NULL); stream_read(s, buf, 4, &nread); if (nread != 4) - return (u32) - 1; + return (u32) -1; return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; } @@ -70,7 +71,7 @@ static u32 read_32(cdk_stream_t s) static u16 read_16(cdk_stream_t s) { byte buf[2]; - size_t nread; + size_t nread = 0; assert(s != NULL); @@ -572,7 +573,7 @@ read_user_id(cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id) static cdk_error_t read_subpkt(cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes) { - byte c, c1; + int c, c1; size_t size, nread, n; cdk_subpkt_t node; cdk_error_t rc; @@ -587,11 +588,18 @@ read_subpkt(cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes) *r_nbytes = 0; c = cdk_stream_getc(inp); n++; + if (c == 255) { size = read_32(inp); + if (size == (u32)-1) + return CDK_Inv_Packet; + n += 4; } else if (c >= 192 && c < 255) { c1 = cdk_stream_getc(inp); + if (c1 == EOF) + return CDK_Inv_Packet; + n++; if (c1 == 0) return 0; @@ -858,17 +866,29 @@ static void read_old_length(cdk_stream_t inp, int ctb, size_t * r_len, size_t * r_size) { int llen = ctb & 0x03; + int c; if (llen == 0) { - *r_len = cdk_stream_getc(inp); + c = cdk_stream_getc(inp); + if (c == EOF) + goto fail; + + *r_len = c; (*r_size)++; } else if (llen == 1) { *r_len = read_16(inp); + if (*r_len == (u16)-1) + goto fail; (*r_size) += 2; } else if (llen == 2) { *r_len = read_32(inp); + if (*r_len == (u32)-1) { + goto fail; + } + (*r_size) += 4; } else { + fail: *r_len = 0; *r_size = 0; } @@ -883,15 +903,25 @@ read_new_length(cdk_stream_t inp, int c, c1; c = cdk_stream_getc(inp); + if (c == EOF) + return; + (*r_size)++; if (c < 192) *r_len = c; else if (c >= 192 && c <= 223) { c1 = cdk_stream_getc(inp); + if (c1 == EOF) + return; + (*r_size)++; *r_len = ((c - 192) << 8) + c1 + 192; } else if (c == 255) { *r_len = read_32(inp); + if (*r_len == (u32)-1) { + return; + } + (*r_size) += 4; } else { *r_len = 1 << (c & 0x1f); |