qbsp: fix memory/.bsp file corruption if map contains a texture name longer than 31 characters

This commit is contained in:
Eric Wasylishen 2023-09-24 19:42:42 -06:00
parent 91734ac8f6
commit 8362ffa385
4 changed files with 53 additions and 3 deletions

View File

@ -80,7 +80,19 @@ size_t ExportMapTexinfo(size_t texinfonum)
dest.flags = src.flags;
dest.miptex = src.miptex;
dest.vecs = src.vecs;
strcpy(dest.texture.data(), map.texinfoTextureName(texinfonum).c_str());
const std::string &src_name = map.texinfoTextureName(texinfonum);
if (src_name.size() > (dest.texture.size() - 1)) {
logging::print("WARNING: texture name '{}' exceeds maximum length {} and will be truncated\n",
src_name, dest.texture.size() - 1);
}
for (size_t i = 0; i < (dest.texture.size() - 1); ++i) {
if (i < src_name.size())
dest.texture[i] = src_name[i];
else
dest.texture[i] = '\0';
}
dest.texture[dest.texture.size() - 1] = '\0';
dest.value = map.miptex[src.miptex].value;
src.outputnum = i;

View File

@ -0,0 +1,22 @@
// Game: Quake 2
// Format: Quake2
// entity 0
{
"classname" "worldspawn"
"_tb_mod" "q2_wal_metadata"
"_tb_textures" "textures/long_folder_name_test"
// brush 0
{
( -64 -64 -16 ) ( -64 -63 -16 ) ( -64 -64 -15 ) long_folder_name_test/long_texture_name_test 0 0 0 1 1
( -64 -64 -16 ) ( -64 -64 -15 ) ( -63 -64 -16 ) long_folder_name_test/long_texture_name_test 0 0 0 1 1
( -64 -64 -16 ) ( -63 -64 -16 ) ( -64 -63 -16 ) long_folder_name_test/long_texture_name_test 0 0 0 1 1
( 64 64 16 ) ( 64 65 16 ) ( 65 64 16 ) long_folder_name_test/long_texture_name_test 0 0 0 1 1
( 64 64 16 ) ( 65 64 16 ) ( 64 64 17 ) long_folder_name_test/long_texture_name_test 0 0 0 1 1
( 64 64 16 ) ( 64 64 17 ) ( 64 65 16 ) long_folder_name_test/long_texture_name_test 0 0 0 1 1
}
}
// entity 1
{
"classname" "info_player_start"
"origin" "-32 0 40"
}

View File

@ -268,9 +268,25 @@ TEST_CASE("nodraw_light" * doctest::test_suite("testmaps_q2"))
CHECK(texinfo->flags.native == (Q2_SURF_LIGHT | Q2_SURF_NODRAW));
}
TEST_CASE("nodraw_detail_light" * doctest::test_suite("testmaps_q2"))
TEST_CASE("q2_long_texture_name" * doctest::test_suite("testmaps_q2"))
{
const auto [bsp, bspx, prt] = LoadTestmapQ2("q2_nodraw_detail_light.map", {"-includeskip"});
const auto [bsp, bspx, prt] = LoadTestmapQ2("q2_long_texture_name.map");
CHECK(GAME_QUAKE_II == bsp.loadversion->game->id);
auto *topface = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {0, 0, 16}, {0, 0, 1});
REQUIRE(nullptr != topface);
// this won't work in game, but we're mostly checking for lack of memory corruption
// (a warning is issued)
auto *texinfo = Face_Texinfo(&bsp, topface);
CHECK(std::string(texinfo->texture.data()) == "long_folder_name_test/long_text");
CHECK(texinfo->nexttexinfo == -1);
}
TEST_CASE("nodraw_light" * doctest::test_suite("testmaps_q2"))
{
const auto [bsp, bspx, prt] = LoadTestmapQ2("q2_nodraw_light.map", {"-includeskip"});
CHECK(GAME_QUAKE_II == bsp.loadversion->game->id);