Coverage Report

Created: 2025-07-11 06:37

/src/abseil-cpp/absl/log/internal/proto.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2020 The Abseil 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
#include "absl/log/internal/proto.h"
16
17
#include <algorithm>
18
#include <cassert>
19
#include <cstddef>
20
#include <cstdint>
21
#include <cstring>
22
23
#include "absl/base/attributes.h"
24
#include "absl/base/config.h"
25
#include "absl/types/span.h"
26
27
namespace absl {
28
ABSL_NAMESPACE_BEGIN
29
namespace log_internal {
30
namespace {
31
0
void EncodeRawVarint(uint64_t value, size_t size, absl::Span<char> *buf) {
32
0
  for (size_t s = 0; s < size; s++) {
33
0
    (*buf)[s] = static_cast<char>((value & 0x7f) | (s + 1 == size ? 0 : 0x80));
34
0
    value >>= 7;
35
0
  }
36
0
  buf->remove_prefix(size);
37
0
}
38
}  // namespace
39
40
0
bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
41
0
  const uint64_t tag_type = MakeTagType(tag, WireType::kVarint);
42
0
  const size_t tag_type_size = VarintSize(tag_type);
43
0
  const size_t value_size = VarintSize(value);
44
0
  if (tag_type_size + value_size > buf->size()) {
45
0
    buf->remove_suffix(buf->size());
46
0
    return false;
47
0
  }
48
0
  EncodeRawVarint(tag_type, tag_type_size, buf);
49
0
  EncodeRawVarint(value, value_size, buf);
50
0
  return true;
51
0
}
52
53
0
bool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
54
0
  const uint64_t tag_type = MakeTagType(tag, WireType::k64Bit);
55
0
  const size_t tag_type_size = VarintSize(tag_type);
56
0
  if (tag_type_size + sizeof(value) > buf->size()) {
57
0
    buf->remove_suffix(buf->size());
58
0
    return false;
59
0
  }
60
0
  EncodeRawVarint(tag_type, tag_type_size, buf);
61
0
  for (size_t s = 0; s < sizeof(value); s++) {
62
0
    (*buf)[s] = static_cast<char>(value & 0xff);
63
0
    value >>= 8;
64
0
  }
65
0
  buf->remove_prefix(sizeof(value));
66
0
  return true;
67
0
}
68
69
0
bool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
70
0
  const uint64_t tag_type = MakeTagType(tag, WireType::k32Bit);
71
0
  const size_t tag_type_size = VarintSize(tag_type);
72
0
  if (tag_type_size + sizeof(value) > buf->size()) {
73
0
    buf->remove_suffix(buf->size());
74
0
    return false;
75
0
  }
76
0
  EncodeRawVarint(tag_type, tag_type_size, buf);
77
0
  for (size_t s = 0; s < sizeof(value); s++) {
78
0
    (*buf)[s] = static_cast<char>(value & 0xff);
79
0
    value >>= 8;
80
0
  }
81
0
  buf->remove_prefix(sizeof(value));
82
0
  return true;
