Attention is currently required from: flichtenheld. Hello flichtenheld,
I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/486?usp=email to review the following change. Change subject: Allow having an extra function that is called when an env is freed ...................................................................... Allow having an extra function that is called when an env is freed Change-Id: I6899c1af65fbd670d434cdb17f81c82b900bfbd4 Signed-off-by: Arne Schwabe <a...@rfc2549.org> --- M CMakeLists.txt M src/openvpn/env_set.c M src/openvpn/env_set.h M tests/unit_tests/openvpn/Makefile.am M tests/unit_tests/openvpn/test_buffer.c 5 files changed, 106 insertions(+), 7 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/86/486/1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 96328a1..04e9e34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -685,6 +685,7 @@ target_sources(test_buffer PRIVATE tests/unit_tests/openvpn/mock_get_random.c + src/openvpn/env_set.c ) target_sources(test_crypto PRIVATE diff --git a/src/openvpn/env_set.c b/src/openvpn/env_set.c index 97b011f..fb7cd98 100644 --- a/src/openvpn/env_set.c +++ b/src/openvpn/env_set.c @@ -112,6 +112,10 @@ } if (do_free) { + if (current->free_function) + { + current->free_function(current); + } secure_memzero(current->string, strlen(current->string)); free(current->string); free(current); @@ -124,15 +128,37 @@ } static void -add_env_item(char *str, const bool do_alloc, struct env_item **list, struct gc_arena *gc) +env_gc_freefunction_wrapper(void *arg) +{ + struct env_item *ei = arg; + ei->free_function(ei); + free(ei->string); + free(ei); +} + +static void +add_env_item(char *str, void (*free_function)(struct env_item *), + struct env_item **list, struct gc_arena *gc) { struct env_item *item; ASSERT(str); ASSERT(list); - ALLOC_OBJ_GC(item, struct env_item, gc); - item->string = do_alloc ? string_alloc(str, gc) : str; + if (gc && free_function) + { + /* alloc items manually without gc to allow the gc_wrap_free + * function to free them all in the right order */ + ALLOC_OBJ(item, struct env_item); + item->string = string_alloc(str, NULL); + gc_addspecial(item, env_gc_freefunction_wrapper, gc); + } + else + { + ALLOC_OBJ_GC(item, struct env_item, gc); + item->string = string_alloc(str, gc); + } + item->free_function = free_function; item->next = *list; *list = item; } @@ -146,10 +172,11 @@ } static void -env_set_add_nolock(struct env_set *es, const char *str) +env_set_add_nolock(struct env_set *es, const char *str, + void (*free_function)(struct env_item *)) { remove_env_item(str, es->gc == NULL, &es->list); - add_env_item((char *)str, true, &es->list, es->gc); + add_env_item((char *)str, free_function, &es->list, es->gc); } struct env_set * @@ -171,6 +198,10 @@ while (e) { struct env_item *next = e->next; + if (e->free_function) + { + e->free_function(e); + } free(e->string); free(e); e = next; @@ -194,7 +225,16 @@ { ASSERT(es); ASSERT(str); - env_set_add_nolock(es, str); + env_set_add_nolock(es, str, NULL); +} + +void +env_set_add_specialfree(struct env_set *es, const char *str, + void (*free_function)(struct env_item *)) +{ + ASSERT(es); + ASSERT(str); + env_set_add_nolock(es, str, free_function); } const char * @@ -246,7 +286,7 @@ e = src->list; while (e) { - env_set_add_nolock(es, e->string); + env_set_add_nolock(es, e->string, e->free_function); e = e->next; } } diff --git a/src/openvpn/env_set.h b/src/openvpn/env_set.h index 4599977..27bc4dd 100644 --- a/src/openvpn/env_set.h +++ b/src/openvpn/env_set.h @@ -36,6 +36,7 @@ struct env_item { char *string; + void (*free_function)(struct env_item *); struct env_item *next; }; @@ -87,6 +88,11 @@ void env_set_add(struct env_set *es, const char *str); +void +env_set_add_specialfree(struct env_set *es, const char *str, + void (*free_function)(struct env_item *)); + + const char *env_set_get(const struct env_set *es, const char *name); void env_set_print(int msglevel, const struct env_set *es); diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index 6667626..c5098a9 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -52,6 +52,7 @@ buffer_testdriver_LDFLAGS = @TEST_LDFLAGS@ -L$(top_srcdir)/src/openvpn -Wl,--wrap=parse_line buffer_testdriver_SOURCES = test_buffer.c mock_msg.c mock_msg.h \ mock_get_random.c \ + $(top_srcdir)/src/openvpn/env_set.c \ $(top_srcdir)/src/openvpn/win32-util.c \ $(top_srcdir)/src/openvpn/platform.c diff --git a/tests/unit_tests/openvpn/test_buffer.c b/tests/unit_tests/openvpn/test_buffer.c index ee84c1f..e355a43 100644 --- a/tests/unit_tests/openvpn/test_buffer.c +++ b/tests/unit_tests/openvpn/test_buffer.c @@ -26,13 +26,22 @@ #endif #include "syshead.h" +#include <stdbool.h> #include <setjmp.h> #include <cmocka.h> #include "buffer.h" +#include "env_set.h" #include "buffer.c" +/* mock this function as it is required by env.c */ +int +script_security(void) +{ + return 0; +} + static void test_buffer_strprefix(void **state) { @@ -353,6 +362,47 @@ assert_string_equal(buf, "There is a .'nice.' \"1234\" [.] year old .tree!"); } +static bool unit_test_free_called = false; + +static void +unit_test_special_free(struct env_item *ei) +{ + assert_string_equal(ei->string, "unit=test"); + unit_test_free_called = true; +} + +static void +test_env_special_free(void **state) +{ + /* Test called via env_set_destroy */ + struct env_set *es = env_set_create(NULL); + env_set_add_specialfree(es, "unit=test", &unit_test_special_free); + env_set_destroy(es); + assert_true(unit_test_free_called); + unit_test_free_called = false; + + /* Test called via env_remove */ + es = env_set_create(NULL); + env_set_add_specialfree(es, "unit=test", &unit_test_special_free); + env_set_del(es, "unit"); + assert_true(unit_test_free_called); + unit_test_free_called = false; + env_set_destroy(es); + + /* Test for env with GC */ + struct gc_arena gc = gc_new(); + es = env_set_create(&gc); + env_set_add_specialfree(es, "unit=test", &unit_test_special_free); + env_set_destroy(es); + + /* The free should be done as part of gc free and not as part of + * the env set destroy */ + assert_false(unit_test_free_called); + + gc_free(&gc); + assert_true(unit_test_free_called); +} + int main(void) { @@ -385,6 +435,7 @@ cmocka_unit_test(test_buffer_free_gc_two), cmocka_unit_test(test_buffer_gc_realloc), cmocka_unit_test(test_character_class), + cmocka_unit_test(test_env_special_free) }; return cmocka_run_group_tests_name("buffer", tests, NULL, NULL); -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/486?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I6899c1af65fbd670d434cdb17f81c82b900bfbd4 Gerrit-Change-Number: 486 Gerrit-PatchSet: 1 Gerrit-Owner: plaisthos <arne-open...@rfc2549.org> Gerrit-Reviewer: flichtenheld <fr...@lichtenheld.com> Gerrit-CC: openvpn-devel <openvpn-devel@lists.sourceforge.net> Gerrit-Attention: flichtenheld <fr...@lichtenheld.com> Gerrit-MessageType: newchange
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel