Keep a non-ASCII last letter in the server browser's tag name

tag_text dropped a trailing lead byte even when its character was whole, so
"Skate Café" was listed as "Skate Caf". The browser shows the tag name until
the server answers a query, so hosts without a forwarded query port kept it.
This commit is contained in:
xThrasherrr committed 2026-10-04 13:27:55 -06:00
1 parent 7e774f4f71
commit 5e557d184e
2 files changed
+18 -8

No files matched your search

@@ -856,6 +856,17 @@ void dedicated_server_codec() {
check(row && row->dedicated && row->name == "Big friendly server" && row->map == ad.map && row->players == 3 &&
row->capacity == 16 && row->password_required && row->code == format_invite({server, ad.secret}),
"Server tags did not round trip");
// A whole last character is kept, and one the byte limit cuts through is dropped whole.
const auto accented = read_server_tags(dingosdk::server::server_tags({"Skate Caf\xC3\xA9", "Caf\xC3\xA9", 1, 8, false, true, 1}), server);
check(accented && accented->name == "Skate Caf\xC3\xA9" && accented->map == "Caf\xC3\xA9",
"A server name lost its non-ASCII last letter");
for (std::size_t lead = 0; lead < 3; ++lead) {
std::string euros(lead, 'a');
for (int i = 0; i < 50; ++i) euros += "\xE2\x82\xAC";
const auto cut = dingosdk::server::server_tags({euros, "Caf\xC3\xA9", 1, 8, false, true, 1});
const auto name = cut.substr(cut.find(",n") + 2);
check(cut.size() < 128 && name.size() > lead && (name.size() - lead) % 3 == 0, "A server name was cut inside a character");
}
check(!read_server_tags(tags, player), "A player's ID read as a server");
check(!read_server_tags("reskate,v1,k1,c4", server), "An incompatible server version listed");
}
+7 -8
View File
@@ -1,4 +1,5 @@
#include "steam_server.h"
#include "server_text.h"
#include "Extension/Multiplayer/Net/protocol.h"
#ifdef _WIN32
#include <Windows.h>
@@ -12,6 +13,7 @@
#include <thread>
#include <unistd.h>
#endif
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <optional>
@@ -45,14 +47,11 @@ struct SteamIP {
// Tags are comma separated, so a name loses its commas; the whole list must
// stay under Steam's 128 byte limit.
std::string tag_text(std::string_view text, std::size_t limit) {
std::string result;
for (const char c : text) {
if (result.size() >= limit) break;
result += c == ',' ? ' ' : c;
}
// Never end inside a UTF-8 sequence.
while (!result.empty() && (static_cast<unsigned char>(result.back()) & 0xC0) == 0x80) result.pop_back();
if (!result.empty() && (static_cast<unsigned char>(result.back()) & 0xC0) == 0xC0) result.pop_back();
std::string result(text);
std::replace(result.begin(), result.end(), ',', ' ');
// Cut at the limit only, and never through a character: a whole last character
// is kept ("Café" stays "Café"), one the limit splits is dropped.
cut_text(result, limit);
return result;
}
// Steam's library prints its own crash-reporting notes ("Setting breakpad