From f71ac6126f7834c400fc9ced96325d1a61fc94d9 Mon Sep 17 00:00:00 2001 From: Fletcher Woodruff Date: Mon, 12 Oct 2020 09:14:35 -0600 Subject: [PATCH] test: free memory used for string options Inside Test_Device, track whether we've already called init_options(). If we have, don't call it again when calling sane_open() again. Add a function cleanup_options() which frees the memory used for these options, and call it in sane_exit() if we previously called init_options(). Change Test_Devices to be initialized with calloc instead of malloc, so that we can assume that uninitialized fields are NULL, and can safely call free() on them unconditionally. This eliminates some larger memory leaks within the test backend. --- backend/test.c | 66 +++++++++++++++++++++++++++++++++++++++++--------- backend/test.h | 1 + 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/backend/test.c b/backend/test.c index a1e186ea3..c92bb55a2 100644 --- a/backend/test.c +++ b/backend/test.c @@ -320,6 +320,38 @@ check_handle (SANE_Handle handle) return SANE_FALSE; } +static void +cleanup_options (Test_Device * test_device) +{ + DBG (2, "cleanup_options: test_device=%p\n", (void *) test_device); + + free(test_device->val[opt_mode].s); + test_device->val[opt_mode].s = NULL; + + free(test_device->val[opt_three_pass_order].s); + test_device->val[opt_three_pass_order].s = NULL; + + free(test_device->val[opt_scan_source].s); + test_device->val[opt_scan_source].s = NULL; + + free(test_device->val[opt_test_picture].s); + test_device->val[opt_test_picture].s = NULL; + + free(test_device->val[opt_read_status_code].s); + test_device->val[opt_read_status_code].s = NULL; + + free(test_device->val[opt_string].s); + test_device->val[opt_string].s = NULL; + + free(test_device->val[opt_string_constraint_string_list].s); + test_device->val[opt_string_constraint_string_list].s = NULL; + + free(test_device->val[opt_string_constraint_long_string_list].s); + test_device->val[opt_string_constraint_long_string_list].s = NULL; + + test_device->options_initialized = SANE_FALSE; +} + static SANE_Status init_options (Test_Device * test_device) { @@ -368,7 +400,7 @@ init_options (Test_Device * test_device) od->constraint.string_list = mode_list; test_device->val[opt_mode].s = malloc (od->size); if (!test_device->val[opt_mode].s) - return SANE_STATUS_NO_MEM; + goto fail; strcpy (test_device->val[opt_mode].s, init_mode); /* opt_depth */ @@ -435,7 +467,7 @@ init_options (Test_Device * test_device) od->constraint.string_list = order_list; test_device->val[opt_three_pass_order].s = malloc (od->size); if (!test_device->val[opt_three_pass_order].s) - return SANE_STATUS_NO_MEM; + goto fail; strcpy (test_device->val[opt_three_pass_order].s, init_three_pass_order); /* opt_resolution */ @@ -464,7 +496,7 @@ init_options (Test_Device * test_device) od->constraint.string_list = source_list; test_device->val[opt_scan_source].s = malloc (od->size); if (!test_device->val[opt_scan_source].s) - return SANE_STATUS_NO_MEM; + goto fail; strcpy (test_device->val[opt_scan_source].s, init_scan_source); /* opt_special_group */ @@ -500,7 +532,7 @@ init_options (Test_Device * test_device) od->constraint.string_list = test_picture_list; test_device->val[opt_test_picture].s = malloc (od->size); if (!test_device->val[opt_test_picture].s) - return SANE_STATUS_NO_MEM; + goto fail; strcpy (test_device->val[opt_test_picture].s, init_test_picture); /* opt_invert_endianness */ @@ -595,7 +627,7 @@ init_options (Test_Device * test_device) od->constraint.string_list = read_status_code_list; test_device->val[opt_read_status_code].s = malloc (od->size); if (!test_device->val[opt_read_status_code].s) - return SANE_STATUS_NO_MEM; + goto fail; strcpy (test_device->val[opt_read_status_code].s, init_read_status_code); /* opt_ppl_loss */ @@ -1129,7 +1161,7 @@ init_options (Test_Device * test_device) od->constraint.string_list = 0; test_device->val[opt_string].s = malloc (od->size); if (!test_device->val[opt_string].s) - return SANE_STATUS_NO_MEM; + goto fail; strcpy (test_device->val[opt_string].s, init_string); /* opt_string_constraint_string_list */ @@ -1148,7 +1180,7 @@ init_options (Test_Device * test_device) od->constraint.string_list = string_constraint_string_list; test_device->val[opt_string_constraint_string_list].s = malloc (od->size); if (!test_device->val[opt_string_constraint_string_list].s) - return SANE_STATUS_NO_MEM; + goto fail; strcpy (test_device->val[opt_string_constraint_string_list].s, init_string_constraint_string_list); @@ -1169,7 +1201,7 @@ init_options (Test_Device * test_device) test_device->val[opt_string_constraint_long_string_list].s = malloc (od->size); if (!test_device->val[opt_string_constraint_long_string_list].s) - return SANE_STATUS_NO_MEM; + goto fail; strcpy (test_device->val[opt_string_constraint_long_string_list].s, init_string_constraint_long_string_list); @@ -1202,6 +1234,10 @@ init_options (Test_Device * test_device) test_device->val[opt_button].w = 0; return SANE_STATUS_GOOD; + +fail: + cleanup_options (test_device); + return SANE_STATUS_NO_MEM; } static SANE_Status @@ -1718,7 +1754,7 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un { SANE_Char number_string[PATH_MAX]; - test_device = malloc (sizeof (*test_device)); + test_device = calloc (sizeof (*test_device), 1); if (!test_device) return SANE_STATUS_NO_MEM; test_device->sane.vendor = "Noname"; @@ -1740,6 +1776,7 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un test_device->eof = SANE_FALSE; test_device->scanning = SANE_FALSE; test_device->cancelled = SANE_FALSE; + test_device->options_initialized = SANE_FALSE; sanei_thread_initialize (test_device->reader_pid); test_device->pipe = -1; DBG (4, "sane_init: new device: `%s' is a %s %s %s\n", @@ -1772,6 +1809,8 @@ sane_exit (void) DBG (4, "sane_exit: freeing device %s\n", test_device->name); previous_device = test_device; test_device = test_device->next; + if (previous_device->options_initialized) + cleanup_options (previous_device); if (previous_device->name) free (previous_device->name); free (previous_device); @@ -1855,9 +1894,12 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) test_device->open = SANE_TRUE; *handle = test_device; - status = init_options (test_device); - if (status != SANE_STATUS_GOOD) - return status; + if (!test_device->options_initialized) { + status = init_options (test_device); + if (status != SANE_STATUS_GOOD) + return status; + test_device->options_initialized = SANE_TRUE; + } test_device->open = SANE_TRUE; test_device->scanning = SANE_FALSE; diff --git a/backend/test.h b/backend/test.h index 5b1b82b32..aeaf109a8 100644 --- a/backend/test.h +++ b/backend/test.h @@ -143,6 +143,7 @@ typedef struct Test_Device SANE_Bool scanning; SANE_Bool cancelled; SANE_Bool eof; + SANE_Bool options_initialized; SANE_Int number_of_scans; } Test_Device;