From patchwork Wed Oct 3 21:01:59 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: opts.c, gcc.c: Plug some memory leaks - and an out-of-bounds memory access Date: Wed, 03 Oct 2012 11:01:59 -0000 From: Tobias Burnus X-Patchwork-Id: 188924 Message-Id: <506CA7C7.2050800@net-b.de> To: gcc patches Found using http://scan5.coverity.com/ Build on x86-64-gnu-linux with C/C++/Fortran. I will now do an all-language build/regtest. OK when it passes? (Note to the save_string call: I reduced it by 2: The "+1" in the call makes it long (out of bounds) and the "+1" in temp_filename_length is not needed (but also doesn't harm) as "tmp" is null terminated and save_string adds another '\0' after copying "len" bytes.) Tobias 2012-10-03 Tobias Burnus * gcc.c (record_temp_file, add_sysrooted_prefix, process_command, do_self_spec, compare_debug_dump_opt_spec_function): Plug memleaks. (do_spec_1): Ditto, fix out-of-bound access. * opts.c (common_handle_option): Plug memleak. diff --git a/gcc/gcc.c b/gcc/gcc.c index af3c34a..2d56d40 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -1981,21 +1981,24 @@ record_temp_file (const char *filename, int always_delete, int fail_delete) always_delete_queue = temp; already1:; } if (fail_delete) { struct temp_file *temp; for (temp = failure_delete_queue; temp; temp = temp->next) if (! filename_cmp (name, temp->name)) - goto already2; + { + free (name); + goto already2; + } temp = XNEW (struct temp_file); temp->next = failure_delete_queue; temp->name = name; failure_delete_queue = temp; already2:; } } @@ -2455,22 +2458,29 @@ add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix, if (target_system_root) { char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root); size_t sysroot_len = strlen (target_system_root); if (sysroot_len > 0 && target_system_root[sysroot_len - 1] == DIR_SEPARATOR) sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0'; if (target_sysroot_suffix) - prefix = concat (target_sysroot_suffix, prefix, NULL); - prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL); + { + char *tmp; + tmp = concat (target_sysroot_suffix, prefix, NULL); + prefix = concat (sysroot_no_trailing_dir_separator, tmp, NULL); + free (tmp); + } + else + prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL); + free (sysroot_no_trailing_dir_separator); /* We have to override this because GCC's notion of sysroot moves along with GCC. */ component = "GCC"; } add_prefix (pprefix, prefix, component, priority, require_machine_suffix, os_multilib); } @@ -3564,21 +3574,21 @@ set_option_handlers (struct cl_option_handlers *handlers) /* Create the vector `switches' and its contents. Store its length in `n_switches'. */ static void process_command (unsigned int decoded_options_count, struct cl_decoded_option *decoded_options) { const char *temp; char *temp1; - const char *tooldir_prefix; + char *tooldir_prefix, *tooldir_prefix2; char *(*get_relative_prefix) (const char *, const char *, const char *) = NULL; struct cl_option_handlers handlers; unsigned int j; gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX"); n_switches = 0; n_infiles = 0; added_libraries = 0; @@ -3913,36 +3923,38 @@ process_command (unsigned int decoded_options_count, add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS", PREFIX_PRIORITY_LAST, 2, 0); add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", PREFIX_PRIORITY_LAST, 2, 0); #endif add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", PREFIX_PRIORITY_LAST, 1, 0); } gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix)); - tooldir_prefix = concat (tooldir_base_prefix, spec_machine, - dir_separator_str, NULL); + tooldir_prefix2 = concat (tooldir_base_prefix, spec_machine, + dir_separator_str, NULL); /* Look for tools relative to the location from which the driver is running, or, if that is not available, the configured prefix. */ tooldir_prefix = concat (gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix, spec_machine, dir_separator_str, - spec_version, dir_separator_str, tooldir_prefix, NULL); + spec_version, dir_separator_str, tooldir_prefix2, NULL); + free (tooldir_prefix2); add_prefix (&exec_prefixes, concat (tooldir_prefix, "bin", dir_separator_str, NULL), "BINUTILS", PREFIX_PRIORITY_LAST, 0, 0); add_prefix (&startfile_prefixes, concat (tooldir_prefix, "lib", dir_separator_str, NULL), "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1); + free (tooldir_prefix); #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS) /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix, then consider it to relocate with the rest of the GCC installation if GCC_EXEC_PREFIX is set. ``make_relative_prefix'' is not compiled for VMS, so don't call it. */ if (target_system_root && !target_system_root_changed && gcc_exec_prefix) { char *tmp_prefix = get_relative_prefix (decoded_options[0].arg, standard_bindir_prefix, @@ -4312,20 +4324,21 @@ do_self_spec (const char *spec) argbuf_copy = XNEWVEC (const char *, VEC_length (const_char_p, argbuf) + 1); argbuf_copy[0] = ""; memcpy (argbuf_copy + 1, VEC_address (const_char_p, argbuf), VEC_length (const_char_p, argbuf) * sizeof (const char *)); decode_cmdline_options_to_array (VEC_length (const_char_p, argbuf) + 1, argbuf_copy, CL_DRIVER, &decoded_options, &decoded_options_count); + free (argbuf_copy); set_option_handlers (&handlers); for (j = 1; j < decoded_options_count; j++) { switch (decoded_options[j].opt_index) { case OPT_SPECIAL_input_file: /* Specs should only generate options, not input files. */ @@ -4733,22 +4746,22 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) temp file. */ if (save_temps_length) { char *tmp; temp_filename_length = save_temps_length + suffix_length + 1; tmp = (char *) alloca (temp_filename_length); memcpy (tmp, save_temps_prefix, save_temps_length); memcpy (tmp + save_temps_length, suffix, suffix_length); tmp[save_temps_length + suffix_length] = '\0'; - temp_filename = save_string (tmp, - temp_filename_length + 1); + temp_filename = save_string (tmp, save_temps_length + + suffix_length); obstack_grow (&obstack, temp_filename, temp_filename_length); arg_going = 1; delete_this_arg = 0; break; } /* If the gcc_input_filename has the same suffix specified for the %g, %u, or %U, and -save-temps is specified, we could end up using that file as an intermediate @@ -5048,20 +5061,21 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) /* See if we already recorded this option. */ FOR_EACH_VEC_ELT (char_p, linker_options, ix, opt) if (! strcmp (string, opt)) { free (string); return 0; } /* This option is new; add it. */ add_linker_option (string, strlen (string)); + free (string); } break; /* Dump out the options accumulated previously using %x. */ case 'X': do_specs_vec (linker_options); break; /* Dump out the options accumulated previously using -Wa,. */ case 'Y': @@ -8179,21 +8193,21 @@ get_random_number (void) } /* %:compare-debug-dump-opt spec function. Save the last argument, expected to be the last -fdump-final-insns option, or generate a temporary. */ static const char * compare_debug_dump_opt_spec_function (int arg, const char **argv ATTRIBUTE_UNUSED) { - const char *ret; + char *ret; char *name; int which; static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3]; if (arg != 0) fatal_error ("too many arguments to %%:compare-debug-dump-opt"); do_spec_2 ("%{fdump-final-insns=*:%*}"); do_spec_1 (" ", 0, NULL); @@ -8233,22 +8247,26 @@ compare_debug_dump_opt_spec_function (int arg, debug_check_temp_file[which] = name; if (!which) { unsigned HOST_WIDE_INT value = get_random_number (); sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value); } if (*random_seed) - ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ", - ret, NULL); + { + char *tmp = ret; + ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ", + ret, NULL); + free (tmp); + } if (which) *random_seed = 0; return ret; } static const char *debug_auxbase_opt; /* %:compare-debug-self-opt spec function. Expands to the options diff --git a/gcc/opts.c b/gcc/opts.c index 8608a56..ccfe3c7 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1468,20 +1468,22 @@ common_handle_option (struct gcc_options *opts, case OPT_aux_info: opts->x_flag_gen_aux_info = 1; break; case OPT_auxbase_strip: { char *tmp = xstrdup (arg); strip_off_ending (tmp, strlen (tmp)); if (tmp[0]) opts->x_aux_base_name = tmp; + else + free (tmp); } break; case OPT_d: decode_d_option (arg, opts, loc, dc); break; case OPT_fcall_used_: case OPT_fcall_saved_: /* Deferred. */