From c86188226a96deccbf7f03a9efe956fb1122af61 Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Sun, 27 Oct 2024 10:59:36 +0100 Subject: [PATCH] Fix Format function to not cut of last character This fixes broke game save The beginning of a saved game looked like this: 00000000: 6c6f 6361 6c20 6f6c 6443 7265 6174 6555 local oldCreateU 00000010: 6e69 7420 3d20 4372 6561 7465 556e 6974 nit = CreateUnit 00000020: 006c 6f63 616c 206f 6c64 5365 7452 6573 .local oldSetRes 00000030: 6f75 7263 6573 4865 6c64 203d 2053 6574 ourcesHeld = Set 00000040: 5265 736f 7572 6365 7348 656c 6400 6c6f ResourcesHeld.lo The newlines are replaced by null-characters so games could not be loaded again --- CMakeLists.txt | 1 + src/include/stratagus.h | 3 ++- tests/stratagus/test_format.cpp | 48 +++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/stratagus/test_format.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b878c5499..087a1c3d0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -535,6 +535,7 @@ set(stratagus_tests_SRCS tests/main.cpp tests/stratagus/test_action_built.cpp tests/stratagus/test_depend.cpp + tests/stratagus/test_format.cpp tests/stratagus/test_luacallback.cpp tests/stratagus/test_missile_fire.cpp tests/stratagus/test_trigger.cpp diff --git a/src/include/stratagus.h b/src/include/stratagus.h index f780dc599f..9f0a8f5427 100644 --- a/src/include/stratagus.h +++ b/src/include/stratagus.h @@ -118,7 +118,8 @@ std::string Format(const char *format, Ts... args) #endif const auto len = snprintf(nullptr, 0, format, args...); std::string res(len, '\0'); - snprintf(res.data(), res.size(), format, args...); + // len+1: writing a '\0' over the existing '\0' should be fine + snprintf(res.data(), len + 1, format, args...); #ifndef _MSC_VER # pragma GCC diagnostic pop #endif diff --git a/tests/stratagus/test_format.cpp b/tests/stratagus/test_format.cpp new file mode 100644 index 0000000000..88131dfd61 --- /dev/null +++ b/tests/stratagus/test_format.cpp @@ -0,0 +1,48 @@ +// _________ __ __ +// / _____// |_____________ _/ |______ ____ __ __ ______ +// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/ +// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ | +// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ > +// \/ \/ \//_____/ \/ +// ______________________ ______________________ +// T H E W A R B E G I N S +// Stratagus - A free fantasy real time strategy game engine +// +/**@name test_format.cpp - Test file for function Format. */ +// +// (c) Copyright 2024 by Matthias Schwarzott +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; only version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// + +#include + +#include "stratagus.h" + +TEST_CASE("Format") +{ + CHECK("" == Format("")); + CHECK("1" == Format("1")); + CHECK("12" == Format("12")); + CHECK("12\n" == Format("12\n")); + CHECK("abc\n" == Format("%s", "abc\n")); + CHECK("abc\n" == Format("%s\n", "abc")); + CHECK("12345" == Format("%d", 12345)); + CHECK(" x" == Format("%*s", 10, "x")); + std::string result = Format("%*s", 100, "x"); + REQUIRE(result.size() == 100); + CHECK(result[98] == ' '); + CHECK(result[99] == 'x'); +}