From 5fe891c10d2f9d9efd24dbea2703ad56e16bd9e3 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Fri, 4 Oct 2024 12:36:18 -0400 Subject: (w)str: Guard against error-prone str_c() usage Also, reorder al_str_insert() arguments. Signed-off-by: Andrew Opalach --- include/al/str.h | 7 ++++--- include/al/wstr.h | 3 ++- tests/str.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/include/al/str.h b/include/al/str.h index d5c7266..b06bf57 100644 --- a/include/al/str.h +++ b/include/al/str.h @@ -14,7 +14,8 @@ typedef struct { #define al_str_at(s, i) (s)->data[i] #define al_str_atr(s, i) (s)->data[(s)->len + i] -#define al_str_c(s) (&((str){ (u32)(sizeof(s) - 1), 0, ((char *)(s)) })) +#define al_string_if_literal(s) ((char *)(s "")) // use al_str_cr for runtime. +#define al_str_c(s) (&((str){ (u32)((sizeof(s) / sizeof(char)) - 1), 0, al_string_if_literal(s) })) #define al_str_cr(s) (&((str){ (u32)al_strlen(s), 0, ((char *)(s)) })) // runtime #define al_str_w(s, i, n) (&((str){ ((u32)(n)), 0, &(s)[i] })) #define al_str_substr(s, start, end) al_str_w((s)->data, start, ((end) - (start))) @@ -98,7 +99,7 @@ static inline void al_str_cat(str *s, str *c) s->len += c->len; } -static inline void al_str_insert(str *s, str *c, u32 i) +static inline void al_str_insert(str *s, u32 i, str *c) { s->alloc = al_str_reserve(s, s->len + c->len); char *data = s->data + i; @@ -109,7 +110,7 @@ static inline void al_str_insert(str *s, str *c, u32 i) static inline void al_str_prepend(str *s, str *c) { - al_str_insert(s, c, 0); + al_str_insert(s, 0, c); } static inline s32 al_str_cmp(str *s, str *c, u32 start, u32 len) diff --git a/include/al/wstr.h b/include/al/wstr.h index 7c7e441..ed2c051 100644 --- a/include/al/wstr.h +++ b/include/al/wstr.h @@ -17,7 +17,8 @@ typedef struct { #define al_wstr_at(w, i) (w)->data[i] #define al_wstr_atr(w, i) (w)->data[(w)->len + i] -#define al_wstr_c(w) (&((wstr){ (u32)((sizeof(w) / sizeof(wchar_t)) - 1), 0, ((wchar_t *)(w)) })) +#define al_wide_string_if_literal(w) ((wchar_t *)(L"" w)) // use al_wstr_cr for runtime. +#define al_wstr_c(w) (&((wstr){ (u32)((sizeof(w) / sizeof(wchar_t)) - 1), 0, al_wide_string_if_literal(w) })) #define al_wstr_cr(w) (&((wstr){ (u32)wcslen(w), 0, ((wchar_t *)(w)) })) // runtime #define al_wstr_w(w, i, n) (&((wstr){ ((u32)(n)), 0, &al_wstr_at(w, i) })) #define al_wstr_substr(w, start, end) al_wstr_w(w, start, ((end) - (start))) diff --git a/tests/str.c b/tests/str.c index ce1c3b5..4af5dc4 100644 --- a/tests/str.c +++ b/tests/str.c @@ -1,5 +1,6 @@ #include #include +#include static bool str_test_cmp(void) { @@ -62,7 +63,7 @@ static bool str_test_insert(void) al_str_from(&insert_str, "testtestasdf"); al_str_from(&prepend_str, "testtestasdf"); - al_str_insert(&insert_str, al_str_c("[insert]"), 8); + al_str_insert(&insert_str, 8, al_str_c("[insert]")); al_str_prepend(&prepend_str, al_str_c("[prepend]")); AL_TEST_TRUE(al_str_eq(insert_result, &insert_str)); @@ -191,6 +192,45 @@ static bool str_test_to_long(void) AL_TEST_END(); } +static str *global __attribute__((unused)) = al_str_c("yeeee"); + +static bool str_test_error_prone_str_c(void) +{ + AL_TEST_START("str_error_prone_str_c"); + + str *n = al_str_c("yoyoyoyoyo"); + AL_TEST_EQ(n->len, al_strlen("yoyoyoyoyo"), u32); + AL_TEST_EQ(n->alloc, 0, u32); + AL_TEST_EQ(al_memcmp(n->data, "yoyoyoyoyo", al_strlen("yoyoyoyoyo") + 1), 0, u32); + +// This is expected to cause a compile error. +#if 0 + char *d = al_malloc(26); + char *s = "yoyoyoyoyo"; + al_memcpy(d, s, strlen(s) + 1); + + str ds = *al_str_c(d); + str ss = *al_str_cr(d); + AL_TEST_EQ(ds.len, (u32)(sizeof(char *) - 1), u32); + AL_TEST_EQ(ss.len, (u32)al_strlen(s), u32); + + al_free(d); + + wchar_t *wd = al_malloc(sizeof(wchar_t) * 26); + wchar_t *ws = L"yoyoyoyoyo"; + al_memcpy(wd, ws, (wcslen(ws) * sizeof(wchar_t)) + sizeof(wchar_t)); + + wstr wds = *al_wstr_c(wd); + wstr wss = *al_wstr_cr(wd); + AL_TEST_EQ(wds.len, (u32)((sizeof(wchar_t *) / sizeof(wchar_t)) - 1), u32); + AL_TEST_EQ(wss.len, (u32)wcslen(ws), u32); + + al_free(wd); +#endif + + AL_TEST_END(); +} + bool str_tests_run(void) { AL_TEST_START_GROUP("str"); @@ -202,6 +242,7 @@ bool str_tests_run(void) AL_TEST_RUN(str_test_substr); AL_TEST_RUN(str_test_get_line); AL_TEST_RUN(str_test_to_long); + AL_TEST_RUN(str_test_error_prone_str_c); AL_TEST_END_GROUP(); } -- cgit v1.2.3-101-g0448