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.
merge-requests/540/head
Fletcher Woodruff 2020-10-12 09:14:35 -06:00
rodzic de903b84c4
commit f71ac6126f
2 zmienionych plików z 55 dodań i 12 usunięć

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;