Merge remote-tracking branch 'cros/upstream/main'

Related changes:
70ef0c25 Rewrite most `Foo* field_` pointer fields to `raw_ptr<Foo> field_`.
701da4c2 cbor: Add allow_and_canonicalize_out_of_order_keys flag
6ab897e9 Remove unused "base/macros.h" in components/
fb311d5b Replace DISALLOW_COPY_AND_ASSIGN in components/
a063c268 Swap from base/stl_util.h to cxx17_backports.h in components/ .cc files.
9d6c30f5 Remove unneeded base/stl_util.h includes in components/ and ui/.
0f45c2c3 components: Replace base::Optional and friends with absl counterparts
9567ac5b Delete unused STL includes from components/ headers.
8370d502 [base] Remove base::StringPiece::as_string() usages.
9ebffe85 Added DIR_METADATA files to a batch of subfolders in //components/c...
         and also removed duplicated metadata from OWNERS files
da40ce6b Remove/replace unnecessary includes of logging.h (components/)

BUG=chromium:1271599
BUG=b:204698553
BUG=b:198296022
TEST=cros_run_unit_tests --board=${BOARD} --packages cbor

Change-Id: I8d2601b151ac76edef08c9813ffc79ae22c228ce
diff --git a/DIR_METADATA b/DIR_METADATA
new file mode 100644
index 0000000..566b704
--- /dev/null
+++ b/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+  component: "Blink>WebAuthentication"
+}
+
+team_email: "security-dev@chromium.org"
diff --git a/diagnostic_writer_unittest.cc b/diagnostic_writer_unittest.cc
index 4569cf7..8ae39ef 100644
--- a/diagnostic_writer_unittest.cc
+++ b/diagnostic_writer_unittest.cc
@@ -64,7 +64,7 @@
   static const uint8_t kInvalidUTF8[] = {0x62, 0xe2, 0x80};
   cbor::Reader::Config config;
   config.allow_invalid_utf8 = true;
-  base::Optional<cbor::Value> maybe_value =
+  absl::optional<cbor::Value> maybe_value =
       cbor::Reader::Read(kInvalidUTF8, config);
 
   ASSERT_TRUE(maybe_value);
diff --git a/reader.cc b/reader.cc
index f256bf5..dcfb217 100644
--- a/reader.cc
+++ b/reader.cc
@@ -6,13 +6,13 @@
 
 #include <math.h>
 
+#include <map>
 #include <utility>
 
 #include "base/check_op.h"
 #include "base/notreached.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "cbor/constants.h"
 
@@ -59,6 +59,7 @@
     "Floating point numbers are not supported.";
 const char kOutOfRangeIntegerValue[] =
     "Integer values must be between INT64_MIN and INT64_MAX.";
+const char kMapKeyDuplicate[] = "Duplicate map keys are not allowed.";
 const char kUnknownError[] = "An unknown error occured.";
 
 }  // namespace
@@ -71,7 +72,7 @@
 Reader::~Reader() {}
 
 // static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
+absl::optional<Value> Reader::Read(base::span<uint8_t const> data,
                                    DecoderError* error_code_out,
                                    int max_nesting_level) {
   Config config;
@@ -82,7 +83,7 @@
 }
 
 // static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
+absl::optional<Value> Reader::Read(base::span<uint8_t const> data,
                                    size_t* num_bytes_consumed,
                                    DecoderError* error_code_out,
                                    int max_nesting_level) {
@@ -97,10 +98,10 @@
 }
 
 // static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
+absl::optional<Value> Reader::Read(base::span<uint8_t const> data,
                                    const Config& config) {
   Reader reader(data);
-  base::Optional<Value> value =
+  absl::optional<Value> value =
       reader.DecodeCompleteDataItem(config, config.max_nesting_level);
 
   auto error = reader.GetErrorCode();
@@ -122,16 +123,16 @@
   return value;
 }
 
