X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FVarint.h;h=a9b9d0d6b63fb0c8f4744e20bc80dc113c6f8f92;hb=06fe0874f2c3a786c79695e5b20c5f4580e05115;hp=7ce9d301b25abb2b13030b0067aa8c9e50b641b8;hpb=546bd3f5f2ed1fdf3a0f5c2b6737a20c4bc2f561;p=folly.git diff --git a/folly/Varint.h b/folly/Varint.h index 7ce9d301..a9b9d0d6 100644 --- a/folly/Varint.h +++ b/folly/Varint.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2016 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,8 @@ #ifndef FOLLY_VARINT_H_ #define FOLLY_VARINT_H_ +#include +#include #include namespace folly { @@ -55,7 +57,8 @@ size_t encodeVarint(uint64_t val, uint8_t* buf); /** * Decode a value from a given buffer, advances data past the returned value. */ -uint64_t decodeVarint(ByteRange& data); +template +uint64_t decodeVarint(Range& data); /** * ZigZag encoding that maps signed integers with a small absolute value @@ -88,13 +91,20 @@ inline size_t encodeVarint(uint64_t val, uint8_t* buf) { return p - buf; } -inline uint64_t decodeVarint(ByteRange& data) { +template +inline uint64_t decodeVarint(Range& data) { + static_assert( + std::is_same::type, char>::value || + std::is_same::type, unsigned char>::value, + "Only character ranges are supported"); + const int8_t* begin = reinterpret_cast(data.begin()); const int8_t* end = reinterpret_cast(data.end()); const int8_t* p = begin; uint64_t val = 0; - if (LIKELY(end - begin >= kMaxVarintLength64)) { // fast path + // end is always greater than or equal to begin, so this subtraction is safe + if (LIKELY(size_t(end - begin) >= kMaxVarintLength64)) { // fast path int64_t b; do { b = *p++; val = (b & 0x7f) ; if (b >= 0) break; @@ -107,7 +117,7 @@ inline uint64_t decodeVarint(ByteRange& data) { b = *p++; val |= (b & 0x7f) << 49; if (b >= 0) break; b = *p++; val |= (b & 0x7f) << 56; if (b >= 0) break; b = *p++; val |= (b & 0x7f) << 63; if (b >= 0) break; - throw std::invalid_argument("Invalid varint value"); // too big + throw std::invalid_argument("Invalid varint value. Too big."); } while (false); } else { int shift = 0; @@ -115,7 +125,11 @@ inline uint64_t decodeVarint(ByteRange& data) { val |= static_cast(*p++ & 0x7f) << shift; shift += 7; } - if (p == end) throw std::invalid_argument("Invalid varint value"); + if (p == end) { + throw std::invalid_argument("Invalid varint value. Too small: " + + folly::to(end - begin) + + " bytes"); + } val |= static_cast(*p++) << shift; }