Merge branch 'gstring-inline-null-handling' into 'main'

gstring: Gracefully handle NULL parameters in inline append

Closes #2890

See merge request GNOME/glib!3217
This commit is contained in:
Philip Withnall
2023-01-26 15:46:03 +00:00
3 changed files with 181 additions and 5 deletions

View File

@@ -34,6 +34,7 @@
#include <glib/gtypes.h>
#include <glib/gunicode.h>
#include <glib/gbytes.h>
#include <glib/gstrfuncs.h>
#include <glib/gutils.h> /* for G_CAN_INLINE */
#include <string.h>
@@ -182,7 +183,9 @@ g_string_append_c_inline (GString *gstring,
g_string_insert_c (gstring, -1, c);
return gstring;
}
#define g_string_append_c(gstr,c) g_string_append_c_inline (gstr, c)
#define g_string_append_c(gstr,c) \
g_string_append_c_inline (gstr, c)
G_ALWAYS_INLINE
static inline GString *
@@ -190,6 +193,12 @@ g_string_append_len_inline (GString *gstring,
const char *val,
gssize len)
{
if G_UNLIKELY (gstring == NULL)
return g_string_append_len (gstring, val, len);
if G_UNLIKELY (val == NULL)
return (len != 0) ? g_string_append_len (gstring, val, len) : gstring;
if (len < 0)
len = strlen (val);
@@ -207,7 +216,9 @@ g_string_append_len_inline (GString *gstring,
else
return g_string_insert_len (gstring, -1, val, len);
}
#define g_string_append_len(gstr,val,len) g_string_append_len_inline (gstr, val, len)
#define g_string_append_len(gstr, val, len) \
g_string_append_len_inline (gstr, val, len)
G_ALWAYS_INLINE
static inline GString *
@@ -219,13 +230,24 @@ g_string_truncate_inline (GString *gstring,
return gstring;
}
#define g_string_truncate(gstr,len) g_string_truncate_inline (gstr, len)
#define g_string_truncate(gstr, len) \
g_string_truncate_inline (gstr, len)
#if G_GNUC_CHECK_VERSION (2, 0)
#define g_string_append(gstr,val) g_string_append_len (gstr, val, __builtin_constant_p (val) ? (gssize) strlen (val) : (gssize) -1)
#define g_string_append(gstr, val) \
(__builtin_constant_p (val) ? \
G_GNUC_EXTENSION ({ \
const char * const __val = (val); \
g_string_append_len (gstr, __val, \
G_LIKELY (__val != NULL) ? \
(gssize) strlen (_G_STR_NONNULL (__val)) \
: (gssize) -1); \
}) \
: \
g_string_append_len (gstr, val, (gssize) -1))
#endif
#endif /* G_GNUC_CHECK_VERSION (2, 0) */
#endif /* G_CAN_INLINE */

View File

@@ -321,6 +321,106 @@ test_str_equal (void)
g_free (str_b);
}
static void
test_string_append (void)
{
GString *string;
char *tmp;
int i;
tmp = g_strdup ("more");
/* append */
string = g_string_new ("firsthalf");
g_string_append (string, "last");
(g_string_append) (string, "half");
g_assert_cmpstr (string->str, ==, "firsthalflasthalf");
i = 0;
g_string_append (string, &tmp[i++]);
(g_string_append) (string, &tmp[i++]);
g_assert_true (i == 2);
g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore");
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*string != NULL*failed*");
g_assert_null (g_string_append (NULL, NULL));
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*string != NULL*failed*");
g_assert_null ((g_string_append) (NULL, NULL));
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true (g_string_append (string, NULL) == string);
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true ((g_string_append) (string, NULL) == string);
g_test_assert_expected_messages ();
g_string_free (string, TRUE);
/* append_len */
string = g_string_new ("firsthalf");
g_string_append_len (string, "lasthalfjunkjunk", strlen ("last"));
(g_string_append_len) (string, "halfjunkjunk", strlen ("half"));
g_string_append_len (string, "more", -1);
(g_string_append_len) (string, "ore", -1);
g_assert_true (g_string_append_len (string, NULL, 0) == string);
g_assert_true ((g_string_append_len) (string, NULL, 0) == string);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*string != NULL*failed*");
g_assert_null (g_string_append_len (NULL, NULL, -1));
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*string != NULL*failed*");
g_assert_null ((g_string_append_len) (NULL, NULL, -1));
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true (g_string_append_len (string, NULL, -1) == string);
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true ((g_string_append_len) (string, NULL, -1) == string);
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true (g_string_append_len (string, NULL, 1) == string);
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true ((g_string_append_len) (string, NULL, 1) == string);
g_test_assert_expected_messages ();
g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore");
char c = 'A';
g_string_append_c (string, c++);
(g_string_append_c) (string, c++);
g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreoreAB");
i = string->len;
g_string_truncate (string, --i);
(g_string_truncate) (string, --i);
g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore");
g_string_free (string, TRUE);
}
int
main (int argc, char *argv[])
{
@@ -344,6 +444,7 @@ main (int argc, char *argv[])
g_test_add_func ("/C++/clear-pointer", test_clear_pointer);
g_test_add_func ("/C++/steal-pointer", test_steal_pointer);
g_test_add_func ("/C++/str-equal", test_str_equal);
g_test_add_func ("/C++/string-append", test_string_append);
return g_test_run ();
}

View File

@@ -225,6 +225,26 @@ test_string_append (void)
g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore");
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*string != NULL*failed*");
g_assert_null (g_string_append (NULL, NULL));
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*string != NULL*failed*");
g_assert_null ((g_string_append) (NULL, NULL));
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true (g_string_append (string, NULL) == string);
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true ((g_string_append) (string, NULL) == string);
g_test_assert_expected_messages ();
g_string_free (string, TRUE);
g_free (tmp);
@@ -235,6 +255,39 @@ test_string_append (void)
g_string_append_len (string, "more", -1);
(g_string_append_len) (string, "ore", -1);
g_assert_true (g_string_append_len (string, NULL, 0) == string);
g_assert_true ((g_string_append_len) (string, NULL, 0) == string);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*string != NULL*failed*");
g_assert_null (g_string_append_len (NULL, NULL, -1));
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*string != NULL*failed*");
g_assert_null ((g_string_append_len) (NULL, NULL, -1));
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true (g_string_append_len (string, NULL, -1) == string);
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true ((g_string_append_len) (string, NULL, -1) == string);
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true (g_string_append_len (string, NULL, 1) == string);
g_test_assert_expected_messages ();
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*assertion*val != NULL*failed*");
g_assert_true ((g_string_append_len) (string, NULL, 1) == string);
g_test_assert_expected_messages ();
g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore");
g_string_free (string, TRUE);
}