-base::Optional<Value> Reader::DecodeCompleteDataItem(const Config& config,
+absl::optional<Value> Reader::DecodeCompleteDataItem(const Config& config,
                                                      int max_nesting_level) {
   if (max_nesting_level < 0 || max_nesting_level > kCBORMaxDepth) {
     error_code_ = DecoderError::TOO_MUCH_NESTING;
-    return base::nullopt;
+    return absl::nullopt;
   }
 
-  base::Optional<DataItemHeader> header = DecodeDataItemHeader();
+  absl::optional<DataItemHeader> header = DecodeDataItemHeader();
   if (!header.has_value()) {
-    return base::nullopt;
+    return absl::nullopt;
   }
 
   switch (header->type) {
@@ -156,29 +157,29 @@
   }
 
   error_code_ = DecoderError::UNSUPPORTED_MAJOR_TYPE;
-  return base::nullopt;
+  return absl::nullopt;
 }
 
-base::Optional<Reader::DataItemHeader> Reader::DecodeDataItemHeader() {
-  const base::Optional<uint8_t> initial_byte = ReadByte();
+absl::optional<Reader::DataItemHeader> Reader::DecodeDataItemHeader() {
+  const absl::optional<uint8_t> initial_byte = ReadByte();
   if (!initial_byte) {
-    return base::nullopt;
+    return absl::nullopt;
   }
 
   const auto major_type = GetMajorType(initial_byte.value());
   const uint8_t additional_info = GetAdditionalInfo(initial_byte.value());
 
-  base::Optional<uint64_t> value = ReadVariadicLengthInteger(additional_info);
-  return value ? base::make_optional(
+  absl::optional<uint64_t> value = ReadVariadicLengthInteger(additional_info);
+  return value ? absl::make_optional(
                      DataItemHeader{major_type, additional_info, value.value()})
-               : base::nullopt;
+               : absl::nullopt;
 }
 
-base::Optional<uint64_t> Reader::ReadVariadicLengthInteger(
+absl::optional<uint64_t> Reader::ReadVariadicLengthInteger(
     uint8_t additional_info) {
   uint8_t additional_bytes = 0;
   if (additional_info < 24) {
-    return base::make_optional(additional_info);
+    return absl::make_optional(additional_info);
   } else if (additional_info == 24) {
     additional_bytes = 1;
   } else if (additional_info == 25) {
@@ -189,13 +190,13 @@
     additional_bytes = 8;
   } else {
     error_code_ = DecoderError::UNKNOWN_ADDITIONAL_INFO;
-    return base::nullopt;
+    return absl::nullopt;
   }
 
-  const base::Optional<base::span<const uint8_t>> bytes =
+  const absl::optional<base::span<const uint8_t>> bytes =
       ReadBytes(additional_bytes);
   if (!bytes) {
-    return base::nullopt;
+    return absl::nullopt;
   }
 
   uint64_t int_data = 0;
@@ -205,36 +206,36 @@
   }
 
   return IsEncodingMinimal(additional_bytes, int_data)
-             ? base::make_optional(int_data)
-             : base::nullopt;
+             ? absl::make_optional(int_data)
+             : absl::nullopt;
 }
 
-base::Optional<Value> Reader::DecodeValueToNegative(uint64_t value) {
+absl::optional<Value> Reader::DecodeValueToNegative(uint64_t value) {
   auto negative_value = -base::CheckedNumeric<int64_t>(value) - 1;
   if (!negative_value.IsValid()) {
     error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
-    return base::nullopt;
+    return absl::nullopt;
   }
   return Value(negative_value.ValueOrDie());
 }
 
-base::Optional<Value> Reader::DecodeValueToUnsigned(uint64_t value) {
+absl::optional<Value> Reader::DecodeValueToUnsigned(uint64_t value) {
   auto unsigned_value = base::CheckedNumeric<int64_t>(value);
   if (!unsigned_value.IsValid()) {
     error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
-    return base::nullopt;
+    return absl::nullopt;
   }
   return Value(unsigned_value.ValueOrDie());
 }
 
-base::Optional<Value> Reader::DecodeToSimpleValue(
+absl::optional<Value> Reader::DecodeToSimpleValue(
     const DataItemHeader& header) {
   // ReadVariadicLengthInteger provides this bound.
   CHECK_LE(header.additional_info, 27);
   // Floating point numbers are not supported.
   if (header.additional_info > 24) {
     error_code_ = DecoderError::UNSUPPORTED_FLOATING_POINT_VALUE;
-    return base::nullopt;
+    return absl::nullopt;
   }
 
   // Since |header.additional_info| <= 24, ReadVariadicLengthInteger also
@@ -253,16 +254,16 @@
   }
 
   error_code_ = DecoderError::UNSUPPORTED_SIMPLE_VALUE;
-  return base::nullopt;
+  return absl::nullopt;
 }
 
-base::Optional<Value> Reader::ReadStringContent(
+absl::optional<Value> Reader::ReadStringContent(
     const Reader::DataItemHeader& header,
     const Config& config) {
   uint64_t num_bytes = header.value;
-  const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
+  const absl::optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
   if (!bytes) {
-    return base::nullopt;
+    return absl::nullopt;
   }
 
   std::string cbor_string(bytes->begin(), bytes->end());
@@ -275,22 +276,22 @@
   }
 
   error_code_ = DecoderError::INVALID_UTF8;
-  return base::nullopt;
+  return absl::nullopt;
 }
 
-base::Optional<Value> Reader::ReadByteStringContent(
+absl::optional<Value> Reader::ReadByteStringContent(
     const Reader::DataItemHeader& header) {
   uint64_t num_bytes = header.value;
-  const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
+  const absl::optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
   if (!bytes) {
-    return base::nullopt;
+    return absl::nullopt;
   }
 
   std::vector<uint8_t> cbor_byte_string(bytes->begin(), bytes->end());
   return Value(std::move(cbor_byte_string));
 }
 
-base::Optional<Value> Reader::ReadArrayContent(
+absl::optional<Value> Reader::ReadArrayContent(
     const Reader::DataItemHeader& header,
     const Config& config,
     int max_nesting_level) {
@@ -298,30 +299,30 @@
 
   Value::ArrayValue cbor_array;
   for (uint64_t i = 0; i < length; ++i) {
-    base::Optional<Value> cbor_element =
+    absl::optional<Value> cbor_element =
         DecodeCompleteDataItem(config, max_nesting_level - 1);
     if (!cbor_element.has_value()) {
-      return base::nullopt;
+      return absl::nullopt;
     }
     cbor_array.push_back(std::move(cbor_element.value()));
   }
   return Value(std::move(cbor_array));
 }
 
-base::Optional<Value> Reader::ReadMapContent(
+absl::optional<Value> Reader::ReadMapContent(
     const Reader::DataItemHeader& header,
     const Config& config,
     int max_nesting_level) {
   const uint64_t length = header.value;
 
-  Value::MapValue cbor_map;
+  std::map<Value, Value, Value::Less> cbor_map;
   for (uint64_t i = 0; i < length; ++i) {
-    base::Optional<Value> key =
+    absl::optional<Value> key =
         DecodeCompleteDataItem(config, max_nesting_level - 1);
-    base::Optional<Value> value =
+    absl::optional<Value> value =
         DecodeCompleteDataItem(config, max_nesting_level - 1);
     if (!key.has_value() || !value.has_value()) {
-      return base::nullopt;
+      return absl::nullopt;
     }
 
     switch (key.value().type()) {
@@ -332,30 +333,41 @@
         break;
       case Value::Type::INVALID_UTF8:
         error_code_ = DecoderError::INVALID_UTF8;
-        return base::nullopt;
+        return absl::nullopt;
       default:
         error_code_ = DecoderError::INCORRECT_MAP_KEY_TYPE;
-        return base::nullopt;
+        return absl::nullopt;
     }
-    if (!IsKeyInOrder(key.value(), &cbor_map)) {
-      return base::nullopt;
+    if (IsDuplicateKey(key.value(), cbor_map))
+      return absl::nullopt;
+
+    if (!config.allow_and_canonicalize_out_of_order_keys &&
+        !IsKeyInOrder(key.value(), cbor_map)) {
+      return absl::nullopt;
     }
 
-    cbor_map.insert_or_assign(std::move(key.value()), std::move(value.value()));
+    cbor_map.emplace(std::move(key.value()), std::move(value.value()));
   }
-  return Value(std::move(cbor_map));
+
+  Value::MapValue map;
+  map.reserve(cbor_map.size());
+  // TODO(crbug/1271599): when Chromium switches to C++17, this code can be
+  // optimized using std::map::extract().
+  for (auto& it : cbor_map)
+    map.emplace_hint(map.end(), it.first.Clone(), std::move(it.second));
+  return Value(std::move(map));
 }
 
-base::Optional<uint8_t> Reader::ReadByte() {
-  const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(1);
-  return bytes ? base::make_optional(bytes.value()[0]) : base::nullopt;
+absl::optional<uint8_t> Reader::ReadByte() {
+  const absl::optional<base::span<const uint8_t>> bytes = ReadBytes(1);
+  return bytes ? absl::make_optional(bytes.value()[0]) : absl::nullopt;
 }
 
-base::Optional<base::span<const uint8_t>> Reader::ReadBytes(
+absl::optional<base::span<const uint8_t>> Reader::ReadBytes(
     uint64_t num_bytes) {
   if (base::strict_cast<uint64_t>(rest_.size()) < num_bytes) {
     error_code_ = DecoderError::INCOMPLETE_CBOR_DATA;
-    return base::nullopt;
+    return absl::nullopt;
   }
   const base::span<const uint8_t> ret = rest_.first(num_bytes);
   rest_ = rest_.subspan(num_bytes);
@@ -371,13 +383,14 @@
   return true;
 }
 
-bool Reader::IsKeyInOrder(const Value& new_key, Value::MapValue* map) {
-  if (map->empty()) {
+bool Reader::IsKeyInOrder(const Value& new_key,
+                          const std::map<Value, Value, Value::Less>& map) {
+  if (map.empty()) {
     return true;
   }
 
-  const auto& max_current_key = map->rbegin()->first;
-  const auto less = map->key_comp();
+  const auto& max_current_key = map.rbegin()->first;
+  const auto less = map.key_comp();
   if (!less(max_current_key, new_key)) {
     error_code_ = DecoderError::OUT_OF_ORDER_KEY;
     return false;
@@ -385,6 +398,15 @@
   return true;
 }
 
+bool Reader::IsDuplicateKey(const Value& new_key,
+                            const std::map<Value, Value, Value::Less>& map) {
+  if (map.find(new_key) == map.end()) {
+    return false;
+  }
+  error_code_ = DecoderError::DUPLICATE_KEY;
+  return true;
+}
+
 // static
 const char* Reader::ErrorCodeToString(DecoderError error) {
   switch (error) {
@@ -414,6 +436,8 @@
       return kUnsupportedFloatingPointValue;
     case DecoderError::OUT_OF_RANGE_INTEGER_VALUE:
       return kOutOfRangeIntegerValue;
+    case DecoderError::DUPLICATE_KEY:
+      return kMapKeyDuplicate;
     case DecoderError::UNKNOWN_ERROR:
       return kUnknownError;
     default:
diff --git a/reader.h b/reader.h
index 6c8ec12..632039b 100644
--- a/reader.h
+++ b/reader.h
@@ -7,13 +7,13 @@
 
 #include <stddef.h>
 
-#include <string>
-#include <vector>
+#include <map>
 
 #include "base/containers/span.h"
-#include "base/optional.h"
+#include "base/memory/raw_ptr.h"
 #include "cbor/cbor_export.h"
 #include "cbor/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // Concise Binary Object Representation (CBOR) decoder as defined by
 // https://tools.ietf.org/html/rfc7049. This decoder only accepts canonical CBOR
@@ -35,7 +35,7 @@
 // Requirements for canonical CBOR representation:
 //  - Duplicate keys in maps are not allowed.
 //  - Keys for maps must be sorted first by length and then by byte-wise
-//    lexical order.
+//    lexical order, as defined in Section 3.9.
 //
 // Known limitations and interpretations of the RFC (and the reasons):
 //  - Does not support indefinite-length data streams or semantic tags (major
@@ -73,6 +73,7 @@
     UNSUPPORTED_SIMPLE_VALUE,
     UNSUPPORTED_FLOATING_POINT_VALUE,
     OUT_OF_RANGE_INTEGER_VALUE,
+    DUPLICATE_KEY,
     UNKNOWN_ERROR,
   };
 
@@ -82,15 +83,19 @@
   // Config contains configuration for a CBOR parsing operation.
   struct CBOR_EXPORT Config {
     Config();
+
+    Config(const Config&) = delete;
+    Config& operator=(const Config&) = delete;
+
     ~Config();
 
     // Used to report the number of bytes of input consumed. This suppresses the
     // |EXTRANEOUS_DATA| error case. May be nullptr.
-    size_t* num_bytes_consumed = nullptr;
+    raw_ptr<size_t> num_bytes_consumed = nullptr;
 
     // Used to report the specific error in the case that parsing fails. May be
     // nullptr;
-    DecoderError* error_code_out = nullptr;
+    raw_ptr<DecoderError> error_code_out = nullptr;
 
     // Controls the maximum depth of CBOR nesting that will be permitted. This
     // exists to control stack consumption during parsing.
@@ -107,10 +112,22 @@
     // correctly.)
     bool allow_invalid_utf8 = false;
 
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Config);
+    // Causes an input to be accepted even if it contains one or more maps with
+    // keys that are not in the canonical ordering as defined in Section 3.9,
+    // and suppresses the OUT_OF_ORDER_KEY error. The original ordering of keys
+    // will _not_ be preserved, but instead, in the returned cbor::Value, all
+    // maps are re-sorted so that their keys are in canonical order. By
+    // definition, enabling this option may result in loss of information (i.e.
+    // the original key ordering).
+    //
+    // Enabling this option will still not allow duplicate keys, in case of
+    // which the DUPLICATE_KEY error will be emitted.
+    bool allow_and_canonicalize_out_of_order_keys = false;
   };
 
+  Reader(const Reader&) = delete;
+  Reader& operator=(const Reader&) = delete;
+
   ~Reader();
 
   // Reads and parses |input_data| into a Value. Returns an empty Optional
@@ -125,18 +142,18 @@
   //
   // Returns an empty Optional if not all the data was consumed, and sets
   // |error_code_out| to EXTRANEOUS_DATA in this case.
-  static base::Optional<Value> Read(base::span<const uint8_t> input_data,
+  static absl::optional<Value> Read(base::span<const uint8_t> input_data,
                                     DecoderError* error_code_out = nullptr,
                                     int max_nesting_level = kCBORMaxDepth);
 
   // A version of |Read|, above, that takes a |Config| structure to allow
   // additional controls.
-  static base::Optional<Value> Read(base::span<const uint8_t> input_data,
+  static absl::optional<Value> Read(base::span<const uint8_t> input_data,
                                     const Config& config);
 
   // A version of |Read| that takes some fields of |Config| as parameters to
   // avoid having to construct a |Config| object explicitly.
-  static base::Optional<Value> Read(base::span<const uint8_t> input_data,
+  static absl::optional<Value> Read(base::span<const uint8_t> input_data,
                                     size_t* num_bytes_consumed,
                                     DecoderError* error_code_out = nullptr,
                                     int max_nesting_level = kCBORMaxDepth);
@@ -162,25 +179,30 @@
     uint64_t value;
   };
 
-  base::Optional<DataItemHeader> DecodeDataItemHeader();
-  base::Optional<Value> DecodeCompleteDataItem(const Config& config,
+  absl::optional<DataItemHeader> DecodeDataItemHeader();
+  absl::optional<Value> DecodeCompleteDataItem(const Config& config,
                                                int max_nesting_level);
-  base::Optional<Value> DecodeValueToNegative(uint64_t value);
-  base::Optional<Value> DecodeValueToUnsigned(uint64_t value);
-  base::Optional<Value> DecodeToSimpleValue(const DataItemHeader& header);
-  base::Optional<uint64_t> ReadVariadicLengthInteger(uint8_t additional_info);
-  base::Optional<Value> ReadByteStringContent(const DataItemHeader& header);
-  base::Optional<Value> ReadStringContent(const DataItemHeader& header,
+  absl::optional<Value> DecodeValueToNegative(uint64_t value);
+  absl::optional<Value> DecodeValueToUnsigned(uint64_t value);
+  absl::optional<Value> DecodeToSimpleValue(const DataItemHeader& header);
+  absl::optional<uint64_t> ReadVariadicLengthInteger(uint8_t additional_info);
+  absl::optional<Value> ReadByteStringContent(const DataItemHeader& header);
+  absl::optional<Value> ReadStringContent(const DataItemHeader& header,
                                           const Config& config);
-  base::Optional<Value> ReadArrayContent(const DataItemHeader& header,
+  absl::optional<Value> ReadArrayContent(const DataItemHeader& header,
                                          const Config& config,
                                          int max_nesting_level);
-  base::Optional<Value> ReadMapContent(const DataItemHeader& header,
+  absl::optional<Value> ReadMapContent(const DataItemHeader& header,
                                        const Config& config,
                                        int max_nesting_level);
-  base::Optional<uint8_t> ReadByte();
-  base::Optional<base::span<const uint8_t>> ReadBytes(uint64_t num_bytes);
-  bool IsKeyInOrder(const Value& new_key, Value::MapValue* map);
+  absl::optional<uint8_t> ReadByte();
+  absl::optional<base::span<const uint8_t>> ReadBytes(uint64_t num_bytes);
+  bool IsKeyInOrder(const Value& new_key,
+                    const std::map<Value, Value, Value::Less>& map);
+  // Check if `new_key` is a duplicate of a key that already exists in the
+  // `map`.
+  bool IsDuplicateKey(const Value& new_key,
+                      const std::map<Value, Value, Value::Less>& map);
   bool IsEncodingMinimal(uint8_t additional_bytes, uint64_t uint_data);
 
   DecoderError GetErrorCode() { return error_code_; }
@@ -189,8 +211,6 @@
 
   base::span<const uint8_t> rest_;
   DecoderError error_code_;
-
-  DISALLOW_COPY_AND_ASSIGN(Reader);
 };
 
 }  // namespace cbor
diff --git a/reader_fuzzer.cc b/reader_fuzzer.cc
index d344306..ae12767 100644
--- a/reader_fuzzer.cc
+++ b/reader_fuzzer.cc
@@ -12,10 +12,10 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   std::vector<uint8_t> input(data, data + size);
-  base::Optional<Value> cbor = Reader::Read(input);
 
+  absl::optional<Value> cbor = Reader::Read(input);
   if (cbor.has_value()) {
-    base::Optional<std::vector<uint8_t>> serialized_cbor =
+    absl::optional<std::vector<uint8_t>> serialized_cbor =
         Writer::Write(cbor.value());
     CHECK(serialized_cbor.has_value());
     if (serialized_cbor.has_value()) {
@@ -24,6 +24,20 @@
                    input.size()) == 0);
     }
   }
+
+  Reader::Config config;
+  config.allow_and_canonicalize_out_of_order_keys = true;
+  absl::optional<Value> cbor_1 = Reader::Read(input, config);
+
+  if (cbor_1.has_value()) {
+    absl::optional<std::vector<uint8_t>> serialized_cbor =
+        Writer::Write(cbor_1.value());
+    CHECK(serialized_cbor.has_value());
+    if (serialized_cbor.has_value()) {
+      CHECK(serialized_cbor.value().size() == input.size());
+    }
+  }
+
   return 0;
 }
 
diff --git a/reader_unittest.cc b/reader_unittest.cc
index 39a3143..285c48a 100644
--- a/reader_unittest.cc
+++ b/reader_unittest.cc
@@ -8,7 +8,7 @@
 #include "cbor/reader.h"
 
 #include "base/containers/span.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -52,7 +52,7 @@
   for (const UintTestCase& test_case : kUintTestCases) {
     SCOPED_TRACE(testing::Message() << "testing uint: " << test_case.value);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::UNSIGNED);
     EXPECT_EQ(cbor.value().GetInteger(), test_case.value);
@@ -117,7 +117,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing element at index : " << test_case_index++);
 
-    base::Optional<Value> cbor = Reader::Read(non_minimal_uint, &error_code);
+    absl::optional<Value> cbor = Reader::Read(non_minimal_uint, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::NON_MINIMAL_CBOR_ENCODING);
   }
@@ -144,7 +144,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing negative int : " << test_case.negative_int);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::NEGATIVE);
     EXPECT_EQ(cbor.value().GetInteger(), test_case.negative_int);
@@ -184,7 +184,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing string test case at : " << element_index++);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::BYTE_STRING);
     EXPECT_EQ(cbor.value().GetBytestring(), test_case.value);
@@ -226,7 +226,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing string value : " << test_case.value);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::STRING);
     EXPECT_EQ(cbor.value().GetString(), test_case.value);
@@ -271,7 +271,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing string with nul bytes :" << test_case.value);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::STRING);
     EXPECT_EQ(cbor.value().GetString(), test_case.value);
@@ -301,7 +301,7 @@
   static const std::vector<uint8_t> string_with_invalid_continuation_byte = {
       0x63, 0x00, 0x00, 0xA6};
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor =
+  absl::optional<Value> cbor =
       Reader::Read(string_with_invalid_continuation_byte, &error_code);
   EXPECT_FALSE(cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::INVALID_UTF8);
@@ -317,7 +317,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kArrayTestCaseCbor);
+  absl::optional<Value> cbor = Reader::Read(kArrayTestCaseCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_array = std::move(cbor.value());
   ASSERT_EQ(cbor_array.type(), Value::Type::ARRAY);
@@ -366,7 +366,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kMapTestCaseCbor);
+  absl::optional<Value> cbor = Reader::Read(kMapTestCaseCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -428,7 +428,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
+  absl::optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -487,7 +487,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
+  absl::optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -541,7 +541,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kMapArrayTestCaseCbor);
+  absl::optional<Value> cbor = Reader::Read(kMapArrayTestCaseCbor);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -594,7 +594,7 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+  absl::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
   ASSERT_TRUE(cbor.has_value());
   ASSERT_EQ(cbor->type(), Value::Type::MAP);
   ASSERT_EQ(cbor->GetMap().size(), 2u);
@@ -637,7 +637,7 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+  absl::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
   ASSERT_TRUE(cbor.has_value());
   ASSERT_EQ(cbor->type(), Value::Type::MAP);
   ASSERT_EQ(cbor->GetMap().size(), 2u);
@@ -710,7 +710,7 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+  absl::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
   ASSERT_TRUE(cbor.has_value());
   ASSERT_EQ(cbor->type(), Value::Type::MAP);
   ASSERT_EQ(cbor->GetMap().size(), 6u);
@@ -763,7 +763,7 @@
       // clang-format on
   };
 
-  base::Optional<Value> cbor = Reader::Read(kNestedMapTestCase);
+  absl::optional<Value> cbor = Reader::Read(kNestedMapTestCase);
   ASSERT_TRUE(cbor.has_value());
   const Value cbor_val = std::move(cbor.value());
   ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -800,11 +800,11 @@
   static const std::vector<uint8_t> kMinNegativeInt = {
       0x3b, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 
-  base::Optional<Value> max_positive_int = Reader::Read(kMaxPositiveInt);
+  absl::optional<Value> max_positive_int = Reader::Read(kMaxPositiveInt);
   ASSERT_TRUE(max_positive_int.has_value());
   EXPECT_EQ(max_positive_int.value().GetInteger(), INT64_MAX);
 
-  base::Optional<Value> min_negative_int = Reader::Read(kMinNegativeInt);
+  absl::optional<Value> min_negative_int = Reader::Read(kMinNegativeInt);
   ASSERT_TRUE(min_negative_int.has_value());
   EXPECT_EQ(min_negative_int.value().GetInteger(), INT64_MIN);
 }
@@ -817,12 +817,12 @@
       0x3b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
   Reader::DecoderError error_code;
-  base::Optional<Value> positive_int_out_of_range_cbor =
+  absl::optional<Value> positive_int_out_of_range_cbor =
       Reader::Read(kOutOfRangePositiveInt, &error_code);
   EXPECT_FALSE(positive_int_out_of_range_cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_RANGE_INTEGER_VALUE);
 
-  base::Optional<Value> negative_int_out_of_range_cbor =
+  absl::optional<Value> negative_int_out_of_range_cbor =
       Reader::Read(kOutOfRangeNegativeInt, &error_code);
   EXPECT_FALSE(negative_int_out_of_range_cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_RANGE_INTEGER_VALUE);
@@ -844,7 +844,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing simple value at index : " << test_element_index++);
 
-    base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+    absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), Value::Type::SIMPLE_VALUE);
     EXPECT_EQ(cbor.value().GetSimpleValue(), test_case.value);
@@ -880,7 +880,7 @@
                  << "testing unsupported floating point : "
                  << testing::PrintToString(unsupported_floating_point));
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor =
+    absl::optional<Value> cbor =
         Reader::Read(unsupported_floating_point, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code,
@@ -925,7 +925,7 @@
                                     << test_element_index++);
 
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor = Reader::Read(incomplete_data, &error_code);
+    absl::optional<Value> cbor = Reader::Read(incomplete_data, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::INCOMPLETE_CBOR_DATA);
   }
@@ -947,7 +947,7 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor = Reader::Read(kMapWithUintKey, &error_code);
+  absl::optional<Value> cbor = Reader::Read(kMapWithUintKey, &error_code);
   EXPECT_FALSE(cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::INCORRECT_MAP_KEY_TYPE);
 }
@@ -979,7 +979,7 @@
                  << "testing data at index : " << test_element_index++);
 
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor = Reader::Read(incorrect_cbor, &error_code);
+    absl::optional<Value> cbor = Reader::Read(incorrect_cbor, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::UNKNOWN_ADDITIONAL_INFO);
   }
@@ -1004,7 +1004,7 @@
     SCOPED_TRACE(testing::Message()
                  << "testing zero nested data : " << test_element_index++);
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor = Reader::Read(zero_depth_data, &error_code, 0);
+    absl::optional<Value> cbor = Reader::Read(zero_depth_data, &error_code, 0);
     EXPECT_TRUE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
   }
@@ -1026,12 +1026,12 @@
   };
 
   Reader::DecoderError error_code;
-  base::Optional<Value> cbor_single_layer_max =
+  absl::optional<Value> cbor_single_layer_max =
       Reader::Read(kNestedCBORData, &error_code, 1);
   EXPECT_FALSE(cbor_single_layer_max.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::TOO_MUCH_NESTING);
 
-  base::Optional<Value> cbor_double_layer_max =
+  absl::optional<Value> cbor_double_layer_max =
       Reader::Read(kNestedCBORData, &error_code, 2);
   EXPECT_TRUE(cbor_double_layer_max.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
@@ -1081,16 +1081,91 @@
   };
 
   int test_element_index = 0;
-  Reader::DecoderError error_code;
   for (const auto& unsorted_map : kMapsWithUnsortedKeys) {
     testing::Message scope_message;
     scope_message << "testing unsorted map : " << test_element_index++;
     SCOPED_TRACE(scope_message);
 
-    base::Optional<Value> cbor =
-        Reader::Read(unsorted_map, &error_code);
-    EXPECT_FALSE(cbor.has_value());
-    EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_ORDER_KEY);
+    // Expect `OUT_OF_ORDER_KEY`.
+    {
+      Reader::DecoderError error_code;
+      absl::optional<Value> cbor =
+          Reader::Read(unsorted_map, &error_code);
+      EXPECT_FALSE(cbor.has_value());
+      EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_ORDER_KEY);
+    }
+
+    // When `allow_and_canonicalize_out_of_order_keys` flag is set, expect
+    // `CBOR_NO_ERROR`.
+    {
+      Reader::DecoderError error_code;
+      Reader::Config config;
+      config.error_code_out = &error_code;
+      config.allow_and_canonicalize_out_of_order_keys = true;
+
+      absl::optional<Value> cbor =
+          Reader::Read(unsorted_map, config);
+      EXPECT_TRUE(cbor);
+      EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
+    }
+  }
+}
+
+TEST(CBORReaderTest, TestOutOfOrderKeyErrorWithDuplicateKeys) {
+  static const std::vector<uint8_t> kMapsWithUnsortedKeys[] = {
+      // clang-format off
+      {0xa3,  // map with 3 keys with same major type and length
+         0x61, 0x62,  // key "b"
+         0x61, 0x42,  // value "B"
+
+         0x61, 0x61,  // key "a" (out of order byte-wise lexically)
+         0x61, 0x45,   // value "E"
+
+         0x61, 0x62,  // key "b" (duplicate)
+         0x61, 0x42,  // value "B"
+      },
+      {0xa3,  // map with 3 byte string keys
+         0x42, 'x', 'x', // key byte string "xx"
+                         // (out of order due to longer length)
+         0x02,
+
+         0x41, 'y',  // key byte string "y"
+         0x01,
+
+         0x41, 'y',  // key byte string "y" (duplicate)
+         0x02,
+      },
+      //clang-format on
+  };
+
+  int test_element_index = 0;
+  for (const auto& unsorted_map : kMapsWithUnsortedKeys) {
+    testing::Message scope_message;
+    scope_message << "testing unsorted map : " << test_element_index++;
+    SCOPED_TRACE(scope_message);
+
+    // Expect `OUT_OF_ORDER_KEY`.
+    {
+      Reader::DecoderError error_code;
+      absl::optional<Value> cbor =
+          Reader::Read(unsorted_map, &error_code);
+      EXPECT_FALSE(cbor.has_value());
+      EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_ORDER_KEY);
+    }
+
+    // When `allow_and_canonicalize_out_of_order_keys` flag is set, expect
+    // `DUPLICATE_KEY`.
+    {
+      Reader::DecoderError error_code;
+      Reader::Config config;
+      config.error_code_out = &error_code;
+      config.allow_and_canonicalize_out_of_order_keys = true;
+
+      absl::optional<Value> cbor =
+          Reader::Read(unsorted_map, config);
+      EXPECT_FALSE(cbor);
+      EXPECT_EQ(error_code, Reader::DecoderError::DUPLICATE_KEY);
+    }
   }
 }
 
