From 6ab9111048ec9a09ea4809c4ec57ad97fe208ce5 Mon Sep 17 00:00:00 2001 From: Botond Baranyi <botond.baranyi@ericsson.com> Date: Wed, 25 Jan 2017 16:00:24 +0100 Subject: [PATCH] Fixed memory leaks in TPD processing (artf786863) Change-Id: I2ba03f8e7ea122e60be0ff1bb39a12679ea1f95a Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com> --- compiler2/makefile.c | 30 +++++++++++++++---- compiler2/xpather.cc | 71 +++++++++++++++++++++++++++++++++----------- compiler2/xpather.h | 2 +- 3 files changed, 78 insertions(+), 25 deletions(-) diff --git a/compiler2/makefile.c b/compiler2/makefile.c index 64efcf9a9..cb188c212 100644 --- a/compiler2/makefile.c +++ b/compiler2/makefile.c @@ -4995,6 +4995,8 @@ int main(int argc, char *argv[]) if (error_flag) { usage(); + Free(other_files); + Free(search_paths); return EXIT_FAILURE; } @@ -5007,6 +5009,8 @@ int main(int argc, char *argv[]) #ifdef LICENSE print_license_info(); #endif + Free(other_files); + Free(search_paths); return EXIT_SUCCESS; } @@ -5017,16 +5021,21 @@ int main(int argc, char *argv[]) free_openssl(); if (!valid_license) { free_license(&lstr); + Free(other_files); + Free(search_paths); exit(EXIT_FAILURE); } if (!check_feature(&lstr, FEATURE_TPGEN)) { ERROR("The license key does not allow the generation of " "Makefile skeletons."); + Free(other_files); + Free(search_paths); return EXIT_FAILURE; } free_license(&lstr); #endif + boolean free_argv = FALSE; if (tflag) { char* abs_work_dir = NULL; FILE* prj_graph_fp = NULL; @@ -5104,7 +5113,7 @@ int main(int argc, char *argv[]) boolean temp_wflag = FALSE; tpd_processed = process_tpd(tpd_file_name, tpd_build_config, file_list_path, - &argc, &argv, &optind, &ets_name, &project_name, + &argc, &argv, &free_argv, &optind, &ets_name, &project_name, &gflag, &sflag, &cflag, &aflag, &pflag, &Rflag, &lflag, &mflag, &Pflag, &Lflag, rflag, Fflag, Tflag, output_file, &abs_work_dir, sub_project_dirs, program_name, prj_graph_fp, create_symlink_list, ttcn3_prep_includes, ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, &csflag, @@ -5118,14 +5127,17 @@ int main(int argc, char *argv[]) wflag = temp_wflag; } - Free(abs_work_dir); if (prj_graph_fp) { fprintf(prj_graph_fp, "</project_hierarchy_graph>\n"); fclose(prj_graph_fp); } if (tpd_processed == TPD_FAILED) { ERROR("Failed to process %s", tpd_file_name); - goto end; + // process_tpd has already cleaned everything up + return EXIT_FAILURE; + } + else { + Free(abs_work_dir); } if (zflag) { WARNING("Compiler option '-z' and its argument will be overwritten by " @@ -5160,8 +5172,12 @@ int main(int argc, char *argv[]) executeMakefileScript(makefileScript, output_file); } } + else { + free_string2_list(run_command_list); + free_string2_list(create_symlink_list); + Free(project_name); + } -end: free_string_list(sub_project_dirs); free_string_list(ttcn3_prep_includes); free_string_list(ttcn3_prep_defines); @@ -5185,10 +5201,9 @@ end: free_string2_list(target_placement_list); free_string2_list(required_configs); Free(makefileScript); - + Free(other_files); if (tpd_processed == TPD_SUCCESS) { - int E; if (!(eflag && ets_name)) Free(ets_name); if (cxxcompiler) @@ -5200,6 +5215,9 @@ end: if (ttcn3prep) Free(ttcn3prep); /* Free(output_file); */ + } + if (free_argv) { + int E; for (E = 0; E < argc; ++E) Free(argv[E]); Free(argv); } diff --git a/compiler2/xpather.cc b/compiler2/xpather.cc index bddf069ce..488c787c0 100644 --- a/compiler2/xpather.cc +++ b/compiler2/xpather.cc @@ -1253,7 +1253,7 @@ static tpd_result config_struct_get_required_configs(struct config_struct* const } static tpd_result process_tpd_internal(const char *p_tpd_name, char* tpdName, const char *actcfg, - const char *file_list_path, int *p_argc, char ***p_argv, + const char *file_list_path, int *p_argc, char ***p_argv, boolean* p_free_argv, int *p_optind, char **p_ets_name, char **p_project_name, boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess, boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag, @@ -1273,7 +1273,7 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, char* tpdName, co const char **search_paths, size_t n_search_paths, char** makefileScript, struct config_struct * const all_configs); extern "C" tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, - const char *file_list_path, int *p_argc, char ***p_argv, + const char *file_list_path, int *p_argc, char ***p_argv, boolean* p_free_argv, int *p_optind, char **p_ets_name, char **p_project_name, boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess, boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag, @@ -1304,7 +1304,7 @@ extern "C" tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, // The first round only collects the configurations about the tpd-s into the // all_configs variable. It does not do anything else. tpd_result success = process_tpd_internal(p_tpd_name, tpdName, - actcfg, file_list_path, p_argc, p_argv, p_optind, p_ets_name, p_project_name, + actcfg, file_list_path, p_argc, p_argv, p_free_argv, p_optind, p_ets_name, p_project_name, p_gflag, p_sflag, p_cflag, p_aflag, preprocess, p_Rflag, p_lflag, p_mflag, p_Pflag, p_Lflag, recursive, force_overwrite, gen_only_top_level, @@ -1332,7 +1332,7 @@ extern "C" tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, // optimal case. In the not optimal case errors are produced. // This round does get the information from the tpd to generate the makefile. success = process_tpd_internal(p_tpd_name, tpdName, - actcfg, file_list_path, p_argc, p_argv, p_optind, p_ets_name, p_project_name, + actcfg, file_list_path, p_argc, p_argv, p_free_argv, p_optind, p_ets_name, p_project_name, p_gflag, p_sflag, p_cflag, p_aflag, preprocess, p_Rflag, p_lflag, p_mflag, p_Pflag, p_Lflag, recursive, force_overwrite, gen_only_top_level, @@ -1371,7 +1371,7 @@ extern "C" tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, } seen_tpd_files.clear(); - return success; + return TPD_SUCCESS; failure: /* free everything before exiting */ @@ -1394,20 +1394,33 @@ failure: Free(search_paths); Free(*generatorCommandOutput); + free_string2_list(run_command_list); free_string2_list(create_symlink_list); free_string2_list(target_placement_list); free_string2_list(required_configs); Free(*makefileScript); Free(*p_project_name); + Free(*abs_work_dir_p); Free(*p_ets_name); Free(*cxxcompiler); Free(*optlevel); Free(*optflags); Free(*ttcn3prep); - for (int E = 0; E < *p_argc; ++E) Free((*p_argv)[E]); - Free(*p_argv); - exit(EXIT_FAILURE); + if (*p_free_argv) { + for (int E = 0; E < *p_argc; ++E) Free((*p_argv)[E]); + Free(*p_argv); + } + + for (size_t i = 0, num = seen_tpd_files.size(); i < num; ++i) { + const cstring& key = seen_tpd_files.get_nth_key(i); + int *elem = seen_tpd_files.get_nth_elem(i); + key.destroy(); + delete elem; + } + seen_tpd_files.clear(); + + return TPD_FAILED; } // optind is the index of the next element of argv to be processed. @@ -1421,7 +1434,7 @@ failure: // If process_tpd() preserves the content of such a string (e.g. ets_name), // it must nevertheless make a copy on the heap via mcopystr(). static tpd_result process_tpd_internal(const char *p_tpd_name, char *tpdName, const char *actcfg, - const char *file_list_path, int *p_argc, char ***p_argv, + const char *file_list_path, int *p_argc, char ***p_argv, boolean* p_free_argv, int *p_optind, char **p_ets_name, char **p_project_name, boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess, boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag, @@ -1582,6 +1595,9 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, char *tpdName, co XPathObject projectNameObj(run_xpath(xpathCtx, projectNameXpath)); Free(projectNameXpath); if (projectNameObj->nodesetval && projectNameObj->nodesetval->nodeNr > 0) { + if (*p_project_name != NULL) { + Free(*p_project_name); + } *p_project_name = mcopystr((const char*)projectNameObj->nodesetval->nodeTab[0]->content); projGenHelper.addTarget(*p_project_name); projGenHelper.setToplevelProjectName(*p_project_name); @@ -2885,6 +2901,7 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, char *tpdName, co int my_argc = 0; char *my_args[] = { NULL }; char **my_argv = my_args + 0; + boolean my_free_argv = FALSE; int my_optind = 0; boolean my_gflag = *p_gflag, my_aflag = *p_aflag, my_cflag = *p_cflag, // pass down my_Rflag = *p_Rflag, my_Pflag = *p_Pflag, my_Zflag = *p_Zflag, my_Hflag = *p_Hflag, @@ -2936,7 +2953,7 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, char *tpdName, co } tpd_result success = process_tpd_internal((const char*)abs_projectLocationURI, tpdName_loc, - my_actcfg, file_list_path, &my_argc, &my_argv, &my_optind, &my_ets, &my_proj_name, + my_actcfg, file_list_path, &my_argc, &my_argv, &my_free_argv, &my_optind, &my_ets, &my_proj_name, &my_gflag, &my_sflag, &my_cflag, &my_aflag, preprocess, &my_Rflag, &my_lflag, &my_mflag, &my_Pflag, &my_Lflag, recursive, force_overwrite, gen_only_top_level, NULL, &sub_proj_abs_work_dir, sub_project_dirs, program_name, prj_graph_fp, create_symlink_list, ttcn3_prep_includes, ttcn3_prep_defines, ttcn3_prep_undefines, @@ -3017,21 +3034,31 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, char *tpdName, co const cstring tmp(my_argv[z]); if (!files.has_key(tmp)){ files.add(tmp, my_argv[z]); - } else { + } else if (my_free_argv) { Free(my_argv[z]); } } } - Free(my_argv); // free the array; we keep the pointers + if (my_free_argv) { + Free(my_argv); // free the array; we keep the pointers + } Free(my_ets); - Free(my_proj_name); } - else if (success == TPD_FAILED) { - ERROR("Failed to process %s", (const char*)abs_projectLocationURI); - result = TPD_FAILED; + else { + if (my_free_argv) { + for (int z = 0; z < my_argc; ++z) { + Free(my_argv[z]); + } + Free(my_argv); + } + if (success == TPD_FAILED) { + ERROR("Failed to process %s", (const char*)abs_projectLocationURI); + result = TPD_FAILED; + } + // else TPD_SKIPPED, keep quiet } - // else TPD_SKIPPED, keep quiet + Free(my_proj_name); Free(tpdName_loc); name = projectLocationURI = tpdName_loc = NULL; // forget all } @@ -3165,6 +3192,15 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, char *tpdName, co } // replace argv only if not config mode if (!get_config_mode) { + if (*p_free_argv) { + for (int i = 0; i < *p_argc; ++i) { + Free((*p_argv)[i]); + } + Free(*p_argv); + } + else { + *p_free_argv = TRUE; + } *p_argv = new_argv; *p_argc = new_argc; *p_optind = 0; @@ -3173,7 +3209,6 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, char *tpdName, co Free(new_argv[i]); } Free(new_argv); - Free(*p_project_name); } // finally... diff --git a/compiler2/xpather.h b/compiler2/xpather.h index e93420d13..c4565b7c5 100644 --- a/compiler2/xpather.h +++ b/compiler2/xpather.h @@ -272,7 +272,7 @@ enum #endif tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, const char *file_list_path, - int *argc, char ***argv, + int *argc, char ***argv, boolean* p_free_argv, int *optind, char **ets_name, char **project_name, boolean *gnu_make, boolean *single_mode, boolean *central_storage, boolean *absolute_paths, -- GitLab