Coverage Report

Created: 2026-09-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/abseil-cpp/absl/strings/internal/charconv_parse.cc
Line
Count
Source
1
// Copyright 2018 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/strings/internal/charconv_parse.h"
16
17
#include <cassert>
18
#include <cstddef>
19
#include <cstdint>
20
#include <limits>
21
22
#include "absl/base/config.h"
23
#include "absl/strings/charconv.h"
24
#include "absl/strings/internal/memutil.h"
25
26
namespace absl {
27
ABSL_NAMESPACE_BEGIN
28
namespace {
29
30
// ParseFloat<10> will read the first 19 significant digits of the mantissa.
31
// This number was chosen for multiple reasons.
32
//
33
// (a) First, for whatever integer type we choose to represent the mantissa, we
34
// want to choose the largest possible number of decimal digits for that integer
35
// type.  We are using uint64_t, which can express any 19-digit unsigned
36
// integer.
37
//
38
// (b) Second, we need to parse enough digits that the binary value of any
39
// mantissa we capture has more bits of resolution than the mantissa
40
// representation in the target float.  Our algorithm requires at least 3 bits
41
// of headway, but 19 decimal digits give a little more than that.
42
//
43
// The following static assertions verify the above comments:
44
constexpr int kDecimalMantissaDigitsMax = 19;
45
46
static_assert(std::numeric_limits<uint64_t>::digits10 ==
47
                  kDecimalMantissaDigitsMax,
48
              "(a) above");
49
50
// IEEE doubles, which we assume in Abseil, have 53 binary bits of mantissa.
51
static_assert(std::numeric_limits<double>::is_iec559, "IEEE double assumed");
52
static_assert(std::numeric_limits<double>::radix == 2, "IEEE double fact");
53
static_assert(std::numeric_limits<double>::digits == 53, "IEEE double fact");
54
55
// The lowest valued 19-digit decimal mantissa we can read still contains
56
// sufficient information to reconstruct a binary mantissa.
57
static_assert(1000000000000000000u > (uint64_t{1} << (53 + 3)), "(b) above");
58
59
// ParseFloat<16> will read the first 15 significant digits of the mantissa.
60
//
61
// Because a base-16-to-base-2 conversion can be done exactly, we do not need
62
// to maximize the number of scanned hex digits to improve our conversion.  What
63
// is required is to scan two more bits than the mantissa can represent, so that
64
// we always round correctly.
65
//
66
// (One extra bit does not suffice to perform correct rounding, since a number
67
// exactly halfway between two representable floats has unique rounding rules,
68
// so we need to differentiate between a "halfway between" number and a "closer
69
// to the larger value" number.)
70
constexpr int kHexadecimalMantissaDigitsMax = 15;
71
72
// The minimum number of significant bits that will be read from
73
// kHexadecimalMantissaDigitsMax hex digits.  We must subtract by three, since
74
// the most significant digit can be a "1", which only contributes a single
75
// significant bit.
76
constexpr int kGuaranteedHexadecimalMantissaBitPrecision =
77
    4 * kHexadecimalMantissaDigitsMax - 3;
78
79
static_assert(kGuaranteedHexadecimalMantissaBitPrecision >
80
                  std::numeric_limits<double>::digits + 2,
81
              "kHexadecimalMantissaDigitsMax too small");
82
83
// We also impose a limit on the number of significant digits we will read from
84
// an exponent, to avoid having to deal with integer overflow.  We use 9 for
85
// this purpose.
86
//
87
// If we read a 9 digit exponent, the end result of the conversion will
88
// necessarily be infinity or zero, depending on the sign of the exponent.
89
// Therefore we can just drop extra digits on the floor without any extra
90
// logic.
91
constexpr int kDecimalExponentDigitsMax = 9;
92
static_assert(std::numeric_limits<int>::digits10 >= kDecimalExponentDigitsMax,
93
              "int type too small");
94
95
// To avoid incredibly large inputs causing integer overflow for our exponent,
96
// we impose an arbitrary but very large limit on the number of significant
97
// digits we will accept.  The implementation refuses to match a string with
98
// more consecutive significant mantissa digits than this.
99
constexpr int kDecimalDigitLimit = 50000000;
100
101
// Corresponding limit for hexadecimal digit inputs.  This is one fourth the
102
// amount of kDecimalDigitLimit, since each dropped hexadecimal digit requires
103
// a binary exponent adjustment of 4.
104
constexpr int kHexadecimalDigitLimit = kDecimalDigitLimit / 4;
105
106
// The largest exponent we can read is 999999999 (per
107
// kDecimalExponentDigitsMax), and the largest exponent adjustment we can get
108
// from dropped mantissa digits is 2 * kDecimalDigitLimit, and the sum of these
109
// comfortably fits in an integer.
110
//
111
// We count kDecimalDigitLimit twice because there are independent limits for
112
// numbers before and after the decimal point.  (In the case where there are no
113
// significant digits before the decimal point, there are independent limits for
114
// post-decimal-point leading zeroes and for significant digits.)
115
static_assert(999999999 + 2 * kDecimalDigitLimit <
116
                  std::numeric_limits<int>::max(),
117
              "int type too small");
118
static_assert(999999999 + 2 * (4 * kHexadecimalDigitLimit) <
119
                  std::numeric_limits<int>::max(),
120
              "int type too small");
121
122
// Returns true if the provided bitfield allows parsing an exponent value
123
// (e.g., "1.5e100").
124
0
bool AllowExponent(chars_format flags) {
125
0
  bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
126
0
  bool scientific =
127
0
      (flags & chars_format::scientific) == chars_format::scientific;
128
0
  return scientific || !fixed;
129
0
}
130
131
// Returns true if the provided bitfield requires an exponent value be present.
132
0
bool RequireExponent(chars_format flags) {
133
0
  bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
134
0
  bool scientific =
135
0
      (flags & chars_format::scientific) == chars_format::scientific;
136
0
  return scientific && !fixed;
137
0
}
138
139
const int8_t kAsciiToInt[256] = {
140
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
141
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
142
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  1,  2,  3,  4,  5,  6,  7,  8,
143
    9,  -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1,
144
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
145
    -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
146
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
147
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
148
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
149
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
150
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
151
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
152
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
153
    -1, -1, -1, -1, -1, -1, -1, -1, -1};
154
155
// Returns true if `ch` is a digit in the given base
156
template <int base>
157
bool IsDigit(char ch);
158
159
// Converts a valid `ch` to its digit value in the given base.
160
template <int base>
161
unsigned ToDigit(char ch);
162
163
// Returns true if `ch` is the exponent delimiter for the given base.
164
template <int base>
165
bool IsExponentCharacter(char ch);
166
167
// Returns the maximum number of significant digits we will read for a float
168
// in the given base.
169
template <int base>
170
constexpr int MantissaDigitsMax();
171
172
// Returns the largest consecutive run of digits we will accept when parsing a
173
// number in the given base.
174
template <int base>
175
constexpr int DigitLimit();
176
177
// Returns the amount the exponent must be adjusted by for each dropped digit.
178
// (For decimal this is 1, since the digits are in base 10 and the exponent base
179
// is also 10, but for hexadecimal this is 4, since the digits are base 16 but
180
// the exponent base is 2.)
181
template <int base>
182
constexpr int DigitMagnitude();
183
184
template <>
185
0
bool IsDigit<10>(char ch) {
186
0
  return ch >= '0' && ch <= '9';
187
0
}
188
template <>
189
0
bool IsDigit<16>(char ch) {
190
0
  return kAsciiToInt[static_cast<unsigned char>(ch)] >= 0;
191
0
}
192
193
template <>
194
0
unsigned ToDigit<10>(char ch) {
195
0
  return static_cast<unsigned>(ch - '0');
196
0
}
197
template <>
198
0
unsigned ToDigit<16>(char ch) {
199
0
  return static_cast<unsigned>(kAsciiToInt[static_cast<unsigned char>(ch)]);
200
0
}
201
202
template <>
203
0
bool IsExponentCharacter<10>(char ch) {
204
0
  return ch == 'e' || ch == 'E';
205
0
}
206
207
template <>
208
0
bool IsExponentCharacter<16>(char ch) {
209
0
  return ch == 'p' || ch == 'P';
210
0
}
211
212
template <>
213
0
constexpr int MantissaDigitsMax<10>() {
214
0
  return kDecimalMantissaDigitsMax;
215
0
}
216
template <>
217
0
constexpr int MantissaDigitsMax<16>() {
218
0
  return kHexadecimalMantissaDigitsMax;
219
0
}
220
221
template <>
222
0
constexpr int DigitLimit<10>() {
223
0
  return kDecimalDigitLimit;
224
0
}
225
template <>
226
0
constexpr int DigitLimit<16>() {
227
0
  return kHexadecimalDigitLimit;
228
0
}
229
230
template <>
231
0
constexpr int DigitMagnitude<10>() {
232
0
  return 1;
233
0
}
234
template <>
235
0
constexpr int DigitMagnitude<16>() {
236
0
  return 4;
237
0
}
238
239
// Reads decimal digits from [begin, end) into *out.  Returns the number of
240
// digits consumed.
241
//
242
// After max_digits has been read, keeps consuming characters, but no longer
243
// adjusts *out.  If a nonzero digit is dropped this way, *dropped_nonzero_digit
244
// is set; otherwise, it is left unmodified.
245
//
246
// If no digits are matched, returns 0 and leaves *out unchanged.
247
//
248
// ConsumeDigits does not protect against overflow on *out; max_digits must
249
// be chosen with respect to type T to avoid the possibility of overflow.
250
template <int base, typename T>
251
ptrdiff_t ConsumeDigits(const char* begin, const char* end,
252
                        ptrdiff_t max_digits, T* out,
253
0
                        bool* dropped_nonzero_digit) {
254
0
  if (base == 10) {
255
0
    assert(max_digits <= std::numeric_limits<T>::digits10);
256
0
  } else if (base == 16) {
257
0
    assert(max_digits * 4 <= std::numeric_limits<T>::digits);
258
0
  }
259
0
  const char* const original_begin = begin;
260
261
  // Skip leading zeros, but only if *out is zero.
262
  // They don't cause an overflow so we don't have to count them for
263
  // `max_digits`.
264
0
  while (!*out && end != begin && *begin == '0') ++begin;
265
266
0
  T accumulator = *out;
267
0
  const char* significant_digits_end =
268
0
      (end - begin > max_digits) ? begin + max_digits : end;
269
0
  while (begin < significant_digits_end && IsDigit<base>(*begin)) {
270
    // Do not guard against *out overflow; max_digits was chosen to avoid this.
271
    // Do assert against it, to detect problems in debug builds.
272
0
    auto digit = static_cast<T>(ToDigit<base>(*begin));
273
0
    assert(accumulator * base >= accumulator);
274
0
    accumulator *= base;
275
0
    assert(accumulator + digit >= accumulator);
276
0
    accumulator += digit;
277
0
    ++begin;
278
0
  }
279
0
  bool dropped_nonzero = false;
280
0
  while (begin < end && IsDigit<base>(*begin)) {
281
0
    dropped_nonzero = dropped_nonzero || (*begin != '0');
282
0
    ++begin;
283
0
  }
284
0
  if (dropped_nonzero && dropped_nonzero_digit != nullptr) {
285
0
    *dropped_nonzero_digit = true;
286
0
  }
287
0
  *out = accumulator;
288
0
  return begin - original_begin;
289
0
}
Unexecuted instantiation: charconv_parse.cc:long absl::(anonymous namespace)::ConsumeDigits<10, unsigned long>(char const*, char const*, long, unsigned long*, bool*)
Unexecuted instantiation: charconv_parse.cc:long absl::(anonymous namespace)::ConsumeDigits<10, int>(char const*, char const*, long, int*, bool*)
Unexecuted instantiation: charconv_parse.cc:long absl::(anonymous namespace)::ConsumeDigits<16, unsigned long>(char const*, char const*, long, unsigned long*, bool*)
290
291
// Returns true if `v` is one of the chars allowed inside parentheses following
292
// a NaN.
293
0
bool IsNanChar(char v) {
294
0
  return (v == '_') || (v >= '0' && v <= '9') || (v >= 'a' && v <= 'z') ||
295
0
         (v >= 'A' && v <= 'Z');
296
0
}
297
298
// Checks the range [begin, end) for a strtod()-formatted infinity or NaN.  If
299
// one is found, sets `out` appropriately and returns true.
300
bool ParseInfinityOrNan(const char* begin, const char* end,
301
0
                        strings_internal::ParsedFloat* out) {
302
0
  if (end - begin < 3) {
303
0
    return false;
304
0
  }
305
0
  switch (*begin) {
306
0
    case 'i':
307
0
    case 'I': {
308
      // An infinity string consists of the characters "inf" or "infinity",
309
      // case insensitive.
310
0
      if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
311
0
        return false;
312
0
      }
313
0
      out->type = strings_internal::FloatType::kInfinity;
314
0
      if (end - begin >= 8 &&
315
0
          strings_internal::memcasecmp(begin + 3, "inity", 5) == 0) {
316
0
        out->end = begin + 8;
317
0
      } else {
318
0
        out->end = begin + 3;
319
0
      }
320
0
      return true;
321
0
    }
322
0
    case 'n':
323
0
    case 'N': {
324
      // A NaN consists of the characters "nan", case insensitive, optionally
325
      // followed by a parenthesized sequence of zero or more alphanumeric
326
      // characters and/or underscores.
327
0
      if (strings_internal::memcasecmp(begin + 1, "an", 2) != 0) {
328
0
        return false;
329
0
      }
330
0
      out->type = strings_internal::FloatType::kNan;
331
0
      out->end = begin + 3;
332
      // NaN is allowed to be followed by a parenthesized string, consisting of
333
      // only the characters [a-zA-Z0-9_].  Match that if it's present.
334
0
      begin += 3;
335
0
      if (begin < end && *begin == '(') {
336
0
        const char* nan_begin = begin + 1;
337
0
        while (nan_begin < end && IsNanChar(*nan_begin)) {
338
0
          ++nan_begin;
339
0
        }
340
0
        if (nan_begin < end && *nan_begin == ')') {
341
          // We found an extra NaN specifier range
342
0
          out->subrange_begin = begin + 1;
343
0
          out->subrange_end = nan_begin;
344
0
          out->end = nan_begin + 1;
345
0
        }
346
0
      }
347
0
      return true;
348
0
    }
349
0
    default:
350
0
      return false;
351
0
  }
352
0
}
353
}  // namespace
354
355
namespace strings_internal {
356
357
template <int base>
358
strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
359
0
                                         chars_format format_flags) {
360
0
  strings_internal::ParsedFloat result;
361
362
  // Exit early if we're given an empty range.
363
0
  if (begin == end) return result;
364
365
  // Handle the infinity and NaN cases.
366
0
  if (ParseInfinityOrNan(begin, end, &result)) {
367
0
    return result;
368
0
  }
369
370
0
  const char* const mantissa_begin = begin;
371
0
  while (begin < end && *begin == '0') {
372
0
    ++begin;  // skip leading zeros
373
0
  }
374
0
  uint64_t mantissa = 0;
375
376
0
  ptrdiff_t exponent_adjustment = 0;
377
0
  bool mantissa_is_inexact = false;
378
0
  ptrdiff_t pre_decimal_digits = ConsumeDigits<base>(
379
0
      begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
380
0
  begin += pre_decimal_digits;
381
0
  ptrdiff_t digits_left;
382
0
  if (pre_decimal_digits >= DigitLimit<base>()) {
383
    // refuse to parse pathological inputs
384
0
    return result;
385
0
  } else if (pre_decimal_digits > MantissaDigitsMax<base>()) {
386
    // We dropped some non-fraction digits on the floor.  Adjust our exponent
387
    // to compensate.
388
0
    exponent_adjustment = pre_decimal_digits - MantissaDigitsMax<base>();
389
0
    digits_left = 0;
390
0
  } else {
391
0
    digits_left = MantissaDigitsMax<base>() - pre_decimal_digits;
392
0
  }
393
0
  if (begin < end && *begin == '.') {
394
0
    ++begin;
395
0
    if (mantissa == 0) {
396
      // If we haven't seen any nonzero digits yet, keep skipping zeros.  We
397
      // have to adjust the exponent to reflect the changed place value.
398
0
      const char* begin_zeros = begin;
399
0
      while (begin < end && *begin == '0') {
400
0
        ++begin;
401
0
      }
402
0
      ptrdiff_t zeros_skipped = begin - begin_zeros;
403
0
      if (zeros_skipped >= DigitLimit<base>()) {
404
        // refuse to parse pathological inputs
405
0
        return result;
406
0
      }
407
0
      exponent_adjustment -= zeros_skipped;
408
0
    }
409
0
    ptrdiff_t post_decimal_digits = ConsumeDigits<base>(
410
0
        begin, end, digits_left, &mantissa, &mantissa_is_inexact);
411
0
    begin += post_decimal_digits;
412
413
    // Since `mantissa` is an integer, each significant digit we read after
414
    // the decimal point requires an adjustment to the exponent. "1.23e0" will
415
    // be stored as `mantissa` == 123 and `exponent` == -2 (that is,
416
    // "123e-2").
417
0
    if (post_decimal_digits >= DigitLimit<base>()) {
418
      // refuse to parse pathological inputs
419
0
      return result;
420
0
    } else if (post_decimal_digits > digits_left) {
421
0
      exponent_adjustment -= digits_left;
422
0
    } else {
423
0
      exponent_adjustment -= post_decimal_digits;
424
0
    }
425
0
  }
426
  // If we've found no mantissa whatsoever, this isn't a number.
427
0
  if (mantissa_begin == begin) {
428
0
    return result;
429
0
  }
430
  // A bare "." doesn't count as a mantissa either.
431
0
  if (begin - mantissa_begin == 1 && *mantissa_begin == '.') {
432
0
    return result;
433
0
  }
434
435
0
  if (mantissa_is_inexact) {
436
    // We dropped significant digits on the floor.  Handle this appropriately.
437
0
    if (base == 10) {
438
      // If we truncated significant decimal digits, store the full range of the
439
      // mantissa for future big integer math for exact rounding.
440
0
      result.subrange_begin = mantissa_begin;
441
0
      result.subrange_end = begin;
442
0
    } else if (base == 16) {
443
      // If we truncated hex digits, reflect this fact by setting the low
444
      // ("sticky") bit.  This allows for correct rounding in all cases.
445
0
      mantissa |= 1;
446
0
    }
447
0
  }
448
0
  result.mantissa = mantissa;
449
450
0
  const char* const exponent_begin = begin;
451
0
  result.literal_exponent = 0;
452
0
  bool found_exponent = false;
453
0
  if (AllowExponent(format_flags) && begin < end &&
454
0
      IsExponentCharacter<base>(*begin)) {
455
0
    bool negative_exponent = false;
456
0
    ++begin;
457
0
    if (begin < end && *begin == '-') {
458
0
      negative_exponent = true;
459
0
      ++begin;
460
0
    } else if (begin < end && *begin == '+') {
461
0
      ++begin;
462
0
    }
463
0
    const char* const exponent_digits_begin = begin;
464
    // Exponent is always expressed in decimal, even for hexadecimal floats.
465
0
    begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax,
466
0
                               &result.literal_exponent, nullptr);
467
0
    if (begin == exponent_digits_begin) {
468
      // there were no digits where we expected an exponent.  We failed to read
469
      // an exponent and should not consume the 'e' after all.  Rewind 'begin'.
470
0
      found_exponent = false;
471
0
      begin = exponent_begin;
472
0
    } else {
473
0
      found_exponent = true;
474
0
      if (negative_exponent) {
475
0
        result.literal_exponent = -result.literal_exponent;
476
0
      }
477
0
    }
478
0
  }
479
480
0
  if (!found_exponent && RequireExponent(format_flags)) {
481
    // Provided flags required an exponent, but none was found.  This results
482
    // in a failure to scan.
483
0
    return result;
484
0
  }
485
486
0
  if (result.mantissa > 0) {
487
0
    const ptrdiff_t exponent = result.literal_exponent +
488
0
                               (DigitMagnitude<base>() * exponent_adjustment);
489
490
0
    if (exponent < (std::numeric_limits<int>::min)() ||
491
0
        exponent > (std::numeric_limits<int>::max)()) {
492
      // We cannot store the exponent in int. Fail by returning a result with
493
      // end default-initialized to nullptr.
494
0
      return result;
495
0
    }
496
497
0
    result.exponent = static_cast<int>(exponent);
498
0
  } else {
499
0
    result.exponent = 0;
500
0
  }
501
0
  result.end = begin;
502
503
  // Success!
504
0
  result.type = strings_internal::FloatType::kNumber;
505
506
0
  return result;
507
0
}
Unexecuted instantiation: absl::strings_internal::ParsedFloat absl::strings_internal::ParseFloat<10>(char const*, char const*, absl::chars_format)
Unexecuted instantiation: absl::strings_internal::ParsedFloat absl::strings_internal::ParseFloat<16>(char const*, char const*, absl::chars_format)
508
509
template ParsedFloat ParseFloat<10>(const char* begin, const char* end,
510
                                    chars_format format_flags);
511
template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
512
                                    chars_format format_flags);
513
514
}  // namespace strings_internal
515
ABSL_NAMESPACE_END
516
}  // namespace absl