@@ -1118,11 +1193,24 @@
       // clang-format on
   };
 
-  Reader::DecoderError error_code;
+  {
+    Reader::DecoderError error_code;
+    absl::optional<Value> cbor =
+        Reader::Read(kMapWithDuplicateKey, &error_code);
+    EXPECT_FALSE(cbor.has_value());
+    EXPECT_EQ(error_code, Reader::DecoderError::DUPLICATE_KEY);
+  }
 
-  base::Optional<Value> cbor = Reader::Read(kMapWithDuplicateKey, &error_code);
-  EXPECT_FALSE(cbor.has_value());
-  EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_ORDER_KEY);
+  {
+    Reader::DecoderError error_code;
+    Reader::Config config;
+    config.error_code_out = &error_code;
+    config.allow_and_canonicalize_out_of_order_keys = true;
+
+    absl::optional<Value> cbor = Reader::Read(kMapWithDuplicateKey, config);
+    EXPECT_FALSE(cbor.has_value());
+    EXPECT_EQ(error_code, Reader::DecoderError::DUPLICATE_KEY);
+  }
 }
 
 // Leveraging Markus Kuhn’s UTF-8 decoder stress test. See
@@ -1143,7 +1231,7 @@
     SCOPED_TRACE(testing::Message() << "testing cbor data utf8 encoding : "
                                     << test_element_index++);
 
