diff --git a/lib/pkg_editor/src/pkg_editor.c b/lib/pkg_editor/src/pkg_editor.c index 3b27216b..6f4e8b38 100644 --- a/lib/pkg_editor/src/pkg_editor.c +++ b/lib/pkg_editor/src/pkg_editor.c @@ -493,7 +493,13 @@ static char *read_file_into_buffer(struct acl_pkg_file *pkg, // get file size fseek(f, 0, SEEK_END); - file_size = ftell(f); + const long ftell_return = ftell(f); + if (ftell_return < 0) { + fprintf(stderr, "Couldn't determine size of file %s\n", in_file); + fclose(f); + return NULL; + } + file_size = (size_t)ftell_return; rewind(f); // slurp the whole file into allocated buf @@ -1307,9 +1313,6 @@ static acl_pack_kind add_file(const char *out_file, FILE *of, const char *file, static acl_pack_kind add_directory(const char *out_file, FILE *of, const char *dir_name, ZInfo *z_info) { -#ifdef FULL_NAME_LENGTH -#undef FULL_NAME_LENGTH -#endif acl_pkg_pack_info info; size_t name_length = strlen(dir_name) + 1; @@ -1335,24 +1338,31 @@ static acl_pack_kind add_directory(const char *out_file, FILE *of, // Now walk the directory processing each name. { + #ifdef _WIN32 #define FULL_NAME_LENGTH (2 * MAX_PATH) +#else +#define FULL_NAME_LENGTH (2 * PATH_MAX) +#endif + char full_name[FULL_NAME_LENGTH]; - if (FULL_NAME_LENGTH < name_length) { + + // Full name must be large enough to store dir_name plus a trailing path + // separator + if (name_length + 1 > FULL_NAME_LENGTH) { fprintf(stderr, "acl_pkg_pack: Failed to write to %s: %s\n", out_file, "Directory name too long"); return PACK_END; } +#ifdef _WIN32 HANDLE file_handle; WIN32_FIND_DATA file_info; // Partially initialize the full path name. - strncpy(full_name, dir_name, FULL_NAME_LENGTH); + strncpy(full_name, dir_name, FULL_NAME_LENGTH - 1); strncpy(full_name + name_length - 1, "\\*.*", - FULL_NAME_LENGTH - name_length + 1); - if (full_name[FULL_NAME_LENGTH - 1] != '\0') { - full_name[FULL_NAME_LENGTH - 1] = '\0'; - } + FULL_NAME_LENGTH - name_length); + full_name[FULL_NAME_LENGTH - 1] = '\0'; // Walk through all the files in the directory. file_handle = FindFirstFile(full_name, &file_info); @@ -1366,10 +1376,9 @@ static acl_pack_kind add_directory(const char *out_file, FILE *of, // Finish the full file name strncpy(full_name + name_length, file_info.cFileName, - FULL_NAME_LENGTH - name_length); - if (full_name[FULL_NAME_LENGTH - 1] != '\0') { - full_name[FULL_NAME_LENGTH - 1] = '\0'; - } + FULL_NAME_LENGTH - name_length - 1); + full_name[FULL_NAME_LENGTH - 1] = '\0'; + if (add_file_or_dir(out_file, of, full_name, z_info) == PACK_END) { FindClose(file_handle); return PACK_END; @@ -1380,14 +1389,6 @@ static acl_pack_kind add_directory(const char *out_file, FILE *of, // Linux DIR *dir; struct dirent *entry; -#define FULL_NAME_LENGTH (2 * PATH_MAX) - char full_name[FULL_NAME_LENGTH]; - if (FULL_NAME_LENGTH < name_length) { - fprintf(stderr, "acl_pkg_pack: Failed to write to %s: %s\n", out_file, - "Directory name too long"); - return PACK_END; - } - // Partially initialize the full path name. strncpy(full_name, dir_name, FULL_NAME_LENGTH - 1); full_name[FULL_NAME_LENGTH - 1] = '\0'; @@ -1408,10 +1409,9 @@ static acl_pack_kind add_directory(const char *out_file, FILE *of, // Finish the full file name, truncate name if the file is too long to // avoid buffer overflow size_t buffer_space_left = FULL_NAME_LENGTH - name_length; - strncpy(full_name + name_length, entry->d_name, buffer_space_left); - if (full_name[FULL_NAME_LENGTH - 1] != '\0') { - full_name[FULL_NAME_LENGTH - 1] = '\0'; - } + strncpy(full_name + name_length, entry->d_name, buffer_space_left - 1); + full_name[FULL_NAME_LENGTH - 1] = '\0'; + if (add_file_or_dir(out_file, of, full_name, z_info) == PACK_END) { closedir(dir); return PACK_END; @@ -1421,6 +1421,7 @@ static acl_pack_kind add_directory(const char *out_file, FILE *of, } closedir(dir); #endif +#undef FULL_NAME_LENGTH } return PACK_DIR; } @@ -1513,6 +1514,17 @@ int acl_pkg_pack(const char *out_file, const char **input_files_dirs) { return 1 /* success */; } +static void create_dir(const char *dir_name) { + // Create output directory. We can ignore the error output since it will + // only delay the failure to the first attempt of creating a file in the + // (not) newly created directory. +#ifdef _WIN32 + (void)CreateDirectory(dir_name, NULL); +#else + (void)mkdir(dir_name, 0755); +#endif +} + static int read_data(void *data, size_t size, ZInfo *z_info, FILE *in_fd) { // We want to fill 'data' with 'size' bytes. z_info->strm.next_out = data; @@ -1555,12 +1567,6 @@ static int read_data(void *data, size_t size, ZInfo *z_info, FILE *in_fd) { static int acl_pkg_unpack_buffer_or_file(const char *buffer, size_t buffer_size, FILE *input, const char *out_dir, const char *routine_name) { -#ifdef FULL_NAME_LEN -#undef FULL_NAME_LEN -#endif -#ifdef NAME_LEN -#undef NAME_LEN -#endif #ifdef _WIN32 #define FULL_NAME_LEN (3 * MAX_PATH) #define NAME_LEN (2 * MAX_PATH) @@ -1598,12 +1604,7 @@ static int acl_pkg_unpack_buffer_or_file(const char *buffer, size_t buffer_size, return 0; } - // Create output directory (ignore any errors). -#ifdef _WIN32 - CreateDirectory(full_name, NULL); -#else - mkdir(full_name, 0755); -#endif + create_dir(full_name); full_name[out_dir_length] = '/'; // Process the file until we hit the PACK_END record (or finish the @@ -1635,22 +1636,21 @@ static int acl_pkg_unpack_buffer_or_file(const char *buffer, size_t buffer_size, return 0; } - // Generate the full name, truncate or zero pad to avoid buffer overflow - if (FULL_NAME_LEN < out_dir_length) { + // Generate the full name, truncate or zero pad to avoid buffer overflow. + // FULL_NAME_LEN must be large enough to store out_dir and a trailing path + // separator and null terminator + if (out_dir_length + 2 > FULL_NAME_LEN) { fprintf(stderr, "%s: Directory name too long\n", routine_name); + inflateEnd(&z_info.strm); + return 0; } + strncpy(full_name + out_dir_length + 1, name, - FULL_NAME_LEN - out_dir_length - 1); - if (full_name[FULL_NAME_LEN - 1] != '\0') { - full_name[FULL_NAME_LEN - 1] = '\0'; - } + FULL_NAME_LEN - out_dir_length - 2); + full_name[FULL_NAME_LEN - 1] = '\0'; if (info.kind == PACK_DIR) { -#ifdef _WIN32 - CreateDirectory(full_name, NULL); -#else - mkdir(full_name, 0755); -#endif + create_dir(full_name); } else { // Read file contents FILE *out_file = fopen(full_name, "wb"); @@ -1712,6 +1712,8 @@ static int acl_pkg_unpack_buffer_or_file(const char *buffer, size_t buffer_size, inflateEnd(&z_info.strm); return 1; +#undef FULL_NAME_LEN +#undef NAME_LEN } int acl_pkg_unpack_buffer(const char *buffer, size_t buffer_size,