]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: DEBUG: Fix potential crash in handling "Growing data stack" debug message
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 9 Mar 2020 09:11:04 +0000 (11:11 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 1 Jun 2021 10:44:55 +0000 (10:44 +0000)
This could have only happened when data_stack_grow event was enabled and
when --enable-devel-checks was used.

src/lib/data-stack.c
src/lib/test-data-stack.c

index 801c4e99d700479e79695e80ebd50c1a67aaf624..fe7361402cf5bfd01374750fcbaca45498d4a08f 100644 (file)
@@ -490,11 +490,11 @@ static void *t_malloc_real(size_t size, bool permanent)
        if (permanent)
                current_block->left -= alloc_size;
 
-       if (warn) {
+       if (warn) T_BEGIN {
                /* warn after allocation, so if e_debug() wants to
                   allocate more memory we don't go to infinite loop */
                data_stack_send_grow_event(alloc_size);
-       }
+       } T_END;
 #ifdef DEBUG
        memcpy(ret, &size, sizeof(size));
        ret = PTR_OFFSET(ret, MEM_ALIGN(sizeof(size)));
index d37cf5ac7fbbb15088c2b3c87ee844204edce32d..70f82388977b3a04f22e6444544e5278593ba68a 100644 (file)
@@ -37,7 +37,7 @@ test_ds_grow_event_callback(struct event *event,
        field = event_find_field_nonrecursive(event, "frame_marker");
        test_assert(field != NULL &&
                    field->value_type == EVENT_FIELD_VALUE_TYPE_STR &&
-                   strstr(field->value.str, "test-data-stack.c") != NULL);
+                   strstr(field->value.str, "data-stack.c") != NULL);
        return TRUE;
 }
 
@@ -96,6 +96,46 @@ static void test_ds_get_bytes_available(void)
        test_end();
 }
 
+static void ATTR_FORMAT(2, 0)
+test_ds_growing_debug(const struct failure_context *ctx ATTR_UNUSED,
+                     const char *format, va_list args)
+{
+       ds_grow_event_count++;
+       (void)t_strdup_vprintf(format, args);
+}
+
+static void test_ds_grow_in_event(void)
+{
+       size_t i, alloc1 = 8096;
+       unsigned char *buf;
+       const char *error;
+
+       test_begin("data-stack grow in event");
+
+       struct event_filter *filter = event_filter_create();
+       event_set_global_debug_log_filter(filter);
+       test_assert(event_filter_parse("event=data_stack_grow", filter, &error) == 0);
+       event_filter_unref(&filter);
+
+       i_set_debug_handler(test_ds_growing_debug);
+       buf = t_buffer_get(alloc1);
+       for (i = 0; i < alloc1; i++)
+               buf[i] = i;
+
+       test_assert(ds_grow_event_count == 0);
+       buf = t_buffer_reget(buf, 65536);
+       test_assert(ds_grow_event_count == 1);
+       for (i = 0; i < alloc1; i++) {
+               if (buf[i] != (unsigned char)i)
+                       break;
+       }
+       test_assert(i == alloc1);
+
+       i_set_debug_handler(default_error_handler);
+       event_unset_global_debug_log_filter();
+       test_end();
+}
+
 static void test_ds_buffers(void)
 {
        test_begin("data-stack buffer growth");
@@ -286,6 +326,7 @@ void test_data_stack(void)
        void (*tests[])(void) = {
                test_ds_grow_event,
                test_ds_get_bytes_available,
+               test_ds_grow_in_event,
                test_ds_buffers,
                test_ds_realloc,
                test_ds_recursive,