Skip to content

Commit 1743bba

Browse files
plafosseclaude
andcommitted
GNU3 Demangler: fix float literal decoding to be platform-independent
Decode big-endian hex via union type-punning instead of casting bytes into native floats. Falls back to raw hex for NaN/Inf, long double, and __float128. Remove unused HexToDec helper. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent af93db2 commit 1743bba

File tree

1 file changed

+44
-40
lines changed

1 file changed

+44
-40
lines changed

demangler/gnu3/demangle_gnu3.cpp

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -226,17 +226,47 @@ static BNNameType GetNameType(char elm1, char elm2)
226226
}
227227
}
228228

229-
static int8_t HexToDec(char c)
229+
230+
231+
232+
// Decode a big-endian hex string into a float or double.
233+
// Returns the decimal string representation, or the raw hex with a type
234+
// prefix if decoding fails or the result is NaN/Inf.
235+
static string DecodeHexFloat(const string& hex, size_t byteCount)
230236
{
231-
if (isdigit(c))
237+
if (hex.size() != byteCount * 2)
238+
return hex;
239+
240+
// Parse big-endian hex into an integer, then reinterpret as float/double
241+
uint64_t bits = 0;
242+
for (size_t i = 0; i < hex.size(); i++)
243+
{
244+
char c = hex[i];
245+
uint64_t nibble;
246+
if (c >= '0' && c <= '9') nibble = c - '0';
247+
else if (c >= 'a' && c <= 'f') nibble = c - 'a' + 10;
248+
else if (c >= 'A' && c <= 'F') nibble = c - 'A' + 10;
249+
else return hex;
250+
bits = (bits << 4) | nibble;
251+
}
252+
253+
if (byteCount == 4)
232254
{
233-
return c - '0';
255+
union { uint32_t i; float f; } u;
256+
u.i = (uint32_t)bits;
257+
if (std::isnan(u.f) || std::isinf(u.f))
258+
return "(float)" + hex;
259+
return to_string(u.f);
234260
}
235-
else if(islower(c) && c <= 'f')
261+
else if (byteCount == 8)
236262
{
237-
return c - 'a' + 10;
263+
union { uint64_t i; double d; } u;
264+
u.i = bits;
265+
if (std::isnan(u.d) || std::isinf(u.d))
266+
return "(double)" + hex;
267+
return to_string(u.d);
238268
}
239-
return -1;
269+
return hex;
240270
}
241271

242272

@@ -994,8 +1024,6 @@ string DemangleGNU3::DemanglePrimaryExpression()
9941024
char elm1 = '\0';
9951025
string out;
9961026
QualifiedName tmpList;
997-
string valueString;
998-
float f; double d; long double ld;
9991027
bool oldTopLevel;
10001028
//expr-primary
10011029
if (m_reader.PeekString(2) == "_Z")
@@ -1042,41 +1070,17 @@ string DemangleGNU3::DemanglePrimaryExpression()
10421070
else
10431071
throw DemangleException();
10441072
break;
1045-
case 'd': //double
1046-
valueString = m_reader.ReadString(8);
1047-
1048-
for (size_t i = 0; i < valueString.size(); i+=2)
1049-
{
1050-
((unsigned char*)&d)[i/2] = (HexToDec(valueString[i]) << 16) + HexToDec(valueString[i+1]);
1051-
}
1052-
out += to_string(d);
1073+
case 'd': //double (16 hex chars = 8 bytes)
1074+
out += DecodeHexFloat(m_reader.ReadString(16), 8);
10531075
break;
1054-
case 'e': //long double
1055-
valueString = m_reader.ReadString(10);
1056-
1057-
for (size_t i = 0; i < valueString.size(); i+=2)
1058-
{
1059-
((unsigned char*)&ld)[i/2] = (HexToDec(valueString[i]) << 16) + HexToDec(valueString[i+1]);
1060-
}
1061-
out += to_string(ld);
1076+
case 'e': //long double (20 hex chars = 10 bytes, platform-dependent layout)
1077+
out += "(long double)" + m_reader.ReadString(20);
10621078
break;
1063-
case 'f': //float
1064-
valueString = m_reader.ReadString(4);
1065-
1066-
for (size_t i = 0; i < valueString.size(); i+=2)
1067-
{
1068-
((unsigned char*)&f)[i/2] = (HexToDec(valueString[i]) << 16) + HexToDec(valueString[i+1]);
1069-
}
1070-
out += to_string(f);
1079+
case 'f': //float (8 hex chars = 4 bytes)
1080+
out += DecodeHexFloat(m_reader.ReadString(8), 4);
10711081
break;
1072-
case 'g': //float_128
1073-
valueString = m_reader.ReadString(16); //We read 16 but then just throw away
1074-
1075-
for (size_t i = 0; i < 10; i+=2)
1076-
{
1077-
((unsigned char*)&ld)[i/2] = (HexToDec(valueString[i]) << 16) + HexToDec(valueString[i+1]);
1078-
}
1079-
out += to_string(ld);
1082+
case 'g': //float_128 (32 hex chars = 16 bytes)
1083+
out += "(__float128)" + m_reader.ReadString(32);
10801084
break;
10811085
case 'l': out = DemangleNumberAsString() + "l"; break; //long
10821086
case 'x': out = DemangleNumberAsString() + "ll"; break; //long long

0 commit comments

Comments
 (0)