qbsp: fix memory/.bsp file corruption if map contains a texture name longer than 31 characters
This commit is contained in:
parent
91734ac8f6
commit
8362ffa385
|
|
@ -80,7 +80,19 @@ size_t ExportMapTexinfo(size_t texinfonum)
|
||||||
dest.flags = src.flags;
|
dest.flags = src.flags;
|
||||||
dest.miptex = src.miptex;
|
dest.miptex = src.miptex;
|
||||||
dest.vecs = src.vecs;
|
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;
|
dest.value = map.miptex[src.miptex].value;
|
||||||
|
|
||||||
src.outputnum = i;
|
src.outputnum = i;
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -268,9 +268,25 @@ TEST_CASE("nodraw_light" * doctest::test_suite("testmaps_q2"))
|
||||||
CHECK(texinfo->flags.native == (Q2_SURF_LIGHT | Q2_SURF_NODRAW));
|
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);
|
CHECK(GAME_QUAKE_II == bsp.loadversion->game->id);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue