kopia lustrzana https://gitlab.com/sane-project/backends
Merge branch 'leak_fix' into 'master'
Fix memory leaks in dll and test backends See merge request sane-project/backends!537merge-requests/540/head
commit
e4ef0548bf
|
@ -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)
|
||||
|
|
194
backend/test.c
194
backend/test.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Ładowanie…
Reference in New Issue