wmem: Make strbuf_utf8_validate() accept embedded NUL bytes

This commit is contained in:
João Valverde 2022-10-19 13:38:06 +01:00
parent 338e6b50e2
commit 6aa33f0fc9
3 changed files with 58 additions and 3 deletions

View File

@ -18,6 +18,7 @@
#include <glib.h>
#include <ws_symbol_export.h>
#include <ws_attributes.h>
#include <ws_posix_compat.h>
#ifdef __cplusplus
extern "C" {

View File

@ -415,10 +415,35 @@ wmem_strbuf_destroy(wmem_strbuf_t *strbuf)
wmem_free(strbuf->allocator, strbuf);
}
bool
wmem_strbuf_utf8_validate(wmem_strbuf_t *strbuf, const char **endptr)
static bool
string_utf8_validate(const char *str, ssize_t max_len, const char **endpptr)
{
return g_utf8_validate(strbuf->str, strbuf->len, endptr);
bool valid;
if (max_len <= 0)
return true;
valid = g_utf8_validate(str, max_len, endpptr);
if (valid || **endpptr != '\0')
return valid;
/* Invalid because of a nul byte. Skip nuls and continue. */
max_len -= *endpptr - str;
str = *endpptr;
while (max_len > 0 && *str == '\0') {
str++;
max_len--;
}
return string_utf8_validate(str, max_len, endpptr);
}
/* g_utf8_validate() returns FALSE in the string contains embedded NUL
* bytes. We accept \x00 as valid and work around that to validate the
* entire len bytes. */
bool
wmem_strbuf_utf8_validate(wmem_strbuf_t *strbuf, const char **endpptr)
{
return string_utf8_validate(strbuf->str, strbuf->len, endpptr);
}
void

View File

@ -1175,6 +1175,34 @@ wmem_test_strbuf(void)
wmem_destroy_allocator(allocator);
}
static void
wmem_test_strbuf_validate(void)
{
wmem_strbuf_t *strbuf;
const char *endptr;
strbuf = wmem_strbuf_new(NULL, "TEST\xEF ABC");
g_assert_false(wmem_strbuf_utf8_validate(strbuf, &endptr));
g_assert(endptr == &strbuf->str[4]);
wmem_strbuf_destroy(strbuf);
strbuf = wmem_strbuf_new(NULL, NULL);
wmem_strbuf_append_len(strbuf, "TEST\x00\x00 ABC", 10);
g_assert_true(wmem_strbuf_utf8_validate(strbuf, &endptr));
wmem_strbuf_destroy(strbuf);
strbuf = wmem_strbuf_new(NULL, NULL);
wmem_strbuf_append_len(strbuf, "TEST\x00\xEF ABC", 10);
g_assert_false(wmem_strbuf_utf8_validate(strbuf, &endptr));
g_assert(endptr == &strbuf->str[5]);
wmem_strbuf_destroy(strbuf);
strbuf = wmem_strbuf_new(NULL, NULL);
wmem_strbuf_append_len(strbuf, "TEST\x00 ABC \x00 DEF \x00", 17);
g_assert_true(wmem_strbuf_utf8_validate(strbuf, &endptr));
wmem_strbuf_destroy(strbuf);
}
static void
wmem_test_tree(void)
{
@ -1466,6 +1494,7 @@ main(int argc, char **argv)
g_test_add_func("/wmem/datastruct/queue", wmem_test_queue);
g_test_add_func("/wmem/datastruct/stack", wmem_test_stack);
g_test_add_func("/wmem/datastruct/strbuf", wmem_test_strbuf);
g_test_add_func("/wmem/datastruct/strbuf/validate", wmem_test_strbuf_validate);
g_test_add_func("/wmem/datastruct/tree", wmem_test_tree);
g_test_add_func("/wmem/datastruct/itree", wmem_test_itree);