diff --git a/Makefile b/Makefile index 5dbbecede3..b22196c3b8 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,11 @@ .PHONY: all clean -all: pbstream.o +all: pbstream.o tests clean: - rm -f pbstream.o + rm -f pbstream.o tests -pbstream.o: pbstream.c +pbstream.o: pbstream.c pbstream.h gcc -std=c99 -O3 -Wall -o pbstream.o -c pbstream.c + +tests: tests.c pbstream.c pbstream.h + gcc -std=c99 -O3 -Wall -o tests tests.c diff --git a/pbstream.c b/pbstream.c index bc25c975b5..991be7fa51 100644 --- a/pbstream.c +++ b/pbstream.c @@ -51,7 +51,13 @@ enum pbstream_status get_varint(char **buf, char *end, uint64_t *out_value) * that callers use a buffer that is overallocated by at least 9 bytes * (the maximum we can overrun before the bitpos check catches the problem). */ for(; *b & 0x80 && bitpos < 64; bitpos += 7, b++) - *out_value |= (*b & 0x7F) << bitpos; + *out_value |= (uint64_t)(*b & 0x7F) << bitpos; + + /* If bitpos is 63 (as it will be if this was a nine-byte varint) this will + * throw away the middle six bits of the final byte. We don't bother warning + * about this. */ + *out_value |= (uint64_t)(*b & 0x7F) << bitpos; + b++; if(unlikely(bitpos >= 64)) { return PBSTREAM_ERROR_UNTERMINATED_VARINT; @@ -60,7 +66,6 @@ enum pbstream_status get_varint(char **buf, char *end, uint64_t *out_value) return PBSTREAM_STATUS_INCOMPLETE; } - *out_value |= (*b & 0x7F) << bitpos; *buf = b; return PBSTREAM_STATUS_OK; } @@ -102,14 +107,14 @@ bool get_64_le(char **buf, char *end, uint64_t *out_value) return PBSTREAM_STATUS_OK; } -int32_t zigzag_decode_32(uint64_t n) +int32_t zigzag_decode_32(uint32_t n) { return (n >> 1) ^ -(int32_t)(n & 1); } int64_t zigzag_decode_64(uint64_t n) { - return (n >> 1) ^ (int64_t)(n & 1); + return (n >> 1) ^ -(int64_t)(n & 1); } /* Parses the next field-number/wire-value pair from the stream of bytes