Merge branch 'leak_fix' into 'master'

Fix memory leaks in dll and test backends

See merge request sane-project/backends!537
merge-requests/540/head
Olaf Meeuwissen 2020-10-20 09:01:15 +00:00
commit e4ef0548bf
3 zmienionych plików z 168 dodań i 31 usunięć

Wyświetl plik

@ -477,9 +477,6 @@ load (struct backend *be)
DBG (1, "load: malloc failed: %s\n", strerror (errno));
return SANE_STATUS_NO_MEM;
}
if (orig_src)
free (orig_src);
orig_src = src;
snprintf (src, src_len, "%s%s%s", path, DIR_SEP, LIBDIR);
}
else
@ -494,6 +491,7 @@ load (struct backend *be)
}
DBG (3, "load: searching backend `%s' in `%s'\n", be->name, src);
orig_src = src;
dir = strsep (&src, DIR_SEP);
while (dir)

Wyświetl plik

@ -237,35 +237,34 @@ static SANE_String_Const source_list[] = {
static double random_factor; /* use for fuzzyness of parameters */
/* initial values */
/* initial values. Initial string values are set in sane_init() */
static SANE_Word init_number_of_devices = 2;
static SANE_Fixed init_tl_x = SANE_FIX (0.0);
static SANE_Fixed init_tl_y = SANE_FIX (0.0);
static SANE_Fixed init_br_x = SANE_FIX (80.0);
static SANE_Fixed init_br_y = SANE_FIX (100.0);
static SANE_Word init_resolution = 50;
static SANE_String init_mode =SANE_VALUE_SCAN_MODE_GRAY;
static SANE_String init_mode = NULL;
static SANE_Word init_depth = 8;
static SANE_Bool init_hand_scanner = SANE_FALSE;
static SANE_Bool init_three_pass = SANE_FALSE;
static SANE_String init_three_pass_order = "RGB";
static SANE_String init_scan_source = "Flatbed";
static SANE_String init_test_picture = "Solid black";
static SANE_String init_three_pass_order = NULL;
static SANE_String init_scan_source = NULL;
static SANE_String init_test_picture = NULL;
static SANE_Bool init_invert_endianess = SANE_FALSE;
static SANE_Bool init_read_limit = SANE_FALSE;
static SANE_Word init_read_limit_size = 1;
static SANE_Bool init_read_delay = SANE_FALSE;
static SANE_Word init_read_delay_duration = 1000;
static SANE_String init_read_status_code = "Default";
static SANE_String init_read_status_code = NULL;
static SANE_Bool init_fuzzy_parameters = SANE_FALSE;
static SANE_Word init_ppl_loss = 0;
static SANE_Bool init_non_blocking = SANE_FALSE;
static SANE_Bool init_select_fd = SANE_FALSE;
static SANE_Bool init_enable_test_options = SANE_FALSE;
static SANE_String init_string = "This is the contents of the string option. "
"Fill some more words to see how the frontend behaves.";
static SANE_String init_string_constraint_string_list = "First entry";
static SANE_String init_string_constraint_long_string_list = "First entry";
static SANE_String init_string = NULL;
static SANE_String init_string_constraint_string_list = NULL;
static SANE_String init_string_constraint_long_string_list = NULL;
/* Test if this machine is little endian (from coolscan.c) */
static SANE_Bool
@ -320,6 +319,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 +399,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 +466,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 +495,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 +531,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 +626,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 +1160,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 +1179,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 +1200,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 +1233,43 @@ 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 void
cleanup_initial_string_values ()
{
// Cleanup backing memory for initial values of string options.
free (init_mode);
init_mode = NULL;
free (init_three_pass_order);
init_three_pass_order = NULL;
free (init_scan_source);
init_scan_source = NULL;
free (init_test_picture);
init_test_picture = NULL;
free (init_read_status_code);
init_read_status_code = NULL;
free (init_string);
init_string = NULL;
free (init_string_constraint_string_list);
init_string_constraint_string_list = NULL;
free (init_string_constraint_long_string_list);
init_string_constraint_long_string_list = NULL;
}
static void
cleanup_test_device (Test_Device * test_device)
{
DBG (2, "cleanup_test_device: test_device=%p\n", (void *) test_device);
if (test_device->options_initialized)
cleanup_options (test_device);
if (test_device->name)
free (test_device->name);
free (test_device);
}
static SANE_Status
@ -1331,7 +1399,11 @@ read_option (SANE_String line, SANE_String option_string,
{
DBG (3, "read_option: set option `%s' to `%s'\n", option_string,
word);
if (*(SANE_String *) value)
free (*(SANE_String *) value);
*(SANE_String *) value = strdup (word);
if (!*(SANE_String *) value)
return SANE_STATUS_NO_MEM;
}
break;
}
@ -1575,6 +1647,49 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
if (inited)
DBG (3, "sane_init: warning: already inited\n");
// Setup initial values of string options. Call free initially in case we've
// already called sane_init and these values are already non-null.
free (init_mode);
init_mode = strdup (SANE_VALUE_SCAN_MODE_GRAY);
if (!init_mode)
goto fail;
free (init_three_pass_order);
init_three_pass_order = strdup ("RGB");
if (!init_three_pass_order)
goto fail;
free (init_scan_source);
init_scan_source = strdup ("Flatbed");
if (!init_scan_source)
goto fail;
free (init_test_picture);
init_test_picture = strdup ("Solid black");
if (!init_test_picture)
goto fail;
free (init_read_status_code);
init_read_status_code = strdup ("Default");
if (!init_read_status_code)
goto fail;
free (init_string);
init_string = strdup ("This is the contents of the string option. "
"Fill some more words to see how the frontend behaves.");
if (!init_string)
goto fail;
free (init_string_constraint_string_list);
init_string_constraint_string_list = strdup ("First entry");
if (!init_string_constraint_string_list)
goto fail;
free (init_string_constraint_long_string_list);
init_string_constraint_long_string_list = strdup ("First entry");
if (!init_string_constraint_long_string_list)
goto fail;
fp = sanei_config_open (TEST_CONFIG_FILE);
if (fp)
{
@ -1713,14 +1828,14 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
sane_device_list =
malloc ((init_number_of_devices + 1) * sizeof (sane_device));
if (!sane_device_list)
return SANE_STATUS_NO_MEM;
goto fail;
for (num = 0; num < init_number_of_devices; num++)
{
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;
goto fail_device;
test_device->sane.vendor = "Noname";
test_device->sane.type = "virtual device";
test_device->sane.model = "frontend-tester";
@ -1728,7 +1843,7 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
number_string[sizeof (number_string) - 1] = '\0';
test_device->name = strdup (number_string);
if (!test_device->name)
return SANE_STATUS_NO_MEM;
goto fail_name;
test_device->sane.name = test_device->name;
if (previous_device)
previous_device->next = test_device;
@ -1740,6 +1855,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",
@ -1752,6 +1868,25 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
random_factor = ((double) rand ()) / RAND_MAX + 0.5;
inited = SANE_TRUE;
return SANE_STATUS_GOOD;
fail_name:
// test_device refers to the last device we were creating, which has not
// yet been added to the linked list of devices.
free (test_device);
fail_device:
// Now, iterate through the linked list of devices to clean up any successful
// devices.
test_device = first_test_device;
while (test_device)
{
previous_device = test_device;
test_device = test_device->next;
cleanup_test_device (previous_device);
}
free (sane_device_list);
fail:
cleanup_initial_string_values ();
return SANE_STATUS_NO_MEM;
}
void
@ -1772,15 +1907,15 @@ 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->name)
free (previous_device->name);
free (previous_device);
cleanup_test_device (previous_device);
}
DBG (4, "sane_exit: freeing device list\n");
if (sane_device_list)
free (sane_device_list);
sane_device_list = NULL;
first_test_device = NULL;
cleanup_initial_string_values ();
inited = SANE_FALSE;
return;
}
@ -1855,9 +1990,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;