-    base::Optional<Value> correctly_encoded_cbor =
+    absl::optional<Value> correctly_encoded_cbor =
         Reader::Read(cbor_byte, &error_code);
     EXPECT_TRUE(correctly_encoded_cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
@@ -1151,7 +1239,7 @@
 
   // Incorrect UTF8 encoding referenced by section 3.5.3 of the stress test.
   std::vector<uint8_t> impossible_utf_byte{0x64, 0xfe, 0xfe, 0xff, 0xff};
-  base::Optional<Value> incorrectly_encoded_cbor =
+  absl::optional<Value> incorrectly_encoded_cbor =
       Reader::Read(impossible_utf_byte, &error_code);
   EXPECT_FALSE(incorrectly_encoded_cbor.has_value());
   EXPECT_EQ(error_code, Reader::DecoderError::INVALID_UTF8);
@@ -1177,7 +1265,7 @@
                  << "testing cbor extraneous data : " << test_element_index++);
 
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor =
+    absl::optional<Value> cbor =
         Reader::Read(extraneous_cbor_data, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::EXTRANEOUS_DATA);
@@ -1212,7 +1300,7 @@
                  << ::testing::PrintToString(unsupported_simple_val));
 
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor =
+    absl::optional<Value> cbor =
         Reader::Read(unsupported_simple_val, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::UNSUPPORTED_SIMPLE_VALUE);