83
0
}
84
85
bool EncodeBytes(uint64_t tag, absl::Span<const char> value,
86
0
                 absl::Span<char> *buf) {
87
0
  const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
88
0
  const size_t tag_type_size = VarintSize(tag_type);
89
0
  uint64_t length = value.size();
90
0
  const size_t length_size = VarintSize(length);
91
0
  if (tag_type_size + length_size + value.size() > buf->size()) {
92
0
    buf->remove_suffix(buf->size());
93
0
    return false;
94
0
  }
95
0
  EncodeRawVarint(tag_type, tag_type_size, buf);
96
0
  EncodeRawVarint(length, length_size, buf);
97
0
  memcpy(buf->data(), value.data(), value.size());
98
0
  buf->remove_prefix(value.size());
99
0
  return true;
100
0
}
101
102
bool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,
103
0
                         absl::Span<char> *buf) {
104
0
  const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
105
0
  const size_t tag_type_size = VarintSize(tag_type);
106
0
  uint64_t length = value.size();
107
0
  const size_t length_size =
108
0
      VarintSize(std::min<uint64_t>(length, buf->size()));
109
0
  if (tag_type_size + length_size <= buf->size() &&
110
0
      tag_type_size + length_size + value.size() > buf->size()) {
111
0
    value.remove_suffix(tag_type_size + length_size + value.size() -
112
0
                        buf->size());
113
0
    length = value.size();
114
0
  }
115
0
  if (tag_type_size + length_size + value.size() > buf->size()) {
116
0
    buf->remove_suffix(buf->size());
117
0
    return false;
118
0
  }
119
0
  EncodeRawVarint(tag_type, tag_type_size, buf);
120
0
  EncodeRawVarint(length, length_size, buf);
121
0
  memcpy(buf->data(), value.data(), value.size());
122
0
  buf->remove_prefix(value.size());
123
0
  return true;
124
0
}
125
126
[[nodiscard]] absl::Span<char> EncodeMessageStart(uint64_t tag,
127
                                                  uint64_t max_size,
128
0
                                                  absl::Span<char> *buf) {
129
0
  const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
130
0
  const size_t tag_type_size = VarintSize(tag_type);
131
0
  max_size = std::min<uint64_t>(max_size, buf->size());
132
0
  const size_t length_size = VarintSize(max_size);
133
0
  if (tag_type_size + length_size > buf->size()) {
134
0
    buf->remove_suffix(buf->size());
135
0
    return absl::Span<char>();
136
0
  }
137
0
  EncodeRawVarint(tag_type, tag_type_size, buf);
138
0
  const absl::Span<char> ret = buf->subspan(0, length_size);
139
0
  EncodeRawVarint(0, length_size, buf);
140
0
  return ret;
141
0
}
142
143
0
void EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf) {
144
0
  if (!msg.data()) return;
145
0
  assert(buf->data() >= msg.data());
146
0
  if (buf->data() < msg.data()) return;
147
0
  EncodeRawVarint(
148
0
      static_cast<uint64_t>(buf->data() - (msg.data() + msg.size())),
149
0
      msg.size(), &msg);
150
0
}
151
152
namespace {
153
0
uint64_t DecodeVarint(absl::Span<const char> *buf) {
154
0
  uint64_t value = 0;
155
0
  size_t s = 0;
156
0
  while (s < buf->size()) {
157
0
    value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]) & 0x7f)
158
0
             << 7 * s;
159
0
    if (!((*buf)[s++] & 0x80)) break;
160
0
  }
161
0
  buf->remove_prefix(s);
162
0
  return value;
163
0
}
164
165
0
uint64_t Decode64Bit(absl::Span<const char> *buf) {
166
0
  uint64_t value = 0;
167
0
  size_t s = 0;
168
0
  while (s < buf->size()) {
169
0
    value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]))
170
0
             << 8 * s;
171
0
    if (++s == sizeof(value)) break;
172
0
  }
173
0
  buf->remove_prefix(s);
174
0
  return value;
175
0
}
176
177
0
uint32_t Decode32Bit(absl::Span<const char> *buf) {
178
0
  uint32_t value = 0;
179
0
  size_t s = 0;
180
0
  while (s < buf->size()) {
181
0
    value |= static_cast<uint32_t>(static_cast<unsigned char>((*buf)[s]))
182
0
             << 8 * s;
183
0
    if (++s == sizeof(value)) break;
184
0
  }
185
0
  buf->remove_prefix(s);
186
0
  return value;
187
0
}
188
}  // namespace
189
190
0
bool ProtoField::DecodeFrom(absl::Span<const char> *data) {
191
0
  if (data->empty()) return false;
192
0
  const uint64_t tag_type = DecodeVarint(data);
193
0
  tag_ = tag_type >> 3;
194
0
  type_ = static_cast<WireType>(tag_type & 0x07);
195
0
  switch (type_) {
196
0
    case WireType::kVarint:
197
0
      value_ = DecodeVarint(data);
198
0
      break;
199
0
    case WireType::k64Bit:
200
0
      value_ = Decode64Bit(data);
201
0
      break;
202
0
    case WireType::kLengthDelimited: {
203
0
      value_ = DecodeVarint(data);
204
0
      data_ = data->subspan(
205
0
          0, static_cast<size_t>(std::min<uint64_t>(value_, data->size())));
206
0
      data->remove_prefix(data_.size());
207
0
      break;
208
0
    }
209
0
    case WireType::k32Bit:
210
0
      value_ = Decode32Bit(data);
211
0
      break;
212
0
  }
213
0
  return true;
214
0
}
215
216
}  // namespace log_internal
217
ABSL_NAMESPACE_END
218
}  // namespace absl