diff --git a/lib/helper.c b/lib/helper.c index 68f98d9..0e0770f 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -9,6 +9,16 @@ #include #include +#ifdef _WIN32 + #define realpath(N,R) _fullpath((R),(N),_MAX_PATH) + #include + #ifndef PATH_MAX + #define PATH_MAX _MAX_PATH + #endif +#else + #include +#endif + #define VERBOSE 0 FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suffix) @@ -16,13 +26,37 @@ FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suff if (unshield && unshield->filename_pattern) { FILE* result = NULL; - char filename[256]; - char dirname[256]; + char* filename; + char* dirname; char * p = strrchr(unshield->filename_pattern, '/'); const char *q; struct dirent *dent = NULL; DIR *sourcedir; - snprintf(filename, sizeof(filename), unshield->filename_pattern, index, suffix); + long int path_max; + + #ifdef PATH_MAX + path_max = PATH_MAX; + #else + path_max = pathconf(prefix, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 4096; + #endif + + dirname = malloc(path_max); + filename = malloc(path_max); + if (filename == NULL || dirname == NULL) + { + unshield_error("Unable to allocate memory.\n"); + return false; + } + + if(snprintf(filename, path_max, unshield->filename_pattern, index, suffix)>=path_max) + { + unshield_error("Pathname exceeds system limits.\n"); + free(filename); + free(dirname); + return false; + } q=strrchr(filename,'/'); if (q) q++; @@ -31,11 +65,11 @@ FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suff if (p) { - strncpy( dirname, unshield->filename_pattern,sizeof(dirname)); - if ((unsigned int)(p-unshield->filename_pattern) > sizeof(dirname)) + strncpy( dirname, unshield->filename_pattern,path_max); + if ((unsigned int)(p-unshield->filename_pattern) > path_max) { unshield_trace("WARN: size\n"); - dirname[sizeof(dirname)-1]=0; + dirname[path_max-1]=0; } else dirname[(p-unshield->filename_pattern)] = 0; @@ -62,7 +96,13 @@ FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suff goto exit; } else - snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name); + if(snprintf(filename, path_max, "%s/%s", dirname, dent->d_name)>=path_max) + { + unshield_error("Pathname exceeds system limits.\n"); + free(filename); + free(dirname); + return false; + } } else unshield_trace("Could not open directory %s error %s\n", dirname, strerror(errno)); @@ -75,7 +115,8 @@ FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suff exit: if (sourcedir) closedir(sourcedir); - + free(filename); + free(dirname); return result; } diff --git a/src/unshield.c b/src/unshield.c index 2aeb118..e913b26 100644 --- a/src/unshield.c +++ b/src/unshield.c @@ -360,8 +360,8 @@ static bool handle_parameters( static bool extract_file(Unshield* unshield, const char* prefix, int index) { bool success; - char dirname[256]; - char filename[256]; + char* dirname; + char* filename; char* p; int directory = unshield_file_directory(unshield, index); long int path_max; @@ -378,6 +378,8 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index) real_output_directory = malloc(path_max); real_filename = malloc(path_max); + dirname = malloc(path_max); + filename = malloc(path_max); if (real_output_directory == NULL || real_filename == NULL) { fprintf(stderr,"Unable to allocate memory."); @@ -385,22 +387,68 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index) goto exit; } - strcpy(dirname, output_directory); - strcat(dirname, "/"); - if (prefix && prefix[0]) + if(strlen(output_directory) < path_max-2) { - strcat(dirname, prefix); + strncpy(dirname, output_directory,path_max-2); + if (path_max > 0) + dirname[path_max - 1]= '\0'; strcat(dirname, "/"); } + else + { + fprintf(stderr, "\nOutput directory exceeds maximum path length.\n"); + exit_status = 1; + success = false; + free(real_filename); + free(real_output_directory); + free(dirname); + free(filename); + return success; + } + + + if (prefix && prefix[0]) + { + if(strlen(dirname)+strlen(prefix) < path_max-2) + { + strcat(dirname, prefix); + strcat(dirname, "/"); + } + else + { + fprintf(stderr, "\nOutput directory exceeds maximum path length.\n"); + exit_status = 1; + success = false; + free(real_filename); + free(real_output_directory); + free(dirname); + free(filename); + return success; + } + } if (!junk_paths && directory >= 0) { const char* tmp = unshield_directory_name(unshield, directory); if (tmp && tmp[0]) { - strcat(dirname, tmp); - strcat(dirname, "/"); + if(strlen(dirname)+strlen(tmp) < path_max-2) + { + strcat(dirname, tmp); + strcat(dirname, "/"); + } + else + { + fprintf(stderr, "\nOutput directory exceeds maximum path length.\n"); + exit_status = 1; + success = false; + free(real_filename); + free(real_output_directory); + free(dirname); + free(filename); + return success; + } } } @@ -448,7 +496,7 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index) make_sure_directory_exists(dirname); - snprintf(filename, sizeof(filename), "%s%s", + snprintf(filename, path_max, "%s%s", dirname, unshield_file_name(unshield, index)); for (p = filename + strlen(dirname); *p != '\0'; p++) @@ -485,6 +533,8 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index) success = false; free(real_filename); free(real_output_directory); + free(dirname); + free(filename); return success; } @@ -513,6 +563,8 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index) } free(real_filename); free(real_output_directory); + free(dirname); + free(filename); return success; } @@ -630,7 +682,7 @@ static int list_files_helper(Unshield* unshield, const char* prefix, int first, for (i = first; i <= last; i++) { - char dirname[256]; + char dirname[4096]; if (unshield_file_is_valid(unshield, i) && should_process_file(unshield, i)) {