@@ -1228,7 +1316,7 @@
   };
   for (const auto& test_case : kTestCases) {
     Reader::DecoderError error_code;
-    base::Optional<Value> cbor = Reader::Read(test_case, &error_code);
+    absl::optional<Value> cbor = Reader::Read(test_case, &error_code);
     EXPECT_FALSE(cbor.has_value());
     EXPECT_EQ(error_code, Reader::DecoderError::INCOMPLETE_CBOR_DATA);
   }
@@ -1252,7 +1340,7 @@
   Reader::Config config;
   config.error_code_out = &error;
 
-  base::Optional<Value> cbor = Reader::Read(kInvalidUTF8, config);
+  absl::optional<Value> cbor = Reader::Read(kInvalidUTF8, config);
   EXPECT_FALSE(cbor);
   EXPECT_EQ(Reader::DecoderError::INVALID_UTF8, error);
 
diff --git a/values.cc b/values.cc
index 384e0fd..32d6b11 100644
--- a/values.cc
+++ b/values.cc
@@ -10,6 +10,7 @@
 #include "base/check_op.h"
 #include "base/notreached.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "cbor/constants.h"
 
diff --git a/values.h b/values.h
index 9820472..46bcb81 100644
--- a/values.h
+++ b/values.h
@@ -11,10 +11,10 @@
 #include <tuple>
 #include <vector>
 
