Skip to content

Commit cb813a7

Browse files
committed
fixed UB
1 parent 1ad224e commit cb813a7

File tree

1 file changed

+21
-19
lines changed

1 file changed

+21
-19
lines changed

include/fast_float/ascii_number.h

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -523,33 +523,36 @@ parse_int_string(UC const *p, UC const *pend, T &value,
523523
return answer;
524524
}
525525

526-
union {
527-
uint8_t as_str[4];
528-
uint32_t as_int;
529-
} digits;
526+
uint32_t digits;
530527

531-
if (cpp20_and_in_constexpr()) {
532-
digits.as_int = 0;
528+
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST
529+
if (std::is_constant_evaluated()) {
530+
uint8_t str[4]{};
533531
for (size_t j = 0; j < 4 && j < len; ++j) {
534-
digits.as_str[j] = static_cast<uint8_t>(p[j]);
532+
str[j] = static_cast<uint8_t>(p[j]);
535533
}
536-
} else if (len >= 4) {
537-
memcpy(&digits.as_int, p, 4);
534+
digits = std::bit_cast<uint32_t>(str);
535+
}
536+
#else
537+
if (false) {
538+
}
539+
#endif
540+
else if (len >= 4) {
541+
::memcpy(&digits, p, 4);
538542
} else {
539543
uint32_t b0 = static_cast<uint8_t>(p[0]);
540544
uint32_t b1 = (len > 1) ? static_cast<uint8_t>(p[1]) : 0xFFu;
541545
uint32_t b2 = (len > 2) ? static_cast<uint8_t>(p[2]) : 0xFFu;
542546
uint32_t b3 = 0xFFu;
543547
#if FASTFLOAT_IS_BIG_ENDIAN
544-
digits.as_int = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
548+
digits = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
545549
#else
546-
digits.as_int = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
550+
digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
547551
#endif
548552
}
549553

550554
uint32_t magic =
551-
((digits.as_int + 0x46464646u) | (digits.as_int - 0x30303030u)) &
552-
0x80808080u;
555+
((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u;
553556
uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32
554557
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
555558
nd = (uint32_t)std::min((size_t)nd, len);
@@ -578,18 +581,17 @@ parse_int_string(UC const *p, UC const *pend, T &value,
578581
return answer;
579582
}
580583

581-
digits.as_int ^= 0x30303030u;
582-
digits.as_int <<= ((4 - nd) * 8);
584+
digits ^= 0x30303030u;
585+
digits <<= ((4 - nd) * 8);
583586

584-
uint32_t check = ((digits.as_int >> 24) & 0xff) |
585-
((digits.as_int >> 8) & 0xff00) |
586-
((digits.as_int << 8) & 0xff0000);
587+
uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) |
588+
((digits << 8) & 0xff0000);
587589
if (check > 0x00020505) {
588590
answer.ec = std::errc::result_out_of_range;
589591
answer.ptr = p + nd;
590592
return answer;
591593
}
592-
value = (uint8_t)((0x640a01 * digits.as_int) >> 24);
594+
value = (uint8_t)((0x640a01 * digits) >> 24);
593595
answer.ec = std::errc();
594596
answer.ptr = p + nd;
595597
return answer;

0 commit comments

Comments
 (0)