]> git.ipfire.org Git - pakfire.git/commitdiff
string: Refactor pakfire_string_format to be more robust
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 18 Aug 2022 10:32:08 +0000 (10:32 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 18 Aug 2022 10:32:08 +0000 (10:32 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/string.h
src/libpakfire/string.c
tests/libpakfire/string.c

index 6baeaee21176c195d474fdfae649bf24654dbd3f..b9fa7d1f3c6162b01a6bd9ad6578bdb79d9a144a 100644 (file)
 
 #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);
index 60b78ab6882b5f86a1b3ea7b50ecd6e5833c4157..3e79c65c74f6668fd064d4aa992f215fa01375b7 100644 (file)
@@ -19,6 +19,7 @@
 #############################################################################*/
 
 #include <errno.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <pakfire/string.h>
 
+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) {
index 238e6669aa67f36df8e784a7d65278b0253f181c..d5b8835c481076622a8992f85f48621135dc4a2f 100644 (file)
 
 #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);