File: CBORReader.h

package info (click to toggle)
webkit2gtk 2.42.2-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 362,452 kB
  • sloc: cpp: 2,881,971; javascript: 282,447; ansic: 134,088; python: 43,789; ruby: 18,308; perl: 15,872; asm: 14,389; xml: 4,395; yacc: 2,350; sh: 2,074; java: 1,734; lex: 1,323; makefile: 288; pascal: 60
file content (136 lines) | stat: -rw-r--r-- 5,719 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2017 The Chromium Authors. All rights reserved.
// Copyright (C) 2018-2023 Apple Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#pragma once

#if ENABLE(WEB_AUTHN)

#include "CBORValue.h"
#include <stddef.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 |maxNestingLevel|.
//  - 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 CBORReader {
    WTF_MAKE_NONCOPYABLE(CBORReader);
public:
    using Bytes = std::span<const uint8_t>;

    enum class DecoderError {
        CBORNoError = 0,
        UnsupportedMajorType,
        UnknownAdditionalInfo,
        IncompleteCBORData,
        IncorrectMapKeyType,
        TooMuchNesting,
        InvalidUTF8,
        ExtraneousData,
        DuplicateKey,
        OutOfOrderKey,
        NonMinimalCBOREncoding,
        UnsupportedSimpleValue,
        UnsupportedFloatingPointValue,
        OutOfRangeIntegerValue,
    };

    // 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 |errorCodeOut|
    // can be provided by the caller to obtain additional information about
    // decoding failures.
    WEBCORE_EXPORT static std::optional<CBORValue> read(const Bytes&, DecoderError* errorCodeOut = nullptr, int maxNestingLevel = kCBORMaxDepth);

    // Translates errors to human-readable error messages.
    static const char* errorCodeToString(DecoderError errorCode);

private:
    explicit CBORReader(const Bytes&);
    std::optional<CBORValue> decodeCBOR(int maxNestingLevel);
    std::optional<CBORValue> decodeValueToNegative(uint64_t value);
    std::optional<CBORValue> decodeValueToUnsigned(uint64_t value);
    std::optional<CBORValue> readSimpleValue(uint8_t additionalInfo, uint64_t value);
    bool readVariadicLengthInteger(uint8_t additionalInfo, uint64_t* value);
    std::optional<CBORValue> readBytes(uint64_t numBytes);
    std::optional<CBORValue> readString(uint64_t numBytes);
    std::optional<CBORValue> readCBORArray(uint64_t length, int maxNestingLevel);
    std::optional<CBORValue> readCBORMap(uint64_t length, int maxNestingLevel);
    bool canConsume(uint64_t bytes);
    void checkExtraneousData();
    bool checkDuplicateKey(const CBORValue& newKey, const CBORValue::MapValue&);
    bool hasValidUTF8Format(const String&);
    bool checkOutOfOrderKey(const CBORValue& newKey, const CBORValue::MapValue&);
    bool checkMinimalEncoding(uint8_t additionalBytes, uint64_t uintData);

    DecoderError getErrorCode();

    const Bytes& m_data;
    Bytes::iterator m_it;
    DecoderError m_errorCode;
};

} // namespace cbor

#endif // ENABLE(WEB_AUTHN)