fix: ::toupper/::tolower UB on signed char at 5 remaining call sites

std::toupper(int) and std::tolower(int) have undefined behavior when
passed a negative value. These sites passed raw signed char without
casting to unsigned char first, unlike the rest of the codebase which
already uses the correct pattern. Affects auth (account names), world
packets, and mount sound path matching.
This commit is contained in:
Kelsi 2026-03-29 19:58:36 -07:00
parent d776226fd1
commit 59bbeaca62
4 changed files with 7 additions and 5 deletions

View file

@ -495,7 +495,7 @@ MountType MountSoundManager::detectMountType(uint32_t creatureDisplayId) const {
MountFamily MountSoundManager::detectMountFamilyFromPath(const std::string& modelPath) const {
// Convert path to lowercase for matching
std::string lower = modelPath;
for (char& c : lower) c = std::tolower(c);
for (char& c : lower) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
// Check creature model path for family keywords
if (lower.find("tallstrider") != std::string::npos ||

View file

@ -57,7 +57,8 @@ bool detectOutboundIPv4(std::array<uint8_t, 4>& outIp) {
network::Packet LogonChallengePacket::build(const std::string& account, const ClientInfo& info) {
// Convert account to uppercase
std::string upperAccount = account;
std::transform(upperAccount.begin(), upperAccount.end(), upperAccount.begin(), ::toupper);
std::transform(upperAccount.begin(), upperAccount.end(), upperAccount.begin(),
[](unsigned char c) { return static_cast<char>(std::toupper(c)); });
// Calculate payload size (everything after cmd + error + size)
// game(4) + version(3) + build(2) + platform(4) + os(4) + locale(4) +

View file

@ -117,8 +117,9 @@ std::vector<uint8_t> SRP::computeAuthHash(const std::string& username,
// Convert to uppercase (WoW requirement)
std::string upperUser = username;
std::string upperPass = password;
std::transform(upperUser.begin(), upperUser.end(), upperUser.begin(), ::toupper);
std::transform(upperPass.begin(), upperPass.end(), upperPass.begin(), ::toupper);
auto toUpper = [](unsigned char c) { return static_cast<char>(std::toupper(c)); };
std::transform(upperUser.begin(), upperUser.end(), upperUser.begin(), toUpper);
std::transform(upperPass.begin(), upperPass.end(), upperPass.begin(), toUpper);
// H(I:P)
std::string combined = upperUser + ":" + upperPass;

View file

@ -80,7 +80,7 @@ network::Packet AuthSessionPacket::build(uint32_t build,
// Convert account name to uppercase
std::string upperAccount = accountName;
std::transform(upperAccount.begin(), upperAccount.end(),
upperAccount.begin(), ::toupper);
upperAccount.begin(), [](unsigned char c) { return static_cast<char>(std::toupper(c)); });
LOG_INFO("Building CMSG_AUTH_SESSION for account: ", upperAccount);