blob: 35558891a45022dc1662b49ae25c5a1be532d7e2 [file] [log] [blame]
// Copyright 2017 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.
#ifndef COMPONENTS_CBOR_CBOR_READER_H_
#define COMPONENTS_CBOR_CBOR_READER_H_
#include <stddef.h>
#include <string>
#include <vector>
#include "base/optional.h"
#include "components/cbor/cbor_export.h"
#include "components/cbor/cbor_values.h"
// Concise Binary Object Representation (CBOR) decoder as defined by
// https://tools.ietf.org/html/rfc7049. This decoder only accepts canonical
// CBOR as defined by section 3.9.
// Supported:
// * Major types:
// * 0: Unsigned integers, up to 64-bit.
// * 2: Byte strings.
// * 3: UTF-8 strings.
// * 4: Definite-length arrays.
// * 5: Definite-length maps.
// * 7: Simple values.
//
// Requirements for canonical CBOR representation:
// - Duplicate keys for map are not allowed.
// - Keys for map must be sorted first by length and then by byte-wise
// lexical order.
//
// Known limitations and interpretations of the RFC:
// - Does not support negative integers, indefinite data streams and tagging.
// - Floating point representations and BREAK stop code in major
// type 7 are not supported.
// - Non-character codepoint are not supported for Major type 3.
// - Incomplete CBOR data items are treated as syntax errors.
// - Trailing data bytes are treated as errors.
// - Unknown additional information formats are treated as syntax errors.
// - Callers can decode CBOR values with at most 16 nested depth layer. More
// strict restrictions on nesting layer size of CBOR values can be enforced
// by setting |max_nesting_level|.
// - Only CBOR maps with integer or string type keys are supported due to the
// cost of serialization when sorting map keys.
// - Simple values that are unassigned/reserved as per RFC 7049 are not
// supported and treated as errors.
namespace cbor {
class CBOR_EXPORT CBORReader {
public:
using Bytes = std::vector<uint8_t>;
enum class DecoderError {
CBOR_NO_ERROR = 0,
UNSUPPORTED_MAJOR_TYPE,
UNKNOWN_ADDITIONAL_INFO,
INCOMPLETE_CBOR_DATA,
INCORRECT_MAP_KEY_TYPE,
TOO_MUCH_NESTING,
INVALID_UTF8,
EXTRANEOUS_DATA,
DUPLICATE_KEY,
OUT_OF_ORDER_KEY,
NON_MINIMAL_CBOR_ENCODING,
UNSUPPORTED_SIMPLE_VALUE,
UNSUPPORTED_FLOATING_POINT_VALUE,
OUT_OF_RANGE_INTEGER_VALUE,
};
// CBOR nested depth sufficient for most use cases.
static const int kCBORMaxDepth = 16;
~CBORReader();
// Reads and parses |input_data| into a CBORValue. If any one of the syntax
// formats is violated -including unknown additional info and incomplete
// CBOR data- then an empty optional is returned. Optional |error_code_out|
// can be provided by the caller to obtain additional information about
// decoding failures.
static base::Optional<CBORValue> Read(const Bytes& input_data,
DecoderError* error_code_out = nullptr,
int max_nesting_level = kCBORMaxDepth);
// Translates errors to human-readable error messages.
static const char* ErrorCodeToString(DecoderError error_code);
private:
CBORReader(Bytes::const_iterator it, const Bytes::const_iterator end);
base::Optional<CBORValue> DecodeCBOR(int max_nesting_level);
base::Optional<CBORValue> DecodeValueToNegative(uint64_t value);
base::Optional<CBORValue> DecodeValueToUnsigned(uint64_t value);
base::Optional<CBORValue> ReadSimpleValue(uint8_t additional_info,
uint64_t value);
bool ReadVariadicLengthInteger(uint8_t additional_info, uint64_t* value);
base::Optional<CBORValue> ReadBytes(uint64_t num_bytes);
base::Optional<CBORValue> ReadString(uint64_t num_bytes);
base::Optional<CBORValue> ReadCBORArray(uint64_t length,
int max_nesting_level);
base::Optional<CBORValue> ReadCBORMap(uint64_t length, int max_nesting_level);
bool CanConsume(uint64_t bytes);
void CheckExtraneousData();
bool CheckDuplicateKey(const CBORValue& new_key, CBORValue::MapValue* map);
bool HasValidUTF8Format(const std::string& string_data);
bool CheckOutOfOrderKey(const CBORValue& new_key, CBORValue::MapValue* map);
bool CheckMinimalEncoding(uint8_t additional_bytes, uint64_t uint_data);
DecoderError GetErrorCode();
Bytes::const_iterator it_;
const Bytes::const_iterator end_;
DecoderError error_code_;
DISALLOW_COPY_AND_ASSIGN(CBORReader);
};
} // namespace cbor
#endif // COMPONENTS_CBOR_CBOR_READER_H_