Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(804)

Unified Diff: components/safe_browsing_db/v4_rice.cc

Issue 2183433002: PVer4: RICE decode bytes to list of uint32 or 4-byte hash prefixes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/RICE/Rice and use safe-math to check integer overflow Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/safe_browsing_db/v4_rice.h ('k') | components/safe_browsing_db/v4_rice_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/safe_browsing_db/v4_rice.cc
diff --git a/components/safe_browsing_db/v4_rice.cc b/components/safe_browsing_db/v4_rice.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b053715083be4305b43e763eb4eb7c8b8ffcc7fa
--- /dev/null
+++ b/components/safe_browsing_db/v4_rice.cc
@@ -0,0 +1,275 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/numerics/safe_math.h"
+#include "base/strings/stringprintf.h"
+#include "components/safe_browsing_db/v4_rice.h"
+
+using ::google::protobuf::RepeatedField;
+using ::google::protobuf::int32;
+
+namespace safe_browsing {
+
+namespace {
+
+const unsigned int kMaxBitIndex = 8 * sizeof(uint32_t);
+
+void GetBytesFromUInt32(uint32_t word, char* bytes) {
+ const size_t mask = 0xFF;
+ bytes[0] = (char)(word & mask);
+ bytes[1] = (char)((word >> 8) & mask);
+ bytes[2] = (char)((word >> 16) & mask);
+ bytes[3] = (char)((word >> 24) & mask);
+}
+
+} // namespace
+
+// static
+V4DecodeResult V4RiceDecoder::ValidateInput(const int32 rice_parameter,
+ const int32 num_entries,
+ const std::string& encoded_data) {
+ if (num_entries < 0) {
+ NOTREACHED();
+ return NUM_ENTRIES_NEGATIVE_FAILURE;
+ }
+
+ if (num_entries == 0) {
+ return DECODE_SUCCESS;
+ }
+
+ if (rice_parameter <= 0) {
+ NOTREACHED();
+ return RICE_PARAMETER_NON_POSITIVE_FAILURE;
+ }
+
+ if (encoded_data.empty()) {
+ NOTREACHED();
+ return ENCODED_DATA_UNEXPECTED_EMPTY_FAILURE;
+ }
+
+ return DECODE_SUCCESS;
+}
+
+// static
+V4DecodeResult V4RiceDecoder::DecodeIntegers(const int32 first_value,
+ const int32 rice_parameter,
+ const int32 num_entries,
+ const std::string& encoded_data,
+ RepeatedField<int32>* out) {
+ DCHECK(out);
+
+ V4DecodeResult result =
+ ValidateInput(rice_parameter, num_entries, encoded_data);
+ if (result != DECODE_SUCCESS) {
+ return result;
+ }
+
+ out->Reserve(num_entries + 1);
+ base::CheckedNumeric<int32> last_value(first_value);
+ out->Add(last_value.ValueOrDie());
+ if (num_entries == 0) {
+ return DECODE_SUCCESS;
+ }
+
+ V4RiceDecoder decoder(rice_parameter, num_entries, encoded_data);
+ while (decoder.HasAnotherValue()) {
+ uint32_t offset;
+ result = decoder.GetNextValue(&offset);
+ if (result != DECODE_SUCCESS) {
+ return result;
+ }
+
+ last_value += offset;
+ if (!last_value.IsValid()) {
+ NOTREACHED();
+ return DECODED_INTEGER_OVERFLOW_FAILURE;
+ }
+
+ out->Add(last_value.ValueOrDie());
+ }
+
+ return DECODE_SUCCESS;
+}
+
+// static
+V4DecodeResult V4RiceDecoder::DecodeBytes(const int32 first_value,
+ const int32 rice_parameter,
+ const int32 num_entries,
+ const std::string& encoded_data,
+ std::string* out) {
+ DCHECK(out);
+
+ V4DecodeResult result =
+ ValidateInput(rice_parameter, num_entries, encoded_data);
+ if (result != DECODE_SUCCESS) {
+ return result;
+ }
+
+ out->reserve((num_entries + 1) * 4);
+ char bytes[4];
+ base::CheckedNumeric<uint32_t> last_value(first_value);
+ GetBytesFromUInt32(last_value.ValueOrDie(), bytes);
+ out->append(bytes, 4);
+
+ if (num_entries == 0) {
+ return DECODE_SUCCESS;
+ }
+
+ V4RiceDecoder decoder(rice_parameter, num_entries, encoded_data);
+ while (decoder.HasAnotherValue()) {
+ uint32_t offset;
+ result = decoder.GetNextValue(&offset);
+ if (result != DECODE_SUCCESS) {
+ return result;
+ }
+
+ last_value += offset;
+ if (!last_value.IsValid()) {
+ NOTREACHED();
+ return DECODED_INTEGER_OVERFLOW_FAILURE;
+ }
+
+ GetBytesFromUInt32(last_value.ValueOrDie(), bytes);
+ out->append(bytes, 4);
+ }
+
+ return DECODE_SUCCESS;
+}
+
+V4RiceDecoder::V4RiceDecoder(const int rice_parameter,
+ const int num_entries,
+ const std::string& encoded_data)
+ : rice_parameter_(rice_parameter),
+ num_entries_(num_entries),
+ data_(encoded_data),
+ current_word_(0) {
+ DCHECK_LE(0, num_entries_);
+ DCHECK_LE(2u, rice_parameter_);
+ DCHECK_GE(28u, rice_parameter_);
+
+ data_byte_index_ = 0;
+ current_word_bit_index_ = kMaxBitIndex;
+}
+
+V4RiceDecoder::~V4RiceDecoder() {}
+
+bool V4RiceDecoder::HasAnotherValue() const {
+ return num_entries_ > 0;
+}
+
+V4DecodeResult V4RiceDecoder::GetNextValue(uint32_t* value) {
+ if (!HasAnotherValue()) {
+ return DECODE_NO_MORE_ENTRIES_FAILURE;
+ }
+
+ V4DecodeResult result;
+ uint32_t q = 0;
+ uint32_t bit;
+ do {
+ result = GetNextBits(1, &bit);
+ if (result != DECODE_SUCCESS) {
+ return result;
+ }
+ q += bit;
+ } while (bit);
+ uint32_t r = 0;
+ result = GetNextBits(rice_parameter_, &r);
+ if (result != DECODE_SUCCESS) {
+ return result;
+ }
+
+ *value = (q << rice_parameter_) + r;
+ num_entries_--;
+ return DECODE_SUCCESS;
+}
+
+V4DecodeResult V4RiceDecoder::GetNextWord(uint32_t* word) {
+ if (data_byte_index_ >= data_.size()) {
+ return DECODE_RAN_OUT_OF_BITS_FAILURE;
+ }
+
+ const size_t mask = 0xFF;
+ *word = (data_[data_byte_index_] & mask);
+ data_byte_index_++;
+ current_word_bit_index_ = 0;
+
+ if (data_byte_index_ < data_.size()) {
+ *word |= ((data_[data_byte_index_] & mask) << 8);
+ data_byte_index_++;
+
+ if (data_byte_index_ < data_.size()) {
+ *word |= ((data_[data_byte_index_] & mask) << 16);
+ data_byte_index_++;
+
+ if (data_byte_index_ < data_.size()) {
+ *word |= ((data_[data_byte_index_] & mask) << 24);
+ data_byte_index_++;
+ }
+ }
+ }
+
+ return DECODE_SUCCESS;
+}
+
+V4DecodeResult V4RiceDecoder::GetNextBits(unsigned int num_requested_bits,
+ uint32_t* x) {
+ if (num_requested_bits > kMaxBitIndex) {
+ NOTREACHED();
+ return DECODE_REQUESTED_TOO_MANY_BITS_FAILURE;
+ }
+
+ if (current_word_bit_index_ == kMaxBitIndex) {
+ V4DecodeResult result = GetNextWord(&current_word_);
+ if (result != DECODE_SUCCESS) {
+ return result;
+ }
+ }
+
+ unsigned int num_bits_left_in_current_word =
+ kMaxBitIndex - current_word_bit_index_;
+ if (num_bits_left_in_current_word >= num_requested_bits) {
+ // All the bits that we need are in |current_word_|.
+ GetBitsFromCurrentWord(num_requested_bits, x);
+ } else {
+ // |current_word_| contains fewer bits than we need so we store the current
+ // value of |current_word_| in |lower|, then read in a new |current_word_|,
+ // and then pick the remaining bits from the new value of |current_word_|.
+ uint32_t lower = current_word_;
+ // Bits we need after we read all of |current_word_|
+ unsigned int num_bits_from_next_word =
+ num_requested_bits - num_bits_left_in_current_word;
+ uint32_t upper;
+ V4DecodeResult result = GetNextWord(&current_word_);
+ if (result != DECODE_SUCCESS) {
+ return result;
+ }
+ GetBitsFromCurrentWord(num_bits_from_next_word, &upper);
+ *x = (upper << (num_requested_bits - num_bits_from_next_word)) | lower;
+ }
+ return DECODE_SUCCESS;
+}
+
+void V4RiceDecoder::GetBitsFromCurrentWord(unsigned int num_requested_bits,
+ uint32_t* x) {
+ uint32_t mask = 0xFFFFFFFF >> (kMaxBitIndex - num_requested_bits);
+ *x = current_word_ & mask;
+ current_word_ = current_word_ >> num_requested_bits;
+ current_word_bit_index_ += num_requested_bits;
+};
+
+std::string V4RiceDecoder::DebugString() const {
+ return base::StringPrintf(
+ "current_word_: %x; data_byte_index_; %x, "
+ "current_word_bit_index_: %x; rice_parameter_: %x",
+ current_word_, data_byte_index_, current_word_bit_index_,
+ rice_parameter_);
+}
+
+std::ostream& operator<<(std::ostream& os, const V4RiceDecoder& rice_decoder) {
+ os << rice_decoder.DebugString();
+ return os;
+}
+
+} // namespace safe_browsing
« no previous file with comments | « components/safe_browsing_db/v4_rice.h ('k') | components/safe_browsing_db/v4_rice_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698