summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pb_decode.c15
-rw-r--r--tests/decode_unittests/decode_unittests.c48
2 files changed, 58 insertions, 5 deletions
diff --git a/pb_decode.c b/pb_decode.c
index e2e90caa..06d766af 100644
--- a/pb_decode.c
+++ b/pb_decode.c
@@ -934,6 +934,9 @@ bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[
if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0)
req_field_count++;
+ if (req_field_count > PB_MAX_REQUIRED_FIELDS)
+ req_field_count = PB_MAX_REQUIRED_FIELDS;
+
if (req_field_count > 0)
{
/* Check the whole words */
@@ -943,9 +946,15 @@ bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[
PB_RETURN_ERROR(stream, "missing required field");
}
- /* Check the remaining bits */
- if (fields_seen[req_field_count >> 5] != (allbits >> (32 - (req_field_count & 31))))
- PB_RETURN_ERROR(stream, "missing required field");
+ /* Check the remaining bits (if any) */
+ if ((req_field_count & 31) != 0)
+ {
+ if (fields_seen[req_field_count >> 5] !=
+ (allbits >> (32 - (req_field_count & 31))))
+ {
+ PB_RETURN_ERROR(stream, "missing required field");
+ }
+ }
}
}
diff --git a/tests/decode_unittests/decode_unittests.c b/tests/decode_unittests/decode_unittests.c
index 47f0fbdb..a6f5c17e 100644
--- a/tests/decode_unittests/decode_unittests.c
+++ b/tests/decode_unittests/decode_unittests.c
@@ -150,9 +150,9 @@ int main()
{
pb_istream_t s;
pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 8, 0, 0};
- uint64_t d;
+ int64_t d;
- COMMENT("Test pb_dec_svarint using uint64_t")
+ COMMENT("Test pb_dec_svarint using int64_t")
TEST((s = S("\x01"), pb_dec_svarint(&s, &f, &d) && d == -1))
TEST((s = S("\x02"), pb_dec_svarint(&s, &f, &d) && d == 1))
TEST((s = S("\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_svarint(&s, &f, &d) && d == INT64_MAX))
@@ -161,6 +161,50 @@ int main()
{
pb_istream_t s;
+ pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 4, 0, 0};
+ int32_t d;
+
+ COMMENT("Test pb_dec_svarint overflow detection using int32_t");
+ TEST((s = S("\xfe\xff\xff\xff\x0f"), pb_dec_svarint(&s, &f, &d)));
+ TEST((s = S("\xfe\xff\xff\xff\x10"), !pb_dec_svarint(&s, &f, &d)));
+ TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_svarint(&s, &f, &d)));
+ TEST((s = S("\xff\xff\xff\xff\x10"), !pb_dec_svarint(&s, &f, &d)));
+ }
+
+ {
+ pb_istream_t s;
+ pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 4, 0, 0};
+ uint32_t d;
+
+ COMMENT("Test pb_dec_uvarint using uint32_t")
+ TEST((s = S("\x01"), pb_dec_uvarint(&s, &f, &d) && d == 1))
+ TEST((s = S("\x02"), pb_dec_uvarint(&s, &f, &d) && d == 2))
+ TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_uvarint(&s, &f, &d) && d == UINT32_MAX))
+ }
+
+ {
+ pb_istream_t s;
+ pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 8, 0, 0};
+ uint64_t d;
+
+ COMMENT("Test pb_dec_uvarint using uint64_t")
+ TEST((s = S("\x01"), pb_dec_uvarint(&s, &f, &d) && d == 1))
+ TEST((s = S("\x02"), pb_dec_uvarint(&s, &f, &d) && d == 2))
+ TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_uvarint(&s, &f, &d) && d == UINT64_MAX))
+ }
+
+ {
+ pb_istream_t s;
+ pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 4, 0, 0};
+ uint32_t d;
+
+ COMMENT("Test pb_dec_uvarint overflow detection using int32_t");
+ TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_uvarint(&s, &f, &d)));
+ TEST((s = S("\xff\xff\xff\xff\x10"), !pb_dec_uvarint(&s, &f, &d)));
+ }
+
+ {
+ pb_istream_t s;
pb_field_t f = {1, PB_LTYPE_FIXED32, 0, 0, 4, 0, 0};
float d;