![]() |
Ansel 0.0
A darktable fork - bloat + design vision
|
#include "common/conf.h"#include "darktable.h"#include <glib.h>#include <glib/gstdio.h>#include <stdarg.h>#include <stddef.h>#include <stdlib.h>#include <setjmp.h>#include <stdint.h>#include <cmocka.h>
Include dependency graph for test_conf_value_lifetime.c:Go to the source code of this file.
Macros | |
| #define | TEST_KEY "plugins/test/conf_value_lifetime" |
Functions | |
| static int | _setup (void **state) |
| static int | _teardown (void **state) |
| static void | _borrowed_value_survives_being_replaced (void **state) |
| static void | _every_displaced_value_stays_readable (void **state) |
| static void | _rewriting_the_same_value_retires_nothing (void **state) |
| static void | _typed_setters_retire_too (void **state) |
| int | main (void) |
Variables | |
| static char * | _rcfile = NULL |
| #define TEST_KEY "plugins/test/conf_value_lifetime" |
Lifetime of the string dt_conf_get_string_const() hands out.
That function returns a pointer INTO the conf hash table, and dt_conf_get_var() releases the lock before returning it. Replacing the value used to free it on the spot – the table's value_destroy_func is a free – so any reader still holding the pointer was reading freed memory. With 98 call sites and no way to tell from a signature which of them could race a writer, the fix was made in the writer: displaced values are retired and released only at cleanup.
These tests pin that. The first one is the bug: read, overwrite, read again through the ORIGINAL pointer.
Checked against the defect rather than only against the fix. Reverting the writer to its free-on-replace form and running under MALLOC_PERTURB_=170 – which fills freed memory, so a use-after-free stops being silent without needing a full ASAN build – fails three of the four, reporting the fill pattern where the value should be:
[ ERROR ] --- "\357\277\275\357\277\275" != "11"
The fourth, _rewriting_the_same_value_retires_nothing(), passes EITHER WAY and is not a regression detector: it asserts pointer identity, and the old code frees then immediately reallocates the same size, so the allocator hands back the same address. It is here to pin the dedup property – that an unchanged write retires nothing – not the lifetime. A key with no confgen declaration, so nothing clamps or sanitises what we store.
Definition at line 59 of file test_conf_value_lifetime.c.
The bug, pinned: a borrowed pointer survives the write that displaces it.
Definition at line 88 of file test_conf_value_lifetime.c.
References dt_conf_get_string_const(), dt_conf_set_string(), state, TEST_KEY, and void().
Referenced by main().
Many successive writes, all of them retired rather than freed.
Definition at line 108 of file test_conf_value_lifetime.c.
References dt_conf_get_string_const(), dt_conf_set_string(), i, state, TEST_KEY, value, and void().
Referenced by main().
Rewriting a key with the value it already holds must change nothing at all.
This is what keeps the retired list proportional to real edits: GUI state is written back constantly with values that did not change, and retiring a string for each of those would make the list grow with idle churn instead. Pointer IDENTITY is the observable.
Definition at line 135 of file test_conf_value_lifetime.c.
References dt_conf_get_string_const(), dt_conf_set_string(), i, state, TEST_KEY, and void().
Referenced by main().
|
static |
Definition at line 63 of file test_conf_value_lifetime.c.
References _rcfile, darktable_t::conf, darktable, dt_conf_init(), state, and void().
Referenced by main().
|
static |
Definition at line 75 of file test_conf_value_lifetime.c.
References _rcfile, darktable_t::conf, darktable, dt_conf_cleanup(), state, and void().
Referenced by main().
The typed setters go through the same writer, so they inherit the same guarantee.
Definition at line 149 of file test_conf_value_lifetime.c.
References dt_conf_get_int_fast(), dt_conf_get_string_const(), dt_conf_set_int(), state, TEST_KEY, and void().
Referenced by main().
| int main | ( | void | ) |
Definition at line 162 of file test_conf_value_lifetime.c.
References _borrowed_value_survives_being_replaced(), _every_displaced_value_stays_readable(), _rewriting_the_same_value_retires_nothing(), _setup(), _teardown(), and _typed_setters_retire_too().
|
static |
Definition at line 61 of file test_conf_value_lifetime.c.
Referenced by _setup(), and _teardown().