test(relinker): pin EH sdata4 funcrel signed overflow row

Standalone EH table fixture after the unwind record loop: CIE zPLR with
LSDA encoding 0x4B (sdata4 funcrel), FDE augmentation 0xFFFFEFFF with
functionBase at the FDE begin 0x1000. The signed branch of
EhFrameReader::encoded must reject it with "unwind pointer address
overflowed".

Co-Authored-By: Claude Haiku 5.5 <[email protected]>
This commit is contained in:
AdriàandClaude Haiku 5.5 committed 2026-10-31 08:15:42 +01:00
1 parent 828ac0b2ae
commit fe13b4d2df
1 file changed
+31 -1
@@ -4,6 +4,7 @@
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>
static void Require(bool ok) { if (!ok) throw std::runtime_error("Unwind record validation failed"); }
@@ -146,6 +147,35 @@ int main() {
sdata8Rejected = std::string(error.what()).find("unwind pointer address overflowed") != std::string::npos;
}
Require(sdata8Rejected);
std::cout << "21 unwind record cases passed\n";
std::vector<std::uint8_t> lsdaBytes(0x400, 0);
Io::WriteU32(lsdaBytes, 0x200, 25);
lsdaBytes[0x208] = 1;
const std::uint8_t ciePrefix[] = {'z', 'P', 'L', 'R', 0, 1, 0, 0x78, 11, 0};
std::copy(std::begin(ciePrefix), std::end(ciePrefix), lsdaBytes.begin() + 0x209);
lsdaBytes[0x212] = 0;
Io::WriteU64(lsdaBytes, 0x213, 0x1000);
lsdaBytes[0x21B] = 0x4B;
lsdaBytes[0x21C] = 0;
Io::WriteU32(lsdaBytes, 0x220, 29);
Io::WriteU32(lsdaBytes, 0x224, 0x24);
Io::WriteU64(lsdaBytes, 0x228, 0x1000);
Io::WriteU64(lsdaBytes, 0x230, 0x20);
lsdaBytes[0x238] = 4;
Io::WriteU32(lsdaBytes, 0x239, 0xFFFFEFFF);
lsdaBytes[0x300] = 1;
lsdaBytes[0x302] = 3;
Io::WriteU64(lsdaBytes, 0x304, 0x200);
Io::WriteU32(lsdaBytes, 0x30C, 1);
Io::WriteU64(lsdaBytes, 0x310, 0x1000);
Io::WriteU64(lsdaBytes, 0x318, 0x220);
Domain::ProgramHeader lsdaLoad{}; lsdaLoad.Type = 1; lsdaLoad.Flags = 4; lsdaLoad.FileSize = lsdaBytes.size(); lsdaLoad.MemorySize = lsdaBytes.size(); lsdaLoad.Alignment = 8;
Domain::ProgramHeader lsdaEh = lsdaLoad; lsdaEh.Type = 0x6474E550; lsdaEh.Offset = 0x300; lsdaEh.MappedAddress = 0x300; lsdaEh.FileSize = 32; lsdaEh.MemorySize = 32; lsdaEh.Alignment = 4;
bool lsdaOverflowRejected = false;
try { Relinker::UnusedNidFilter::ReadExceptionFunctions(lsdaBytes, {lsdaLoad, lsdaEh}, {}, {}); }
catch (const Domain::RelinkerException& error) {
lsdaOverflowRejected = std::string(error.what()).find("unwind pointer address overflowed") != std::string::npos;
}
Require(lsdaOverflowRejected);
std::cout << "22 unwind record cases passed\n";
} catch (const std::exception& error) { std::cerr << error.what() << '\n'; return 1; }
}