diff options
34 files changed, 138 insertions, 100 deletions
diff --git a/difftool/Makemodule.am b/difftool/Makemodule.am index 7eb6600..7488ff1 100644 --- a/difftool/Makemodule.am +++ b/difftool/Makemodule.am @@ -2,6 +2,6 @@ sqfsdiff_SOURCES = difftool/sqfsdiff.c difftool/sqfsdiff.h difftool/util.c sqfsdiff_SOURCES += difftool/compare_dir.c difftool/node_compare.c sqfsdiff_SOURCES += difftool/compare_files.c difftool/super.c sqfsdiff_SOURCES += difftool/extract.c difftool/options.c -sqfsdiff_LDADD = libcommon.a libsquashfs.la libutil.la $(LZO_LIBS) libfstree.a +sqfsdiff_LDADD = libcommon.a libsquashfs.la libcompat.a $(LZO_LIBS) libfstree.a bin_PROGRAMS += sqfsdiff diff --git a/include/compat.h b/include/compat.h index 26ad69b..82b1c7e 100644 --- a/include/compat.h +++ b/include/compat.h @@ -59,6 +59,9 @@ #define le16toh(x) (x) #define le32toh(x) (x) #define le64toh(x) (x) + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> #else #include <endian.h> #endif @@ -164,4 +167,8 @@ char *strndup(const char *str, size_t max_len); int getsubopt(char **opt, char *const *keys, char **val); #endif +#if defined(_WIN32) || defined(__WINDOWS__) +WCHAR *path_to_windows(const char *input); +#endif + #endif /* COMPAT_H */ diff --git a/include/util/util.h b/include/util/util.h index 7aa4f31..ed1102b 100644 --- a/include/util/util.h +++ b/include/util/util.h @@ -18,19 +18,4 @@ #define container_of(ptr, type, member) \ ((type *)((char *)ptr - offsetof(type, member))) -/* - Helper for allocating data structures with flexible array members. - - 'base_size' is the size of the struct itself, 'item_size' the size of a - single array element and 'nmemb' the number of elements. - - Iternally checks for arithmetic overflows when allocating the combined thing. - */ -SQFS_INTERNAL -void *alloc_flex(size_t base_size, size_t item_size, size_t nmemb); - -/* Basically the same as calloc, but *ALWAYS* does overflow checking */ -SQFS_INTERNAL -void *alloc_array(size_t item_size, size_t nmemb); - #endif /* UTIL_H */ diff --git a/lib/common/comp_lzo.c b/lib/common/comp_lzo.c index 473b76f..cf5a362 100644 --- a/lib/common/comp_lzo.c +++ b/lib/common/comp_lzo.c @@ -176,7 +176,7 @@ static sqfs_compressor_t *lzo_create_copy(sqfs_compressor_t *cmp) lzo_compressor_t *other = (lzo_compressor_t *)cmp; lzo_compressor_t *lzo; - lzo = alloc_flex(sizeof(*lzo), 1, lzo_algs[other->algorithm].bufsize); + lzo = calloc(1, sizeof(*lzo) + lzo_algs[other->algorithm].bufsize); if (lzo == NULL) return NULL; @@ -209,8 +209,8 @@ sqfs_compressor_t *lzo_compressor_create(const sqfs_compressor_config_t *cfg) return NULL; } - lzo = alloc_flex(sizeof(*lzo), 1, - lzo_algs[cfg->opt.lzo.algorithm].bufsize); + lzo = calloc(1, + sizeof(*lzo) + lzo_algs[cfg->opt.lzo.algorithm].bufsize); base = (sqfs_compressor_t *)lzo; if (lzo == NULL) diff --git a/lib/common/mkdir_p.c b/lib/common/mkdir_p.c index a568567..0413495 100644 --- a/lib/common/mkdir_p.c +++ b/lib/common/mkdir_p.c @@ -12,9 +12,6 @@ #include <errno.h> #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - /* Supported paths: - <letter>:\ <absolute path> @@ -85,25 +82,13 @@ static WCHAR *skip_prefix(WCHAR *ptr) int mkdir_p(const char *path) { WCHAR *wpath, *ptr, *end; - DWORD length, error; + DWORD error; bool done; - length = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) + 1; - wpath = alloc_array(sizeof(wpath[0]), length); - if (wpath == NULL) { - fprintf(stderr, "Converting UTF-8 path to UTF-16: %ld\n", - GetLastError()); + wpath = path_to_windows(path); + if (wpath == NULL) return -1; - } - - MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, length); - wpath[length - 1] = '\0'; - - for (ptr = wpath; *ptr != '\0'; ++ptr) { - if (*ptr == '/') - *ptr = '\\'; - } ptr = skip_prefix(wpath); if (ptr == NULL) { diff --git a/lib/common/serialize_fstree.c b/lib/common/serialize_fstree.c index 14a5a4e..42843e2 100644 --- a/lib/common/serialize_fstree.c +++ b/lib/common/serialize_fstree.c @@ -19,7 +19,7 @@ static sqfs_inode_generic_t *tree_node_to_inode(tree_node_t *node) if (S_ISLNK(node->mode)) extra = strlen(node->data.slink_target); - inode = alloc_flex(sizeof(*inode), 1, extra); + inode = calloc(1, sizeof(*inode) + extra); if (inode == NULL) { perror("creating inode"); return NULL; diff --git a/lib/common/write_export_table.c b/lib/common/write_export_table.c index c797577..c0d4993 100644 --- a/lib/common/write_export_table.c +++ b/lib/common/write_export_table.c @@ -20,7 +20,7 @@ int write_export_table(const char *filename, sqfs_file_t *file, if (fs->inode_tbl_size < 1) return 0; - table = alloc_array(sizeof(sqfs_u64), fs->inode_tbl_size); + table = calloc(1, sizeof(sqfs_u64) * fs->inode_tbl_size); if (table == NULL) { perror("Allocating NFS export table"); diff --git a/lib/compat/Makemodule.am b/lib/compat/Makemodule.am index fb37b46..7137f2c 100644 --- a/lib/compat/Makemodule.am +++ b/lib/compat/Makemodule.am @@ -1,5 +1,6 @@ libcompat_a_SOURCES = lib/compat/getline.c lib/compat/getsubopt.c libcompat_a_SOURCES += lib/compat/strndup.c lib/compat/mockups.c libcompat_a_SOURCES += lib/compat/chdir.c include/compat.h +libcompat_a_SOURCES += lib/compat/path_to_windows.c noinst_LIBRARIES += libcompat.a diff --git a/lib/compat/chdir.c b/lib/compat/chdir.c index b1b2d0c..04dcf17 100644 --- a/lib/compat/chdir.c +++ b/lib/compat/chdir.c @@ -10,37 +10,16 @@ #include "util/util.h" #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> #include <stdlib.h> int chdir(const char *path) { - WCHAR *wpath, *ptr; - DWORD length; + WCHAR *wpath; int ret; - length = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); - if (length <= 0) { - fprintf(stderr, "Converting '%s' to UTF-16: %ld\n", - path, GetLastError()); - return -1; - } - - wpath = alloc_array(sizeof(wpath[0]), length + 1); - if (wpath == NULL) { - fprintf(stderr, "Converting '%s' to UTF-16: out of memory\n", - path); + wpath = path_to_windows(path); + if (wpath == NULL) return -1; - } - - MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, length + 1); - wpath[length] = '\0'; - - for (ptr = wpath; *ptr != '\0'; ++ptr) { - if (*ptr == '/') - *ptr = '\\'; - } if (!SetCurrentDirectoryW(wpath)) { fprintf(stderr, "Switching to directory '%s': %ld\n", diff --git a/lib/compat/path_to_windows.c b/lib/compat/path_to_windows.c new file mode 100644 index 0000000..ff3a5d2 --- /dev/null +++ b/lib/compat/path_to_windows.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * path_to_windows.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "compat.h" + +#include <stdlib.h> +#include <stdio.h> + +#if defined(_WIN32) || defined(__WINDOWS__) +WCHAR *path_to_windows(const char *input) +{ + WCHAR *wpath, *ptr; + DWORD length; + + length = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0); + if (length <= 0) { + fprintf(stderr, "Converting UTF-8 path to UTF-16: %ld\n", + GetLastError()); + return NULL; + } + + wpath = calloc(sizeof(wpath[0]), length + 1); + if (wpath == NULL) { + fprintf(stderr, + "Converting UTF-8 path to UTF-16: out of memory\n"); + return NULL; + } + + MultiByteToWideChar(CP_UTF8, 0, input, -1, wpath, length + 1); + wpath[length] = '\0'; + + for (ptr = wpath; *ptr != '\0'; ++ptr) { + if (*ptr == '/') + *ptr = '\\'; + } + + return wpath; +} +#endif diff --git a/lib/fstree/gen_inode_table.c b/lib/fstree/gen_inode_table.c index d97c645..a5a28c9 100644 --- a/lib/fstree/gen_inode_table.c +++ b/lib/fstree/gen_inode_table.c @@ -61,8 +61,7 @@ int fstree_gen_inode_table(fstree_t *fs) size_t inum = 1; fs->inode_tbl_size = count_nodes(fs->root); - fs->inode_table = alloc_array(sizeof(tree_node_t *), - fs->inode_tbl_size); + fs->inode_table = calloc(1, sizeof(tree_node_t*) * fs->inode_tbl_size); if (fs->inode_table == NULL) { perror("allocating inode table"); diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am index be405cf..59cdbcb 100644 --- a/lib/sqfs/Makemodule.am +++ b/lib/sqfs/Makemodule.am @@ -24,6 +24,7 @@ libsquashfs_la_SOURCES += lib/sqfs/data_writer/internal.h lib/sqfs/data_reader.c libsquashfs_la_SOURCES += lib/sqfs/data_writer/common.c libsquashfs_la_SOURCES += lib/sqfs/data_writer/fileapi.c libsquashfs_la_SOURCES += lib/sqfs/str_table.c lib/sqfs/str_table.h +libsquashfs_la_SOURCES += lib/sqfs/alloc.c lib/sqfs/util.h libsquashfs_la_CPPFLAGS = $(AM_CPPFLAGS) libsquashfs_la_LDFLAGS = $(AM_LDFLAGS) libsquashfs_la_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS) diff --git a/lib/util/alloc.c b/lib/sqfs/alloc.c index 526a4d5..e8305d8 100644 --- a/lib/util/alloc.c +++ b/lib/sqfs/alloc.c @@ -6,9 +6,8 @@ */ #include "config.h" -#include "util/util.h" +#include "util.h" -#include <stddef.h> #include <stdlib.h> #include <errno.h> diff --git a/lib/sqfs/comp/internal.h b/lib/sqfs/comp/internal.h index dabf1a6..c687d41 100644 --- a/lib/sqfs/comp/internal.h +++ b/lib/sqfs/comp/internal.h @@ -14,7 +14,7 @@ #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" -#include "util/util.h" +#include "../util.h" SQFS_INTERNAL int sqfs_generic_write_options(sqfs_file_t *file, const void *data, diff --git a/lib/sqfs/data_reader.c b/lib/sqfs/data_reader.c index b105096..6a0db35 100644 --- a/lib/sqfs/data_reader.c +++ b/lib/sqfs/data_reader.c @@ -14,7 +14,7 @@ #include "sqfs/table.h" #include "sqfs/inode.h" #include "sqfs/io.h" -#include "util/util.h" +#include "util.h" #include <stdlib.h> #include <string.h> diff --git a/lib/sqfs/data_writer/internal.h b/lib/sqfs/data_writer/internal.h index 9c64b6c..d6e26cd 100644 --- a/lib/sqfs/data_writer/internal.h +++ b/lib/sqfs/data_writer/internal.h @@ -16,7 +16,7 @@ #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" -#include "util/util.h" +#include "../util.h" #include <string.h> #include <stdlib.h> diff --git a/lib/sqfs/dir_reader.c b/lib/sqfs/dir_reader.c index bae24d5..bda7d7a 100644 --- a/lib/sqfs/dir_reader.c +++ b/lib/sqfs/dir_reader.c @@ -14,7 +14,7 @@ #include "sqfs/inode.h" #include "sqfs/error.h" #include "sqfs/dir.h" -#include "util/util.h" +#include "util.h" #include <string.h> #include <stdlib.h> diff --git a/lib/sqfs/dir_writer.c b/lib/sqfs/dir_writer.c index 673c103..bdd5dd1 100644 --- a/lib/sqfs/dir_writer.c +++ b/lib/sqfs/dir_writer.c @@ -13,7 +13,7 @@ #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/dir.h" -#include "util/util.h" +#include "util.h" #include <stdlib.h> #include <string.h> diff --git a/lib/sqfs/meta_reader.c b/lib/sqfs/meta_reader.c index 0b8b33a..19e856a 100644 --- a/lib/sqfs/meta_reader.c +++ b/lib/sqfs/meta_reader.c @@ -12,7 +12,7 @@ #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" -#include "util/util.h" +#include "util.h" #include <stdlib.h> #include <string.h> diff --git a/lib/sqfs/meta_writer.c b/lib/sqfs/meta_writer.c index cdd34e8..acb2235 100644 --- a/lib/sqfs/meta_writer.c +++ b/lib/sqfs/meta_writer.c @@ -12,7 +12,7 @@ #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" -#include "util/util.h" +#include "util.h" #include <string.h> #include <stdlib.h> diff --git a/lib/sqfs/read_inode.c b/lib/sqfs/read_inode.c index fa3ec31..11d7a1c 100644 --- a/lib/sqfs/read_inode.c +++ b/lib/sqfs/read_inode.c @@ -12,7 +12,7 @@ #include "sqfs/super.h" #include "sqfs/inode.h" #include "sqfs/dir.h" -#include "util/util.h" +#include "util.h" #include <stdlib.h> #include <string.h> diff --git a/lib/sqfs/read_super.c b/lib/sqfs/read_super.c index f5cc988..8b3f019 100644 --- a/lib/sqfs/read_super.c +++ b/lib/sqfs/read_super.c @@ -10,7 +10,7 @@ #include "sqfs/super.h" #include "sqfs/error.h" #include "sqfs/io.h" -#include "util/util.h" +#include "util.h" #include <string.h> diff --git a/lib/sqfs/read_table.c b/lib/sqfs/read_table.c index 747c8bc..096ac1a 100644 --- a/lib/sqfs/read_table.c +++ b/lib/sqfs/read_table.c @@ -12,7 +12,7 @@ #include "sqfs/table.h" #include "sqfs/block.h" #include "sqfs/io.h" -#include "util/util.h" +#include "util.h" #include <stdlib.h> diff --git a/lib/sqfs/read_tree.c b/lib/sqfs/read_tree.c index eaf7c16..5464595 100644 --- a/lib/sqfs/read_tree.c +++ b/lib/sqfs/read_tree.c @@ -15,7 +15,7 @@ #include "sqfs/inode.h" #include "sqfs/error.h" #include "sqfs/dir.h" -#include "util/util.h" +#include "util.h" #include <string.h> #include <stdlib.h> diff --git a/lib/sqfs/str_table.c b/lib/sqfs/str_table.c index 1ec0ef7..c0a364f 100644 --- a/lib/sqfs/str_table.c +++ b/lib/sqfs/str_table.c @@ -11,8 +11,8 @@ #include <string.h> #include "sqfs/error.h" -#include "util/util.h" #include "str_table.h" +#include "util.h" /* R5 hash function (borrowed from reiserfs) */ static sqfs_u32 strhash(const char *s) diff --git a/lib/sqfs/util.h b/lib/sqfs/util.h new file mode 100644 index 0000000..a379c0d --- /dev/null +++ b/lib/sqfs/util.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * util.h + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#ifndef SQFS_UTIL_H +#define SQFS_UTIL_H + +#include "config.h" +#include "sqfs/predef.h" +#include "compat.h" + +#include <stddef.h> + +/* + Helper for allocating data structures with flexible array members. + + 'base_size' is the size of the struct itself, 'item_size' the size of a + single array element and 'nmemb' the number of elements. + + Iternally checks for arithmetic overflows when allocating the combined thing. + */ +SQFS_INTERNAL +void *alloc_flex(size_t base_size, size_t item_size, size_t nmemb); + +/* Basically the same as calloc, but *ALWAYS* does overflow checking */ +SQFS_INTERNAL +void *alloc_array(size_t item_size, size_t nmemb); + +#endif /* SQFS_UTIL_H */ diff --git a/lib/sqfs/write_table.c b/lib/sqfs/write_table.c index b8946a5..1931b83 100644 --- a/lib/sqfs/write_table.c +++ b/lib/sqfs/write_table.c @@ -13,7 +13,7 @@ #include "sqfs/table.h" #include "sqfs/block.h" #include "sqfs/io.h" -#include "util/util.h" +#include "util.h" #include <stdlib.h> diff --git a/lib/sqfs/xattr_reader.c b/lib/sqfs/xattr_reader.c index 250b4bd..d5b003b 100644 --- a/lib/sqfs/xattr_reader.c +++ b/lib/sqfs/xattr_reader.c @@ -14,7 +14,7 @@ #include "sqfs/error.h" #include "sqfs/block.h" #include "sqfs/io.h" -#include "util/util.h" +#include "util.h" #include <stdlib.h> #include <string.h> diff --git a/lib/sqfs/xattr_writer.c b/lib/sqfs/xattr_writer.c index 2e6a074..047e411 100644 --- a/lib/sqfs/xattr_writer.c +++ b/lib/sqfs/xattr_writer.c @@ -15,8 +15,8 @@ #include "sqfs/block.h" #include "sqfs/io.h" -#include "util/util.h" #include "str_table.h" +#include "util.h" #include <stdlib.h> #include <string.h> diff --git a/lib/util/Makemodule.am b/lib/util/Makemodule.am index 426e088..0ee762b 100644 --- a/lib/util/Makemodule.am +++ b/lib/util/Makemodule.am @@ -1,4 +1,4 @@ -libutil_la_SOURCES = include/util/util.h lib/util/alloc.c +libutil_la_SOURCES = include/util/util.h libutil_la_CFLAGS = $(AM_CFLAGS) libutil_la_CPPFLAGS = $(AM_CPPFLAGS) libutil_la_LDFLAGS = $(AM_LDFLAGS) diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c index 7484618..6ddcdb0 100644 --- a/mkfs/mkfs.c +++ b/mkfs/mkfs.c @@ -50,6 +50,7 @@ static int pack_files(sqfs_data_writer_t *data, fstree_t *fs, const char *path; char *node_path; file_info_t *fi; + size_t size; int ret; if (set_working_dir(opt)) @@ -90,8 +91,16 @@ static int pack_files(sqfs_data_writer_t *data, fstree_t *fs, if (filesize % opt->cfg.block_size) ++max_blk_count; - inode = alloc_flex(sizeof(*inode), sizeof(sqfs_u32), - max_blk_count); + if (SZ_MUL_OV(sizeof(sqfs_u32), max_blk_count, &size) || + SZ_ADD_OV(sizeof(*inode), size, &size)) { + fputs("creating file inode: too many blocks\n", + stderr); + file->destroy(file); + free(node_path); + return -1; + } + + inode = calloc(1, size); if (inode == NULL) { perror("creating file inode"); file->destroy(file); diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c index d0f2851..0076537 100644 --- a/tar/tar2sqfs.c +++ b/tar/tar2sqfs.c @@ -6,6 +6,7 @@ */ #include "config.h" #include "common.h" +#include "compat.h" #include "tar.h" #include <stdlib.h> @@ -213,7 +214,7 @@ static int write_file(tar_header_decoded_t *hdr, file_info_t *fi, { const sparse_map_t *it; sqfs_inode_generic_t *inode; - size_t max_blk_count; + size_t size, max_blk_count; sqfs_file_t *file; sqfs_u64 sum; int ret; @@ -222,7 +223,14 @@ static int write_file(tar_header_decoded_t *hdr, file_info_t *fi, if (filesize % cfg.block_size) ++max_blk_count; - inode = alloc_flex(sizeof(*inode), sizeof(sqfs_u32), max_blk_count); + if (SZ_MUL_OV(sizeof(sqfs_u32), max_blk_count, &size) || + SZ_ADD_OV(sizeof(*inode), size, &size)) { + fputs("creating file inode: too many blocks\n", + stderr); + return -1; + } + + inode = calloc(1, size); if (inode == NULL) { perror("creating file inode"); return -1; diff --git a/tests/Makemodule.am b/tests/Makemodule.am index 72d99ba..62cf813 100644 --- a/tests/Makemodule.am +++ b/tests/Makemodule.am @@ -2,6 +2,7 @@ test_canonicalize_name_SOURCES = tests/canonicalize_name.c test_canonicalize_name_LDADD = libfstree.a test_str_table_SOURCES = tests/str_table.c lib/sqfs/str_table.c +test_str_table_SOURCES += lib/sqfs/alloc.c lib/sqfs/util.h test_str_table_SOURCES += lib/sqfs/str_table.h test_str_table_LDADD = libutil.la libcompat.a test_str_table_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(top_srcdir)/tests diff --git a/unpack/restore_fstree.c b/unpack/restore_fstree.c index 7cecf16..1de9b05 100644 --- a/unpack/restore_fstree.c +++ b/unpack/restore_fstree.c @@ -9,22 +9,12 @@ #ifdef _WIN32 static int create_node(const sqfs_tree_node_t *n, const char *name) { - WCHAR *wpath = NULL; - DWORD length; + WCHAR *wpath; HANDLE fh; - length = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) + 1; - if (length <= 0) - goto fail; - - wpath = alloc_array(sizeof(wpath[0]), length); - if (wpath == NULL) { - perror(name); + wpath = path_to_windows(name); + if (wpath == NULL) return -1; - } - - MultiByteToWideChar(CP_UTF8, 0, name, -1, wpath, length); - wpath[length - 1] = '\0'; switch (n->inode->base.mode & S_IFMT) { case S_IFDIR: |