]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Optimize p_strndup()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 11 Mar 2021 23:19:38 +0000 (01:19 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 21 Sep 2021 07:12:53 +0000 (07:12 +0000)
src/lib/strfuncs.c
src/lib/test-lib.inc
src/lib/test-strfuncs.c

index 7b5e54499a753916b7d1582d273256a007c3acdb..68b67a2fb450ec60a6fcbb061ca882faf587d639 100644 (file)
@@ -87,19 +87,21 @@ char *p_strdup_until(pool_t pool, const void *start, const void *end)
 
 char *p_strndup(pool_t pool, const void *str, size_t max_chars)
 {
+       const char *p;
        char *mem;
        size_t len;
 
        i_assert(str != NULL);
        i_assert(max_chars != SIZE_MAX);
 
-       len = 0;
-       while (len < max_chars && ((const char *) str)[len] != '\0')
-               len++;
+       p = memchr(str, '\0', max_chars);
+       if (p == NULL)
+               len = max_chars;
+       else
+               len = p - (const char *)str;
 
        mem = p_malloc(pool, len+1);
        memcpy(mem, str, len);
-       mem[len] = '\0';
        return mem;
 }
 
index 0591f86dc3e453608f61b3ab1fbc4045c12fb954..549c7bd4e15336d22cfeb0995ce47d364656af25 100644 (file)
@@ -95,6 +95,7 @@ TEST(test_stats_dist)
 TEST(test_str)
 TEST(test_strescape)
 TEST(test_strfuncs)
+FATAL(fatal_strfuncs)
 TEST(test_strnum)
 TEST(test_str_find)
 TEST(test_str_sanitize)
index 5db27110379bbb59708a0f972a2025ac5c7512bb..b3c84fee7c7022718177d741f891316976877cd5 100644 (file)
@@ -16,6 +16,29 @@ static void test_p_strdup(void)
        test_end();
 }
 
+static void test_p_strndup(void)
+{
+       struct {
+               const char *input;
+               const char *output;
+               size_t len;
+       } tests[] = {
+               { "foo", "fo", 2 },
+               { "foo", "foo", 3 },
+               { "foo", "foo", 4 },
+               { "foo", "foo", SIZE_MAX-1 },
+       };
+       test_begin("p_strndup()");
+
+       for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
+               char *str = p_strndup(default_pool, tests[i].input,
+                                     tests[i].len);
+               test_assert_strcmp_idx(str, tests[i].output, i);
+               p_free(default_pool, str);
+       }
+       test_end();
+}
+
 static void test_p_strdup_empty(void)
 {
        test_begin("p_strdup_empty()");
@@ -475,6 +498,7 @@ test_str_match(void)
 void test_strfuncs(void)
 {
        test_p_strdup();
+       test_p_strndup();
        test_p_strdup_empty();
        test_p_strdup_until();
        test_p_strarray_dup();
@@ -492,3 +516,20 @@ void test_strfuncs(void)
        test_dec2str_buf();
        test_str_match();
 }
+
+enum fatal_test_state fatal_strfuncs(unsigned int stage)
+{
+       switch (stage) {
+       case 0:
+               test_begin("fatal p_strndup()");
+               test_expect_fatal_string("(str != NULL)");
+               (void)p_strndup(default_pool, NULL, 100);
+               return FATAL_TEST_FAILURE;
+       case 1:
+               test_expect_fatal_string("(max_chars != SIZE_MAX)");
+               (void)p_strndup(default_pool, "foo", SIZE_MAX);
+               return FATAL_TEST_FAILURE;
+       }
+       test_end();
+       return FATAL_TEST_FINISHED;
+}