diff options
author | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2020-02-01 22:08:30 +0300 |
---|---|---|
committer | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2020-02-01 22:08:30 +0300 |
commit | e382ea5c2bb38179e4a8a57464cd97a04653b1df (patch) | |
tree | 3ea631146a6fa64e4882f0a2c85b856ae3f7961a /pb_decode.c | |
parent | 982655a7c9efabd3dd42faae03057203ddd070d8 (diff) |
Avoid overflows in allocation for packed fields.
This will only occur with unlimited length streams, so it's kind-of
low impact. Such streams allow denial of service anyway.
Diffstat (limited to 'pb_decode.c')
-rw-r--r-- | pb_decode.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/pb_decode.c b/pb_decode.c index f16837b..f936412 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -670,12 +670,25 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_ while (substream.bytes_left) { + if (*size == PB_SIZE_MAX) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + if ((size_t)*size + 1 > allocated_size) { /* Allocate more storage. This tries to guess the * number of remaining entries. Round the division * upwards. */ - allocated_size += (substream.bytes_left - 1) / field->data_size + 1; + size_t remain = (substream.bytes_left - 1) / field->data_size + 1; + if (remain < PB_SIZE_MAX - allocated_size) + allocated_size += remain; + else + allocated_size += 1; if (!allocate_field(&substream, field->pField, field->data_size, allocated_size)) { @@ -693,15 +706,6 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_ break; } - if (*size == PB_SIZE_MAX) - { -#ifndef PB_NO_ERRMSG - stream->errmsg = "too many array entries"; -#endif - status = false; - break; - } - (*size)++; } if (!pb_close_string_substream(stream, &substream)) |