diff options
author | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2012-10-18 19:45:28 +0300 |
---|---|---|
committer | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2012-10-18 19:45:28 +0300 |
commit | dcab39a41c0a403db38860c22426075e6ae9f25d (patch) | |
tree | 7f1824628371ec59353b0765a209e6e5518401f7 /pb_decode.c | |
parent | 900c8dd1252afe2b2474b852ae48dcb46e100505 (diff) |
Remove the "buf = NULL" => skip requirement from pb_istream_t callbacks.
Rationale: it's easy to implement the callback wrong. Doing so introduces
io errors when unknown fields are present in the input. If code is not
tested with unknown fields, these bugs can remain hidden for long time.
Added a special case for the memory buffer stream, where it gives a small
speed benefit.
Added testcase for skipping fields with test_decode2 implementation.
Update issue 37
Status: FixedInGit
Diffstat (limited to 'pb_decode.c')
-rw-r--r-- | pb_decode.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/pb_decode.c b/pb_decode.c index 86dec4b7..8e01fd7a 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -36,26 +36,41 @@ static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { * pb_istream * **************/ -bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count) +static bool checkreturn buf_read(pb_istream_t *stream, uint8_t *buf, size_t count) { - if (stream->bytes_left < count) - PB_RETURN_ERROR(stream, "end-of-stream"); + uint8_t *source = (uint8_t*)stream->state; - if (!stream->callback(stream, buf, count)) - PB_RETURN_ERROR(stream, "io error"); + if (buf != NULL) + memcpy(buf, source, count); - stream->bytes_left -= count; + stream->state = source + count; return true; } -static bool checkreturn buf_read(pb_istream_t *stream, uint8_t *buf, size_t count) +bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count) { - uint8_t *source = (uint8_t*)stream->state; + if (buf == NULL && stream->callback != buf_read) + { + /* Skip input bytes */ + uint8_t tmp[16]; + while (count > 16) + { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); - if (buf != NULL) - memcpy(buf, source, count); + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); - stream->state = source + count; + stream->bytes_left -= count; return true; } |