From 7313246786857168dac4c3191e80843b58e294c3 Mon Sep 17 00:00:00 2001 From: Derek Mauro Date: Mon, 9 Feb 2026 10:14:52 -0800 Subject: [PATCH] Fix sign-extension issue in absl::HexStringToBytes() Fixes #2006 PiperOrigin-RevId: 867661246 Change-Id: Ia4ad66620e0298287993b228bf604b8b75302c7d --- absl/strings/escaping.cc | 12 +++++++----- absl/strings/escaping_test.cc | 4 ++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc index 2f8cbc10..228e5274 100644 --- a/absl/strings/escaping.cc +++ b/absl/strings/escaping.cc @@ -827,7 +827,7 @@ bool Base64UnescapeInternal(const char* absl_nullable src, size_t slen, } /* clang-format off */ -constexpr std::array kHexValueLenient = { +constexpr std::array kHexValueLenient = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -846,7 +846,7 @@ constexpr std::array kHexValueLenient = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -constexpr std::array kHexValueStrict = { +constexpr std::array kHexValueStrict = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -874,7 +874,7 @@ void HexStringToBytesInternal(const char* absl_nullable from, T to, size_t num) { for (size_t i = 0; i < num; i++) { to[i] = static_cast(kHexValueLenient[from[i * 2] & 0xFF] << 4) + - (kHexValueLenient[from[i * 2 + 1] & 0xFF]); + static_cast(kHexValueLenient[from[i * 2 + 1] & 0xFF]); } } @@ -992,8 +992,10 @@ bool HexStringToBytes(absl::string_view hex, std::string* absl_nonnull bytes) { output, num_bytes, [hex](char* buf, size_t buf_size) { auto hex_p = hex.cbegin(); for (size_t i = 0; i < buf_size; ++i) { - int h1 = absl::kHexValueStrict[static_cast(*hex_p++)]; - int h2 = absl::kHexValueStrict[static_cast(*hex_p++)]; + int h1 = absl::kHexValueStrict[static_cast( + static_cast(*hex_p++))]; + int h2 = absl::kHexValueStrict[static_cast( + static_cast(*hex_p++))]; if (h1 == -1 || h2 == -1) { return size_t{0}; } diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc index 4786c882..08618aa3 100644 --- a/absl/strings/escaping_test.cc +++ b/absl/strings/escaping_test.cc @@ -733,6 +733,10 @@ TEST(Escaping, HexStringToBytesBackToHex) { bytes = "abc"; EXPECT_TRUE(absl::HexStringToBytes("", &bytes)); EXPECT_EQ("", bytes); // Results in empty output. + + // Ensure there is no sign extension bug on a signed char. + hex.assign("\xC8" "b", 2); + EXPECT_FALSE(absl::HexStringToBytes(hex, &bytes)); } TEST(HexAndBack, HexStringToBytes_and_BytesToHexString) {