+#include "base/check.h"
 #include "base/containers/flat_map.h"
 #include "base/containers/span.h"
-#include "base/logging.h"
-#include "base/macros.h"
+#include "base/notreached.h"
 #include "base/notreached.h"
 #include "base/strings/string_piece.h"
 #include "cbor/cbor_export.h"
@@ -147,6 +147,9 @@
 
   Value& operator=(Value&& that) noexcept;
 
+  Value(const Value&) = delete;
+  Value& operator=(const Value&) = delete;
+
   ~Value();
 
   // Value's copy constructor and copy assignment operator are deleted.
@@ -206,8 +209,6 @@
 
   void InternalMoveConstructFrom(Value&& that);
   void InternalCleanup();
-
-  DISALLOW_COPY_AND_ASSIGN(Value);
 };
 
 }  // namespace cbor
diff --git a/writer.cc b/writer.cc
index 1ae21c6..2762bb3 100644
--- a/writer.cc
+++ b/writer.cc
@@ -17,19 +17,19 @@
 Writer::~Writer() {}
 
 // static
-base::Optional<std::vector<uint8_t>> Writer::Write(const Value& node,
+absl::optional<std::vector<uint8_t>> Writer::Write(const Value& node,
                                                    const Config& config) {
   std::vector<uint8_t> cbor;
   Writer writer(&cbor);
   if (!writer.EncodeCBOR(node, config.max_nesting_level,
                          config.allow_invalid_utf8_for_testing)) {
-    return base::nullopt;
+    return absl::nullopt;
   }
   return cbor;
 }
 
 // static
-base::Optional<std::vector<uint8_t>> Writer::Write(const Value& node,
+absl::optional<std::vector<uint8_t>> Writer::Write(const Value& node,
                                                    size_t max_nesting_level) {
   Config config;
   config.max_nesting_level = base::checked_cast<int>(max_nesting_level);
diff --git a/writer.h b/writer.h
index 756bd7f..b2d9ef1 100644
--- a/writer.h
+++ b/writer.h
@@ -10,9 +10,10 @@
 
 #include <vector>
 
-#include "base/optional.h"
+#include "base/memory/raw_ptr.h"
 #include "cbor/cbor_export.h"
 #include "cbor/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 // A basic Concise Binary Object Representation (CBOR) encoder as defined by
 // https://tools.ietf.org/html/rfc7049. This is a generic encoder that supplies
@@ -72,17 +73,20 @@
     bool allow_invalid_utf8_for_testing = false;
   };
 
+  Writer(const Writer&) = delete;
+  Writer& operator=(const Writer&) = delete;
+
   ~Writer();
 
   // Returns the CBOR byte string representation of |node|, unless its nesting
   // depth is greater than |max_nesting_level|, in which case an empty optional
   // value is returned.
-  static base::Optional<std::vector<uint8_t>> Write(
+  static absl::optional<std::vector<uint8_t>> Write(
       const Value& node,
       size_t max_nesting_level = kDefaultMaxNestingDepth);
 
   // A version of |Write| above that takes a Config.
-  static base::Optional<std::vector<uint8_t>> Write(const Value& node,
+  static absl::optional<std::vector<uint8_t>> Write(const Value& node,
                                                     const Config& config);
 
  private:
@@ -108,9 +112,7 @@
   size_t GetNumUintBytes(uint64_t value);
 
   // Holds the encoded CBOR data.
-  std::vector<uint8_t>* encoded_cbor_;
-
-  DISALLOW_COPY_AND_ASSIGN(Writer);
+  raw_ptr<std::vector<uint8_t>> encoded_cbor_;
 };
 
 }  // namespace cbor
diff --git a/writer_unittest.cc b/writer_unittest.cc
index 912a4ba..b3348a8 100644
--- a/writer_unittest.cc
+++ b/writer_unittest.cc
@@ -7,7 +7,7 @@
 #include <limits>
 #include <string>
 
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"