Coverage Report

Created: 2026-04-02 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/pki/input.h
Line
Count
Source
1
// Copyright 2015 The Chromium Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef BSSL_DER_INPUT_H_
16
#define BSSL_DER_INPUT_H_
17
18
#include <stddef.h>
19
#include <stdint.h>
20
21
#include <string>
22
#include <string_view>
23
24
#include <openssl/base.h>
25
#include <openssl/span.h>
26
27
#if __has_include(<version>)
28
#include <version>
29
#endif
30
31
#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L
32
#include <ranges>
33
BSSL_NAMESPACE_BEGIN
34
namespace der {
35
class OPENSSL_EXPORT Input;
36
}
37
BSSL_NAMESPACE_END
38
39
// Mark `Input` as satisfying the `view` and `borrowed_range` concepts. This
40
// should be done before the definition of `Input`, so that any inlined calls to
41
// range functionality use the correct specializations.
42
template <>
43
inline constexpr bool std::ranges::enable_view<bssl::der::Input> = true;
44
template <>
45
inline constexpr bool std::ranges::enable_borrowed_range<bssl::der::Input> =
46
    true;
47
#endif
48
49
BSSL_NAMESPACE_BEGIN
50
namespace der {
51
52
// An opaque class that represents a fixed buffer of data of a fixed length,
53
// to be used as an input to other operations. An Input object does not own
54
// the data it references, so callers are responsible for making sure that
55
// the data outlives the Input object and any other associated objects.
56
//
57
// All data access for an Input should be done through the ByteReader class.
58
// This class and associated classes are designed with safety in mind to make it
59
// difficult to read memory outside of an Input. ByteReader provides a simple
60
// API for reading through the Input sequentially. For more complicated uses,
61
// multiple instances of a ByteReader for a particular Input can be created.
62
//
63
// TODO(crbug.com/boringssl/661): This class will gradually be replaced with
64
// bssl::Span<const uint8_t>. Avoid relying on APIs that are not part of
65
// bssl::Span.
66
class OPENSSL_EXPORT Input {
67
 public:
68
  // Creates an empty Input, one from which no data can be read.
69
2.96M
  constexpr Input() = default;
70
71
  // Creates an Input from a span. The constructed Input is only valid as long
72
  // as |data| points to live memory. If constructed from, say, a
73
  // |std::vector<uint8_t>|, mutating the vector will invalidate the Input.
74
28.7k
  constexpr Input(bssl::Span<const uint8_t> data) : data_(data) {}
75
76
  // Creates an Input from the given |data| and |len|.
77
  constexpr explicit Input(const uint8_t *data, size_t len)
78
1.69M
      : data_(Span(data, len)) {}
79
80
  // Deprecated: Use StringAsBytes.
81
  //
82
  // Creates an Input from a std::string_view. The constructed Input is only
83
  // valid as long as |data| points to live memory. If constructed from, say, a
84
  // |std::string|, mutating the vector will invalidate the Input.
85
925
  explicit Input(std::string_view str) : data_(StringAsBytes(str)) {}
86
87
  // The following APIs have the same semantics as in |bssl::Span|.
88
382
  constexpr Span<const uint8_t>::iterator begin() const {
89
382
    return data_.begin();
90
382
  }
91
382
  constexpr Span<const uint8_t>::iterator end() const { return data_.end(); }
92
2.58M
  constexpr const uint8_t *data() const { return data_.data(); }
93
2.44M
  constexpr size_t size() const { return data_.size(); }
94
4.76k
  constexpr bool empty() const { return data_.empty(); }
95
1.18k
  constexpr uint8_t operator[](size_t idx) const { return data_[idx]; }
96
0
  constexpr uint8_t front() const { return data_.front(); }
97
3.27k
  constexpr uint8_t back() const { return data_.back(); }
98
0
  constexpr Input subspan(size_t pos, size_t len) const {
99
0
    return Input(data_.subspan(pos, len));
100
0
  }
101
188
  constexpr Input subspan(size_t pos) const {
102
188
    return Input(data_.subspan(pos));
103
188
  }
104
188
  constexpr Input first(size_t len) const { return Input(data_.first(len)); }
105
0
  constexpr Input last(size_t len) const { return Input(data_.last(len)); }
106
107
 private:
108
  // TODO(crbug.com/770501): Replace this type with span altogether.
109
  Span<const uint8_t> data_;
110
};
111
112
// Return true if |lhs|'s data and |rhs|'s data are byte-wise equal.
113
OPENSSL_EXPORT bool operator==(Input lhs, Input rhs);
114
115
// Return true if |lhs|'s data and |rhs|'s data are not byte-wise equal.
116
OPENSSL_EXPORT bool operator!=(Input lhs, Input rhs);
117
118
// Returns true if |lhs|'s data is lexicographically less than |rhs|'s data.
119
242k
OPENSSL_EXPORT constexpr bool operator<(Input lhs, Input rhs) {
120
  // This is `std::lexicographical_compare`, but that's not `constexpr` until
121
  // C++-20.
122
242k
  auto *it1 = lhs.data();
123
242k
  auto *it2 = rhs.data();
124
242k
  const auto *end1 = lhs.data() + lhs.size();
125
242k
  const auto *end2 = rhs.data() + rhs.size();
126
687k
  for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
127
659k
    if (*it1 < *it2) {
128
143k
      return true;
129
515k
    } else if (*it2 < *it1) {
130
71.2k
      return false;
131
71.2k
    }
132
659k
  }
133
134
27.6k
  return it2 != end2;
135
242k
}
136
137
// This class provides ways to read data from an Input in a bounds-checked way.
138
// The ByteReader is designed to read through the input sequentially. Once a
139
// byte has been read with a ByteReader, the caller can't go back and re-read
140
// that byte with the same reader. Of course, the caller can create multiple
141
// ByteReaders for the same input (or copy an existing ByteReader).
142
//
143
// For something simple like a single byte lookahead, the easiest way to do
144
// that is to copy the ByteReader and call ReadByte() on the copy - the original
145
// ByteReader will be unaffected and the peeked byte will be read through
146
// ReadByte(). For other read patterns, it can be useful to mark where one is
147
// in a ByteReader to be able to return to that spot.
148
//
149
// Some operations using Mark can also be done by creating a copy of the
150
// ByteReader. By using a Mark instead, you use less memory, but more
151
// importantly, you end up with an immutable object that matches the semantics
152
// of what is intended.
153
class OPENSSL_EXPORT ByteReader {
154
 public:
155
  // Creates a ByteReader to read the data represented by an Input.
156
  explicit ByteReader(Input in);
157
158
  // Reads a single byte from the input source, putting the byte read in
159
  // |*byte_p|. If a byte cannot be read from the input (because there is
160
  // no input left), then this method returns false.
161
  [[nodiscard]] bool ReadByte(uint8_t *out);
162
163
  // Reads |len| bytes from the input source, and initializes an Input to
164
  // point to that data. If there aren't enough bytes left in the input source,
165
  // then this method returns false.
166
  [[nodiscard]] bool ReadBytes(size_t len, Input *out);
167
168
  // Returns how many bytes are left to read.
169
3.28k
  size_t BytesLeft() const { return data_.size(); }
170
171
  // Returns whether there is any more data to be read.
172
  bool HasMore();
173
174
 private:
175
  void Advance(size_t len);
176
177
  bssl::Span<const uint8_t> data_;
178
};
179
180
}  // namespace der
181
BSSL_NAMESPACE_END
182
183
#endif  // BSSL_DER_INPUT_H_