From: Michael Tremer Date: Thu, 18 Aug 2022 10:32:08 +0000 (+0000) Subject: string: Refactor pakfire_string_format to be more robust X-Git-Tag: 0.9.28~451 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=73dab74581a7665a40585511a15ba2f0ebf930c6;p=pakfire.git string: Refactor pakfire_string_format to be more robust Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/include/pakfire/string.h b/src/libpakfire/include/pakfire/string.h index 6baeaee21..b9fa7d1f3 100644 --- a/src/libpakfire/include/pakfire/string.h +++ b/src/libpakfire/include/pakfire/string.h @@ -23,7 +23,17 @@ #ifdef PAKFIRE_PRIVATE -#define pakfire_string_format(s, fmt, ...) snprintf(s, sizeof(s) - 1, fmt, __VA_ARGS__) +/* + Formats a string and stores it in the given buffer. +*/ +#define pakfire_string_format(s, format, ...) \ + __pakfire_string_format(s, sizeof(s), format, __VA_ARGS__) +int __pakfire_string_format(char* s, const size_t length, const char* format, ...) + __attribute__((format(printf, 3, 4)));;; + +/* + Simpler version when a string needs to be copied. +*/ #define pakfire_string_set(s, value) pakfire_string_format(s, "%s", value) int pakfire_string_startswith(const char* s, const char* prefix); diff --git a/src/libpakfire/string.c b/src/libpakfire/string.c index 60b78ab68..3e79c65c7 100644 --- a/src/libpakfire/string.c +++ b/src/libpakfire/string.c @@ -19,6 +19,7 @@ #############################################################################*/ #include +#include #include #include #include @@ -26,6 +27,28 @@ #include +int __pakfire_string_format(char* s, const size_t length, const char* format, ...) { + va_list args; + + // Write string to buffer + va_start(args, format); + const ssize_t required = vsnprintf(s, length, format, args); + va_end(args); + + // Catch any errors + if (required < 0) + return 1; + + // Check if the entire string could be written + if ((size_t)required >= length) { + errno = ENOMEM; + return 1; + } + + // Success + return 0; +} + int pakfire_string_startswith(const char* s, const char* prefix) { // Validate input if (!s || !prefix) { diff --git a/tests/libpakfire/string.c b/tests/libpakfire/string.c index 238e6669a..d5b8835c4 100644 --- a/tests/libpakfire/string.c +++ b/tests/libpakfire/string.c @@ -26,6 +26,24 @@ #include "../testsuite.h" +static int test_string_set(const struct test* t) { + // Allocate a small buffer + char buffer[4]; + + // Write a string into a buffer which just has just enough space + ASSERT_SUCCESS(pakfire_string_set(buffer, "ABC")); + ASSERT_STRING_EQUALS(buffer, "ABC"); + + // Write a string which would not fit + ASSERT_ERRNO(pakfire_string_set(buffer, "1234"), ENOMEM); + ASSERT_STRING_EQUALS(buffer, "123"); + + return EXIT_SUCCESS; + +FAIL: + return EXIT_FAILURE; +} + static int test_string_startswith(const struct test* t) { ASSERT_TRUE(pakfire_string_startswith("ABC", "A")); ASSERT_FALSE(pakfire_string_startswith("ABC", "B")); @@ -274,6 +292,7 @@ FAIL: } int main(int argc, const char* argv[]) { + testsuite_add_test(test_string_set); testsuite_add_test(test_string_startswith); testsuite_add_test(test_string_endswith); testsuite_add_test(test_string_matches);