mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[cmp] update Bled to latest
* Also try to fix the fallthrough Coverity warning in format_ext.c
This commit is contained in:
		
							parent
							
								
									2cf183e9f1
								
							
						
					
					
						commit
						07d1fdcc2f
					
				
					 15 changed files with 485 additions and 267 deletions
				
			
		|  | @ -64,6 +64,9 @@ typedef struct archive_handle_t { | ||||||
| 	/* Currently processed file's header */ | 	/* Currently processed file's header */ | ||||||
| 	file_header_t *file_header; | 	file_header_t *file_header; | ||||||
| 
 | 
 | ||||||
|  | 	/* List of link placeholders */ | ||||||
|  | 	llist_t *link_placeholders; | ||||||
|  | 
 | ||||||
| 	/* Process the header component, e.g. tar -t */ | 	/* Process the header component, e.g. tar -t */ | ||||||
| 	void FAST_FUNC (*action_header)(const file_header_t *); | 	void FAST_FUNC (*action_header)(const file_header_t *); | ||||||
| 
 | 
 | ||||||
|  | @ -77,6 +80,9 @@ typedef struct archive_handle_t { | ||||||
| 	off_t offset; | 	off_t offset; | ||||||
| 
 | 
 | ||||||
| 	/* Archiver specific. Can make it a union if it ever gets big */ | 	/* Archiver specific. Can make it a union if it ever gets big */ | ||||||
|  | #if ENABLE_FEATURE_TAR_LONG_OPTIONS | ||||||
|  | 	unsigned tar__strip_components; | ||||||
|  | #endif | ||||||
| #define PAX_NEXT_FILE 0 | #define PAX_NEXT_FILE 0 | ||||||
| #define PAX_GLOBAL    1 | #define PAX_GLOBAL    1 | ||||||
| #if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB | #if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB | ||||||
|  | @ -95,6 +101,7 @@ typedef struct archive_handle_t { | ||||||
| #endif | #endif | ||||||
| #if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM | #if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM | ||||||
| 	uoff_t cpio__blocks; | 	uoff_t cpio__blocks; | ||||||
|  | 	struct bb_uidgid_t cpio__owner; | ||||||
| 	struct hardlinks_t *cpio__hardlinks_to_create; | 	struct hardlinks_t *cpio__hardlinks_to_create; | ||||||
| 	struct hardlinks_t *cpio__created_hardlinks; | 	struct hardlinks_t *cpio__created_hardlinks; | ||||||
| #endif | #endif | ||||||
|  | @ -110,20 +117,23 @@ typedef struct archive_handle_t { | ||||||
| 	const char *ar__name; | 	const char *ar__name; | ||||||
| 	struct archive_handle_t *ar__out; | 	struct archive_handle_t *ar__out; | ||||||
| #endif | #endif | ||||||
|  | #if ENABLE_FEATURE_AR_LONG_FILENAMES | ||||||
|  | 	char *ar__long_names; | ||||||
|  | 	unsigned ar__long_name_size; | ||||||
|  | #endif | ||||||
| } archive_handle_t; | } archive_handle_t; | ||||||
| /* bits in ah_flags */ | /* bits in ah_flags */ | ||||||
| #define ARCHIVE_RESTORE_DATE        (1 << 0) | #define ARCHIVE_RESTORE_DATE        (1 << 0) | ||||||
| #define ARCHIVE_CREATE_LEADING_DIRS (1 << 1) | #define ARCHIVE_CREATE_LEADING_DIRS (1 << 1) | ||||||
| #define ARCHIVE_UNLINK_OLD          (1 << 2) | #define ARCHIVE_UNLINK_OLD          (1 << 2) | ||||||
| #define ARCHIVE_EXTRACT_QUIET       (1 << 3) | #define ARCHIVE_EXTRACT_NEWER       (1 << 3) | ||||||
| #define ARCHIVE_EXTRACT_NEWER       (1 << 4) | #define ARCHIVE_DONT_RESTORE_OWNER  (1 << 4) | ||||||
| #define ARCHIVE_DONT_RESTORE_OWNER  (1 << 5) | #define ARCHIVE_DONT_RESTORE_PERM   (1 << 5) | ||||||
| #define ARCHIVE_DONT_RESTORE_PERM   (1 << 6) | #define ARCHIVE_NUMERIC_OWNER       (1 << 6) | ||||||
| #define ARCHIVE_NUMERIC_OWNER       (1 << 7) | #define ARCHIVE_O_TRUNC             (1 << 7) | ||||||
| #define ARCHIVE_O_TRUNC             (1 << 8) | #define ARCHIVE_REMEMBER_NAMES      (1 << 8) | ||||||
| #define ARCHIVE_REMEMBER_NAMES      (1 << 9) |  | ||||||
| #if ENABLE_RPM | #if ENABLE_RPM | ||||||
| #define ARCHIVE_REPLACE_VIA_RENAME  (1 << 10) | #define ARCHIVE_REPLACE_VIA_RENAME  (1 << 9) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -157,6 +167,11 @@ typedef struct tar_header_t {     /* byte offset */ | ||||||
| struct BUG_tar_header { | struct BUG_tar_header { | ||||||
| 	char c[sizeof(tar_header_t) == TAR_BLOCK_SIZE ? 1 : -1]; | 	char c[sizeof(tar_header_t) == TAR_BLOCK_SIZE ? 1 : -1]; | ||||||
| }; | }; | ||||||
|  | void chksum_and_xwrite_tar_header(int fd, struct tar_header_t *hp) FAST_FUNC; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | extern const char cpio_TRAILER[]; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| archive_handle_t *init_handle(void) FAST_FUNC; | archive_handle_t *init_handle(void) FAST_FUNC; | ||||||
| 
 | 
 | ||||||
|  | @ -188,22 +203,22 @@ void seek_by_jump(int fd, off_t amount) FAST_FUNC; | ||||||
| void seek_by_read(int fd, off_t amount) FAST_FUNC; | void seek_by_read(int fd, off_t amount) FAST_FUNC; | ||||||
| 
 | 
 | ||||||
| const char *strip_unsafe_prefix(const char *str) FAST_FUNC; | const char *strip_unsafe_prefix(const char *str) FAST_FUNC; | ||||||
|  | void create_or_remember_link(llist_t **link_placeholders, | ||||||
|  | 		const char *target, | ||||||
|  | 		const char *linkname, | ||||||
|  | 		int hard_link) FAST_FUNC; | ||||||
|  | void create_links_from_list(llist_t *list) FAST_FUNC; | ||||||
| 
 | 
 | ||||||
| void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; | void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; | ||||||
| const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC; | const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC; | ||||||
| const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; | const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; | ||||||
| 
 | 
 | ||||||
| /* A bit of bunzip2 internals are exposed for compressed help support: */ | /* A bit of bunzip2 internals are exposed for compressed help support: */ | ||||||
| typedef struct bunzip_data bunzip_data; | char *unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) FAST_FUNC; | ||||||
| int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; |  | ||||||
| /* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes
 |  | ||||||
|  * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */ |  | ||||||
| int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; |  | ||||||
| void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; |  | ||||||
| 
 | 
 | ||||||
| /* Meaning and direction (input/output) of the fields are transformer-specific */ | /* Meaning and direction (input/output) of the fields are transformer-specific */ | ||||||
| typedef struct transformer_state_t { | typedef struct transformer_state_t { | ||||||
| 	int8_t      check_signature;        /* most often referenced member */ | 	int8_t   signature_skipped; /* most often referenced member */ | ||||||
| 
 | 
 | ||||||
| 	IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate); | 	IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate); | ||||||
| 	USE_FOR_NOMMU(const char *xformer_prog;) | 	USE_FOR_NOMMU(const char *xformer_prog;) | ||||||
|  | @ -223,6 +238,12 @@ typedef struct transformer_state_t { | ||||||
| 	uint64_t bytes_in;  /* used in unzip code only: needs to know packed size */ | 	uint64_t bytes_in;  /* used in unzip code only: needs to know packed size */ | ||||||
| 	uint32_t crc32; | 	uint32_t crc32; | ||||||
| 	time_t   mtime;     /* gunzip code may set this on exit */ | 	time_t   mtime;     /* gunzip code may set this on exit */ | ||||||
|  | 
 | ||||||
|  | 	union {             /* if we read magic, it's saved here */ | ||||||
|  | 		uint8_t b[8]; | ||||||
|  | 		uint16_t b16[4]; | ||||||
|  | 		uint32_t b32[2]; | ||||||
|  | 	} magic; | ||||||
| } transformer_state_t; | } transformer_state_t; | ||||||
| 
 | 
 | ||||||
| void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; | void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; | ||||||
|  | @ -278,11 +299,11 @@ int bbunpack(char **argv, | ||||||
| void check_errors_in_children(int signo); | void check_errors_in_children(int signo); | ||||||
| #if BB_MMU | #if BB_MMU | ||||||
| void fork_transformer(int fd, | void fork_transformer(int fd, | ||||||
| 	int check_signature, | 	int signature_skipped, | ||||||
| 	IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) | 	IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) | ||||||
| ) FAST_FUNC; | ) FAST_FUNC; | ||||||
| #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer)) | #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 0, (transformer)) | ||||||
| #define fork_transformer_with_no_sig(fd, transformer)              fork_transformer((fd), 0, (transformer)) | #define fork_transformer_with_no_sig(fd, transformer)              fork_transformer((fd), 1, (transformer)) | ||||||
| #else | #else | ||||||
| void fork_transformer(int fd, const char *transform_prog) FAST_FUNC; | void fork_transformer(int fd, const char *transform_prog) FAST_FUNC; | ||||||
| #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog)) | #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog)) | ||||||
|  |  | ||||||
|  | @ -65,7 +65,6 @@ int64_t bled_uncompress(const char* src, const char* dst, int type) | ||||||
| 	init_transformer_state(&xstate); | 	init_transformer_state(&xstate); | ||||||
| 	xstate.src_fd = -1; | 	xstate.src_fd = -1; | ||||||
| 	xstate.dst_fd = -1; | 	xstate.dst_fd = -1; | ||||||
| 	xstate.check_signature = 1; |  | ||||||
| 
 | 
 | ||||||
| 	xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0); | 	xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0); | ||||||
| 	if (xstate.src_fd < 0) { | 	if (xstate.src_fd < 0) { | ||||||
|  | @ -113,7 +112,6 @@ int64_t bled_uncompress_with_handles(HANDLE hSrc, HANDLE hDst, int type) | ||||||
| 	init_transformer_state(&xstate); | 	init_transformer_state(&xstate); | ||||||
| 	xstate.src_fd = -1; | 	xstate.src_fd = -1; | ||||||
| 	xstate.dst_fd = -1; | 	xstate.dst_fd = -1; | ||||||
| 	xstate.check_signature = 1; |  | ||||||
| 
 | 
 | ||||||
| 	xstate.src_fd = _open_osfhandle((intptr_t)hSrc, _O_RDONLY); | 	xstate.src_fd = _open_osfhandle((intptr_t)hSrc, _O_RDONLY); | ||||||
| 	if (xstate.src_fd < 0) { | 	if (xstate.src_fd < 0) { | ||||||
|  | @ -157,7 +155,6 @@ int64_t bled_uncompress_to_buffer(const char* src, char* buf, size_t size, int t | ||||||
| 	init_transformer_state(&xstate); | 	init_transformer_state(&xstate); | ||||||
| 	xstate.src_fd = -1; | 	xstate.src_fd = -1; | ||||||
| 	xstate.dst_fd = -1; | 	xstate.dst_fd = -1; | ||||||
| 	xstate.check_signature = 1; |  | ||||||
| 
 | 
 | ||||||
| 	if (src[0] == 0) { | 	if (src[0] == 0) { | ||||||
| 		xstate.src_fd = bb_virtual_fd; | 		xstate.src_fd = bb_virtual_fd; | ||||||
|  | @ -206,7 +203,6 @@ int64_t bled_uncompress_to_dir(const char* src, const char* dir, int type) | ||||||
| 	init_transformer_state(&xstate); | 	init_transformer_state(&xstate); | ||||||
| 	xstate.src_fd = -1; | 	xstate.src_fd = -1; | ||||||
| 	xstate.dst_fd = -1; | 	xstate.dst_fd = -1; | ||||||
| 	xstate.check_signature = 1; |  | ||||||
| 
 | 
 | ||||||
| 	xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0); | 	xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0); | ||||||
| 	if (xstate.src_fd < 0) { | 	if (xstate.src_fd < 0) { | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Licensed under GPLv2 or later, see file LICENSE in this source tree. |  * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||||||
|  */ |  */ | ||||||
| 
 |  | ||||||
| #include "libbb.h" | #include "libbb.h" | ||||||
| #include "bb_archive.h" | #include "bb_archive.h" | ||||||
| 
 | 
 | ||||||
|  | @ -11,6 +10,12 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | ||||||
| 	file_header_t *file_header = archive_handle->file_header; | 	file_header_t *file_header = archive_handle->file_header; | ||||||
| 	int dst_fd; | 	int dst_fd; | ||||||
| 	int res; | 	int res; | ||||||
|  | 	char *hard_link; | ||||||
|  | #if ENABLE_FEATURE_TAR_LONG_OPTIONS | ||||||
|  | 	char *dst_name; | ||||||
|  | #else | ||||||
|  | # define dst_name (file_header->name) | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #if ENABLE_FEATURE_TAR_SELINUX | #if ENABLE_FEATURE_TAR_SELINUX | ||||||
| 	char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE]; | 	char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE]; | ||||||
|  | @ -23,11 +28,49 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | ||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | 	/* Hard links are encoded as regular files of size 0
 | ||||||
|  | 	 * with a nonempty link field */ | ||||||
|  | 	hard_link = NULL; | ||||||
|  | 	if (S_ISREG(file_header->mode) && file_header->size == 0) | ||||||
|  | 		hard_link = file_header->link_target; | ||||||
|  | 
 | ||||||
|  | #if ENABLE_FEATURE_TAR_LONG_OPTIONS | ||||||
|  | 	dst_name = file_header->name; | ||||||
|  | 	if (archive_handle->tar__strip_components) { | ||||||
|  | 		unsigned n = archive_handle->tar__strip_components; | ||||||
|  | 		do { | ||||||
|  | 			dst_name = strchr(dst_name, '/'); | ||||||
|  | 			if (!dst_name || dst_name[1] == '\0') { | ||||||
|  | 				data_skip(archive_handle); | ||||||
|  | 				goto ret; | ||||||
|  | 			} | ||||||
|  | 			dst_name++; | ||||||
|  | 			/*
 | ||||||
|  | 			 * Link target is shortened only for hardlinks: | ||||||
|  | 			 * softlinks restored unchanged. | ||||||
|  | 			 */ | ||||||
|  | 			if (hard_link) { | ||||||
|  | // GNU tar 1.26 does not check that we reached end of link name:
 | ||||||
|  | // if "dir/hardlink" is hardlinked to "file",
 | ||||||
|  | // tar xvf a.tar --strip-components=1 says:
 | ||||||
|  | //  tar: hardlink: Cannot hard link to '': No such file or directory
 | ||||||
|  | // and continues processing. We silently skip such entries.
 | ||||||
|  | 				hard_link = strchr(hard_link, '/'); | ||||||
|  | 				if (!hard_link || hard_link[1] == '\0') { | ||||||
|  | 					data_skip(archive_handle); | ||||||
|  | 					goto ret; | ||||||
|  | 				} | ||||||
|  | 				hard_link++; | ||||||
|  | 			} | ||||||
|  | 		} while (--n != 0); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| 	if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { | 	if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { | ||||||
| 		char *slash = strrchr(file_header->name, '/'); | 		char *slash = strrchr(dst_name, '/'); | ||||||
| 		if (slash) { | 		if (slash) { | ||||||
| 			*slash = '\0'; | 			*slash = '\0'; | ||||||
| 			bb_make_directory(file_header->name, -1, FILEUTILS_RECUR); | 			bb_make_directory(dst_name, -1, FILEUTILS_RECUR); | ||||||
| 			*slash = '/'; | 			*slash = '/'; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -35,12 +78,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | ||||||
| 	if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) { | 	if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) { | ||||||
| 		/* Remove the entry if it exists */ | 		/* Remove the entry if it exists */ | ||||||
| 		if (!S_ISDIR(file_header->mode)) { | 		if (!S_ISDIR(file_header->mode)) { | ||||||
| 			/* Is it hardlink?
 | 			if (hard_link) { | ||||||
| 			 * We encode hard links as regular files of size 0 with a symlink */ |  | ||||||
| 			if (S_ISREG(file_header->mode) |  | ||||||
| 			 && file_header->link_target |  | ||||||
| 			 && file_header->size == 0 |  | ||||||
| 			) { |  | ||||||
| 				/* Ugly special case:
 | 				/* Ugly special case:
 | ||||||
| 				 * tar cf t.tar hardlink1 hardlink2 hardlink1 | 				 * tar cf t.tar hardlink1 hardlink2 hardlink1 | ||||||
| 				 * results in this tarball structure: | 				 * results in this tarball structure: | ||||||
|  | @ -48,56 +86,46 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | ||||||
| 				 * hardlink2 -> hardlink1 | 				 * hardlink2 -> hardlink1 | ||||||
| 				 * hardlink1 -> hardlink1 <== !!! | 				 * hardlink1 -> hardlink1 <== !!! | ||||||
| 				 */ | 				 */ | ||||||
| 				if (strcmp(file_header->link_target, file_header->name) == 0) | 				if (strcmp(hard_link, dst_name) == 0) | ||||||
| 					goto ret; | 					goto ret; | ||||||
| 			} | 			} | ||||||
| 			/* Proceed with deleting */ | 			/* Proceed with deleting */ | ||||||
| 			if (_unlink(file_header->name) == -1 | 			if (_unlink(dst_name) == -1 | ||||||
| 			 && errno != ENOENT | 			 && errno != ENOENT | ||||||
| 			) { | 			) { | ||||||
| 				bb_perror_msg_and_die("can't remove old file %s", | 				bb_perror_msg_and_die("can't remove old file %s", | ||||||
| 						file_header->name); | 						dst_name); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) { | 	else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) { | ||||||
| 		/* Remove the existing entry if its older than the extracted entry */ | 		/* Remove the existing entry if its older than the extracted entry */ | ||||||
| 		struct stat existing_sb; | 		struct stat existing_sb; | ||||||
| 		if (lstat(file_header->name, &existing_sb) == -1) { | 		if (lstat(dst_name, &existing_sb) == -1) { | ||||||
| 			if (errno != ENOENT) { | 			if (errno != ENOENT) { | ||||||
| 				bb_perror_msg_and_die("can't stat old file"); | 				bb_simple_perror_msg_and_die("can't stat old file"); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else if (existing_sb.st_mtime >= file_header->mtime) { | 		else if (existing_sb.st_mtime >= file_header->mtime) { | ||||||
| 			if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | 			if (!S_ISDIR(file_header->mode)) { | ||||||
| 			 && !S_ISDIR(file_header->mode) |  | ||||||
| 			) { |  | ||||||
| 				bb_error_msg("%s not created: newer or " | 				bb_error_msg("%s not created: newer or " | ||||||
| 					"same age file exists", file_header->name); | 					"same age file exists", dst_name); | ||||||
| 			} | 			} | ||||||
| 			data_skip(archive_handle); | 			data_skip(archive_handle); | ||||||
| 			goto ret; | 			goto ret; | ||||||
| 		} | 		} | ||||||
| 		else if ((_unlink(file_header->name) == -1) && (errno != EISDIR)) { | 		else if ((_unlink(dst_name) == -1) && (errno != EISDIR)) { | ||||||
| 			bb_perror_msg_and_die("can't remove old file %s", | 			bb_perror_msg_and_die("can't remove old file %s", | ||||||
| 					file_header->name); | 					dst_name); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Handle hard links separately
 | 	/* Handle hard links separately */ | ||||||
| 	 * We encode hard links as regular files of size 0 with a symlink */ | 	if (hard_link) { | ||||||
| 	if (S_ISREG(file_header->mode) | 		create_or_remember_link(&archive_handle->link_placeholders, | ||||||
| 	 && file_header->link_target | 				hard_link, | ||||||
| 	 && file_header->size == 0 | 				dst_name, | ||||||
| 	) { | 				1); | ||||||
| 		/* hard link */ |  | ||||||
| 		res = link(file_header->link_target, file_header->name); |  | ||||||
| 		if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { |  | ||||||
| 			bb_perror_msg("can't create %slink " |  | ||||||
| 					"from %s to %s", "hard", |  | ||||||
| 					file_header->name, |  | ||||||
| 					file_header->link_target); |  | ||||||
| 		} |  | ||||||
| 		/* Hardlinks have no separate mode/ownership, skip chown/chmod */ | 		/* Hardlinks have no separate mode/ownership, skip chown/chmod */ | ||||||
| 		goto ret; | 		goto ret; | ||||||
| 	} | 	} | ||||||
|  | @ -106,15 +134,17 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | ||||||
| 	switch (file_header->mode & S_IFMT) { | 	switch (file_header->mode & S_IFMT) { | ||||||
| 	case S_IFREG: { | 	case S_IFREG: { | ||||||
| 		/* Regular file */ | 		/* Regular file */ | ||||||
| 		char *dst_name; | #ifdef ARCHIVE_REPLACE_VIA_RENAME | ||||||
|  | 		char *dst_nameN; | ||||||
|  | #endif | ||||||
| 		int flags = O_WRONLY | O_CREAT | O_EXCL; | 		int flags = O_WRONLY | O_CREAT | O_EXCL; | ||||||
| 		if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) | 		if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) | ||||||
| 			flags = O_WRONLY | O_CREAT | O_TRUNC; | 			flags = O_WRONLY | O_CREAT | O_TRUNC; | ||||||
| 		dst_name = file_header->name; |  | ||||||
| #ifdef ARCHIVE_REPLACE_VIA_RENAME | #ifdef ARCHIVE_REPLACE_VIA_RENAME | ||||||
|  | 		dst_nameN = dst_name; | ||||||
| 		if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) | 		if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) | ||||||
| 			/* rpm-style temp file name */ | 			/* rpm-style temp file name */ | ||||||
| 			dst_name = xasprintf("%s;%x", dst_name, (int)getpid()); | 			dst_nameN = xasprintf("%s;%x", dst_name, (int)getpid()); | ||||||
| #endif | #endif | ||||||
| 		if (_sopen_s(&dst_fd, dst_name, flags, _SH_DENYNO, file_header->mode) != 0) { | 		if (_sopen_s(&dst_fd, dst_name, flags, _SH_DENYNO, file_header->mode) != 0) { | ||||||
| 			bb_perror_msg_and_die("can't open file %s", dst_name); | 			bb_perror_msg_and_die("can't open file %s", dst_name); | ||||||
|  | @ -123,48 +153,66 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | ||||||
| 		_close(dst_fd); | 		_close(dst_fd); | ||||||
| #ifdef ARCHIVE_REPLACE_VIA_RENAME | #ifdef ARCHIVE_REPLACE_VIA_RENAME | ||||||
| 		if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) { | 		if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) { | ||||||
| 			xrename(dst_name, file_header->name); | 			xrename(dst_nameN, dst_name); | ||||||
| 			free(dst_name); | 			free(dst_nameN); | ||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	case S_IFDIR: | 	case S_IFDIR: | ||||||
| 		res = mkdir(file_header->name, file_header->mode); | //TODO: this causes problems if tarball contains a r-xr-xr-x directory:
 | ||||||
| 		if ((res == -1) | // we create this directory, and then fail to create files inside it
 | ||||||
|  | // (if tar xf isn't run as root).
 | ||||||
|  | // GNU tar works around this by chmod-ing directories *after* all files are extracted.
 | ||||||
|  | 		res = mkdir(dst_name, file_header->mode); | ||||||
|  | 		if ((res != 0) | ||||||
| 		 && (errno != EISDIR) /* btw, Linux doesn't return this */ | 		 && (errno != EISDIR) /* btw, Linux doesn't return this */ | ||||||
| 		 && (errno != EEXIST) | 		 && (errno != EEXIST) | ||||||
| 		 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |  | ||||||
| 		) { | 		) { | ||||||
| 			bb_perror_msg("can't make dir %s", file_header->name); | 			bb_perror_msg("can't make dir %s", dst_name); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case S_IFLNK: | 	case S_IFLNK: | ||||||
| 		/* Symlink */ | 		/* Symlink */ | ||||||
| //TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
 | //TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
 | ||||||
| 		res = symlink(file_header->link_target, file_header->name); | 
 | ||||||
| 		if ((res == -1) | 		/* To avoid a directory traversal attack via symlinks,
 | ||||||
| 		 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | 		 * do not restore symlinks with ".." components | ||||||
| 		) { | 		 * or symlinks starting with "/", unless a magic | ||||||
| 			bb_perror_msg("can't create %slink " | 		 * envvar is set. | ||||||
| 				"from %s to %s", "sym", | 		 * | ||||||
| 				file_header->name, | 		 * For example, consider a .tar created via: | ||||||
| 				file_header->link_target); | 		 *  $ tar cvf bug.tar anything.txt | ||||||
| 		} | 		 *  $ ln -s /tmp symlink | ||||||
|  | 		 *  $ tar --append -f bug.tar symlink | ||||||
|  | 		 *  $ rm symlink | ||||||
|  | 		 *  $ mkdir symlink | ||||||
|  | 		 *  $ tar --append -f bug.tar symlink/evil.py | ||||||
|  | 		 * | ||||||
|  | 		 * This will result in an archive that contains: | ||||||
|  | 		 *  $ tar --list -f bug.tar | ||||||
|  | 		 *  anything.txt | ||||||
|  | 		 *  symlink [-> /tmp] | ||||||
|  | 		 *  symlink/evil.py | ||||||
|  | 		 * | ||||||
|  | 		 * Untarring bug.tar would otherwise place evil.py in '/tmp'. | ||||||
|  | 		 */ | ||||||
|  | 		create_or_remember_link(&archive_handle->link_placeholders, | ||||||
|  | 				file_header->link_target, | ||||||
|  | 				dst_name, | ||||||
|  | 				0); | ||||||
| 		break; | 		break; | ||||||
| 	case S_IFSOCK: | 	case S_IFSOCK: | ||||||
| 	case S_IFBLK: | 	case S_IFBLK: | ||||||
| 	case S_IFCHR: | 	case S_IFCHR: | ||||||
| 	case S_IFIFO: | 	case S_IFIFO: | ||||||
| 		res = mknod(file_header->name, file_header->mode, file_header->device); | 		res = mknod(dst_name, file_header->mode, file_header->device); | ||||||
| 		if ((res == -1) | 		if (res != 0) { | ||||||
| 		 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | 			bb_perror_msg("can't create node %s", dst_name); | ||||||
| 		) { |  | ||||||
| 			bb_perror_msg("can't create node %s", file_header->name); |  | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		bb_error_msg_and_die("unrecognized file type"); | 		bb_simple_error_msg_and_die("unrecognized file type"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!S_ISLNK(file_header->mode)) { | 	if (!S_ISLNK(file_header->mode)) { | ||||||
|  | @ -199,7 +247,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | ||||||
| 
 | 
 | ||||||
| 			t[1].tv_sec = t[0].tv_sec = file_header->mtime; | 			t[1].tv_sec = t[0].tv_sec = file_header->mtime; | ||||||
| 			t[1].tv_usec = t[0].tv_usec = 0; | 			t[1].tv_usec = t[0].tv_usec = 0; | ||||||
| 			utimes64(file_header->name, t); | 			utimes64(dst_name, t); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,14 +1,14 @@ | ||||||
| /* vi: set sw=4 ts=4: */ | /* vi: set sw=4 ts=4: */ | ||||||
| /* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
 | /*
 | ||||||
| 
 |  * Small bzip2 deflate implementation, by Rob Landley (rob@landley.net). | ||||||
|    Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), |  * | ||||||
|    which also acknowledges contributions by Mike Burrows, David Wheeler, |  * Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), | ||||||
|    Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, |  * which also acknowledges contributions by Mike Burrows, David Wheeler, | ||||||
|    Robert Sedgewick, and Jon L. Bentley. |  * Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, | ||||||
| 
 |  * Robert Sedgewick, and Jon L. Bentley. | ||||||
|    Licensed under GPLv2 or later, see file LICENSE in this source tree. |  * | ||||||
| */ |  * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||||||
| 
 |  */ | ||||||
| /*
 | /*
 | ||||||
| 	Size and speed optimizations by Manuel Novoa III  (mjn3@codepoet.org). | 	Size and speed optimizations by Manuel Novoa III  (mjn3@codepoet.org). | ||||||
| 
 | 
 | ||||||
|  | @ -38,7 +38,6 @@ | ||||||
| 
 | 
 | ||||||
| 	Manuel | 	Manuel | ||||||
|  */ |  */ | ||||||
| 
 |  | ||||||
| #include "libbb.h" | #include "libbb.h" | ||||||
| #include "bb_archive.h" | #include "bb_archive.h" | ||||||
| 
 | 
 | ||||||
|  | @ -101,14 +100,14 @@ struct bunzip_data { | ||||||
| 	unsigned dbufSize; | 	unsigned dbufSize; | ||||||
| 
 | 
 | ||||||
| 	/* For I/O error handling */ | 	/* For I/O error handling */ | ||||||
| 	jmp_buf jmpbuf; | 	jmp_buf *jmpbuf; | ||||||
| 
 | 
 | ||||||
| 	/* Big things go last (register-relative addressing can be larger for big offsets) */ | 	/* Big things go last (register-relative addressing can be larger for big offsets) */ | ||||||
| 	uint32_t crc32Table[256]; | 	uint32_t crc32Table[256]; | ||||||
| 	uint8_t selectors[32768];  /* nSelectors=15 bits */ | 	uint8_t selectors[32768];  /* nSelectors=15 bits */ | ||||||
| 	struct group_data groups[MAX_GROUPS];  /* Huffman coding tables */ | 	struct group_data groups[MAX_GROUPS];  /* Huffman coding tables */ | ||||||
| }; | }; | ||||||
| /* typedef struct bunzip_data bunzip_data; -- done in .h file */ | typedef struct bunzip_data bunzip_data; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return the next nnn bits of input.  All reads from the compressed input
 | /* Return the next nnn bits of input.  All reads from the compressed input
 | ||||||
|  | @ -128,14 +127,15 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted) | ||||||
| 			/* if "no input fd" case: in_fd == -1, read fails, we jump */ | 			/* if "no input fd" case: in_fd == -1, read fails, we jump */ | ||||||
| 			bd->inbufCount = safe_read(bd->in_fd, bd->inbuf, IOBUF_SIZE); | 			bd->inbufCount = safe_read(bd->in_fd, bd->inbuf, IOBUF_SIZE); | ||||||
| 			if (bd->inbufCount <= 0) | 			if (bd->inbufCount <= 0) | ||||||
| 				longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF); | 				longjmp(*bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF); | ||||||
| 			bd->inbufPos = 0; | 			bd->inbufPos = 0; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/* Avoid 32-bit overflow (dump bit buffer to top of output) */ | 		/* Avoid 32-bit overflow (dump bit buffer to top of output) */ | ||||||
| 		if (bit_count >= 24) { | 		if (bit_count >= 24) { | ||||||
| 			bits = bd->inbufBits & ((1 << bit_count) - 1); | 			bits = bd->inbufBits & ((1U << bit_count) - 1); | ||||||
| 			bits_wanted -= bit_count; | 			bits_wanted -= bit_count; | ||||||
|  | 			// coverity[negative_shift]
 | ||||||
| 			bits <<= bits_wanted; | 			bits <<= bits_wanted; | ||||||
| 			bit_count = 0; | 			bit_count = 0; | ||||||
| 		} | 		} | ||||||
|  | @ -152,20 +152,20 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted) | ||||||
| 
 | 
 | ||||||
| 	return bits; | 	return bits; | ||||||
| } | } | ||||||
|  | //#define get_bits(bd, n) (dbg("%d:get_bits()", __LINE__), get_bits(bd, n))
 | ||||||
| 
 | 
 | ||||||
| /* Unpacks the next block and sets up for the inverse Burrows-Wheeler step. */ | /* Unpacks the next block and sets up for the inverse Burrows-Wheeler step. */ | ||||||
| static int get_next_block(bunzip_data *bd) | static int get_next_block(bunzip_data *bd) | ||||||
| { | { | ||||||
| 	struct group_data *hufGroup; | 	int groupCount, selector, | ||||||
| 	int dbufCount, dbufSize, groupCount, *base, *limit, selector, | 		i, j, symCount, symTotal, nSelectors, byteCount[256]; | ||||||
| 		i, j, t, runPos, symCount, symTotal, nSelectors, byteCount[256]; |  | ||||||
| 	int runCnt; |  | ||||||
| 	uint8_t uc, symToByte[256], mtfSymbol[256], *selectors; | 	uint8_t uc, symToByte[256], mtfSymbol[256], *selectors; | ||||||
| 	uint32_t *dbuf; | 	uint32_t *dbuf; | ||||||
| 	unsigned origPtr; | 	unsigned origPtr, t; | ||||||
|  | 	unsigned dbufCount, runPos; | ||||||
|  | 	unsigned runCnt = 0; // runCnt; /* for compiler */
 | ||||||
| 
 | 
 | ||||||
| 	dbuf = bd->dbuf; | 	dbuf = bd->dbuf; | ||||||
| 	dbufSize = bd->dbufSize; |  | ||||||
| 	selectors = bd->selectors; | 	selectors = bd->selectors; | ||||||
| 
 | 
 | ||||||
| /* In bbox, we are ok with aborting through setjmp which is set up in start_bunzip */ | /* In bbox, we are ok with aborting through setjmp which is set up in start_bunzip */ | ||||||
|  | @ -180,15 +180,19 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 	i = get_bits(bd, 24); | 	i = get_bits(bd, 24); | ||||||
| 	j = get_bits(bd, 24); | 	j = get_bits(bd, 24); | ||||||
| 	bd->headerCRC = get_bits(bd, 32); | 	bd->headerCRC = get_bits(bd, 32); | ||||||
| 	if ((i == 0x177245) && (j == 0x385090)) return RETVAL_LAST_BLOCK; | 	if ((i == 0x177245) && (j == 0x385090)) | ||||||
| 	if ((i != 0x314159) || (j != 0x265359)) return RETVAL_NOT_BZIP_DATA; | 		return RETVAL_LAST_BLOCK; | ||||||
|  | 	if ((i != 0x314159) || (j != 0x265359)) | ||||||
|  | 		return RETVAL_NOT_BZIP_DATA; | ||||||
| 
 | 
 | ||||||
| 	/* We can add support for blockRandomised if anybody complains.  There was
 | 	/* We can add support for blockRandomised if anybody complains.  There was
 | ||||||
| 	   some code for this in busybox 1.0.0-pre3, but nobody ever noticed that | 	   some code for this in busybox 1.0.0-pre3, but nobody ever noticed that | ||||||
| 	   it didn't actually work. */ | 	   it didn't actually work. */ | ||||||
| 	if (get_bits(bd, 1)) return RETVAL_OBSOLETE_INPUT; | 	if (get_bits(bd, 1)) | ||||||
|  | 		return RETVAL_OBSOLETE_INPUT; | ||||||
| 	origPtr = get_bits(bd, 24); | 	origPtr = get_bits(bd, 24); | ||||||
| 	if ((int)origPtr > dbufSize) return RETVAL_DATA_ERROR; | 	if (origPtr > bd->dbufSize) | ||||||
|  | 		return RETVAL_DATA_ERROR; | ||||||
| 
 | 
 | ||||||
| 	/* mapping table: if some byte values are never used (encoding things
 | 	/* mapping table: if some byte values are never used (encoding things
 | ||||||
| 	   like ascii text), the compression code removes the gaps to have fewer | 	   like ascii text), the compression code removes the gaps to have fewer | ||||||
|  | @ -232,8 +236,9 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 		/* Get next value */ | 		/* Get next value */ | ||||||
| 		int n = 0; | 		int n = 0; | ||||||
| 		while (get_bits(bd, 1)) { | 		while (get_bits(bd, 1)) { | ||||||
| 			if (n >= groupCount) return RETVAL_DATA_ERROR; |  | ||||||
| 			n++; | 			n++; | ||||||
|  | 			if (n >= groupCount) | ||||||
|  | 				return RETVAL_DATA_ERROR; | ||||||
| 		} | 		} | ||||||
| 		/* Decode MTF to get the next selector */ | 		/* Decode MTF to get the next selector */ | ||||||
| 		tmp_byte = mtfSymbol[n]; | 		tmp_byte = mtfSymbol[n]; | ||||||
|  | @ -249,6 +254,8 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 		uint8_t length[MAX_SYMBOLS]; | 		uint8_t length[MAX_SYMBOLS]; | ||||||
| 		/* 8 bits is ALMOST enough for temp[], see below */ | 		/* 8 bits is ALMOST enough for temp[], see below */ | ||||||
| 		unsigned temp[MAX_HUFCODE_BITS+1]; | 		unsigned temp[MAX_HUFCODE_BITS+1]; | ||||||
|  | 		struct group_data *hufGroup; | ||||||
|  | 		int *base, *limit; | ||||||
| 		int minLen, maxLen, pp, len_m1; | 		int minLen, maxLen, pp, len_m1; | ||||||
| 
 | 
 | ||||||
| 		/* Read Huffman code lengths for each symbol.  They're stored in
 | 		/* Read Huffman code lengths for each symbol.  They're stored in
 | ||||||
|  | @ -284,8 +291,10 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 		/* Find largest and smallest lengths in this group */ | 		/* Find largest and smallest lengths in this group */ | ||||||
| 		minLen = maxLen = length[0]; | 		minLen = maxLen = length[0]; | ||||||
| 		for (i = 1; i < symCount; i++) { | 		for (i = 1; i < symCount; i++) { | ||||||
| 			if (length[i] > maxLen) maxLen = length[i]; | 			if (length[i] > maxLen) | ||||||
| 			else if (length[i] < minLen) minLen = length[i]; | 				maxLen = length[i]; | ||||||
|  | 			else if (length[i] < minLen) | ||||||
|  | 				minLen = length[i]; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/* Calculate permute[], base[], and limit[] tables from length[].
 | 		/* Calculate permute[], base[], and limit[] tables from length[].
 | ||||||
|  | @ -308,7 +317,7 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 		base = hufGroup->base - 1; | 		base = hufGroup->base - 1; | ||||||
| 		limit = hufGroup->limit - 1; | 		limit = hufGroup->limit - 1; | ||||||
| 
 | 
 | ||||||
| 		/* Calculate permute[].  Concurently, initialize temp[] and limit[]. */ | 		/* Calculate permute[].  Concurrently, initialize temp[] and limit[]. */ | ||||||
| 		pp = 0; | 		pp = 0; | ||||||
| 		for (i = minLen; i <= maxLen; i++) { | 		for (i = minLen; i <= maxLen; i++) { | ||||||
| 			int k; | 			int k; | ||||||
|  | @ -321,7 +330,8 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 		/* Count symbols coded for at each bit length */ | 		/* Count symbols coded for at each bit length */ | ||||||
| 		/* NB: in pathological cases, temp[8] can end ip being 256.
 | 		/* NB: in pathological cases, temp[8] can end ip being 256.
 | ||||||
| 		 * That's why uint8_t is too small for temp[]. */ | 		 * That's why uint8_t is too small for temp[]. */ | ||||||
| 		for (i = 0; i < symCount; i++) temp[length[i]]++; | 		for (i = 0; i < symCount; i++) | ||||||
|  | 			temp[length[i]]++; | ||||||
| 
 | 
 | ||||||
| 		/* Calculate limit[] (the largest symbol-coding value at each bit
 | 		/* Calculate limit[] (the largest symbol-coding value at each bit
 | ||||||
| 		 * length, which is (previous limit<<1)+symbols at this level), and | 		 * length, which is (previous limit<<1)+symbols at this level), and | ||||||
|  | @ -364,12 +374,22 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 
 | 
 | ||||||
| 	runPos = dbufCount = selector = 0; | 	runPos = dbufCount = selector = 0; | ||||||
| 	for (;;) { | 	for (;;) { | ||||||
|  | 		struct group_data *hufGroup; | ||||||
|  | 		int *base, *limit; | ||||||
| 		int nextSym; | 		int nextSym; | ||||||
|  | 		uint8_t ngrp; | ||||||
| 
 | 
 | ||||||
| 		/* Fetch next Huffman coding group from list. */ | 		/* Fetch next Huffman coding group from list. */ | ||||||
| 		symCount = GROUP_SIZE - 1; | 		symCount = GROUP_SIZE - 1; | ||||||
| 		if (selector >= nSelectors) return RETVAL_DATA_ERROR; | 		if (selector >= nSelectors) | ||||||
| 		hufGroup = bd->groups + selectors[selector++]; | 			return RETVAL_DATA_ERROR; | ||||||
|  | 		ngrp = selectors[selector++]; | ||||||
|  | 		if (ngrp >= groupCount) { | ||||||
|  | 			dbg("%d selectors[%d]:%d groupCount:%d", | ||||||
|  | 				__LINE__, selector-1, ngrp, groupCount); | ||||||
|  | 			return RETVAL_DATA_ERROR; | ||||||
|  | 		} | ||||||
|  | 		hufGroup = bd->groups + ngrp; | ||||||
| 		base = hufGroup->base - 1; | 		base = hufGroup->base - 1; | ||||||
| 		limit = hufGroup->limit - 1; | 		limit = hufGroup->limit - 1; | ||||||
| 
 | 
 | ||||||
|  | @ -404,7 +424,8 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 		} | 		} | ||||||
| 		/* Figure how many bits are in next symbol and unget extras */ | 		/* Figure how many bits are in next symbol and unget extras */ | ||||||
| 		i = hufGroup->minLen; | 		i = hufGroup->minLen; | ||||||
| 		while (nextSym > limit[i]) ++i; | 		while (nextSym > limit[i]) | ||||||
|  | 			++i; | ||||||
| 		j = hufGroup->maxLen - i; | 		j = hufGroup->maxLen - i; | ||||||
| 		if (j < 0) | 		if (j < 0) | ||||||
| 			return RETVAL_DATA_ERROR; | 			return RETVAL_DATA_ERROR; | ||||||
|  | @ -436,7 +457,7 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 			   symbols, but a run of length 0 doesn't mean anything in this | 			   symbols, but a run of length 0 doesn't mean anything in this | ||||||
| 			   context).  Thus space is saved. */ | 			   context).  Thus space is saved. */ | ||||||
| 			runCnt += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */ | 			runCnt += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */ | ||||||
| 			if (runPos < dbufSize) runPos <<= 1; | 			if (runPos < bd->dbufSize) runPos <<= 1; | ||||||
| 			goto end_of_huffman_loop; | 			goto end_of_huffman_loop; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -446,14 +467,15 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 		   literal used is the one at the head of the mtfSymbol array.) */ | 		   literal used is the one at the head of the mtfSymbol array.) */ | ||||||
| 		if (runPos != 0) { | 		if (runPos != 0) { | ||||||
| 			uint8_t tmp_byte; | 			uint8_t tmp_byte; | ||||||
| 			if (dbufCount + runCnt > dbufSize) { | 			if (dbufCount + runCnt > bd->dbufSize) { | ||||||
| 				dbg("dbufCount:%d+runCnt:%d %d > dbufSize:%d RETVAL_DATA_ERROR", | 				dbg("dbufCount:%u+runCnt:%u %u > dbufSize:%u RETVAL_DATA_ERROR", | ||||||
| 						dbufCount, runCnt, dbufCount + runCnt, dbufSize); | 						dbufCount, runCnt, dbufCount + runCnt, bd->dbufSize); | ||||||
| 				return RETVAL_DATA_ERROR; | 				return RETVAL_DATA_ERROR; | ||||||
| 			} | 			} | ||||||
| 			tmp_byte = symToByte[mtfSymbol[0]]; | 			tmp_byte = symToByte[mtfSymbol[0]]; | ||||||
| 			byteCount[tmp_byte] += runCnt; | 			byteCount[tmp_byte] += runCnt; | ||||||
| 			while (--runCnt >= 0) dbuf[dbufCount++] = (uint32_t)tmp_byte; | 			while ((int)--runCnt >= 0) | ||||||
|  | 				dbuf[dbufCount++] = (uint32_t)tmp_byte; | ||||||
| 			runPos = 0; | 			runPos = 0; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -467,7 +489,7 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 		   first symbol in the mtf array, position 0, would have been handled | 		   first symbol in the mtf array, position 0, would have been handled | ||||||
| 		   as part of a run above.  Therefore 1 unused mtf position minus | 		   as part of a run above.  Therefore 1 unused mtf position minus | ||||||
| 		   2 non-literal nextSym values equals -1.) */ | 		   2 non-literal nextSym values equals -1.) */ | ||||||
| 		if (dbufCount >= dbufSize) return RETVAL_DATA_ERROR; | 		if (dbufCount >= bd->dbufSize) return RETVAL_DATA_ERROR; | ||||||
| 		i = nextSym - 1; | 		i = nextSym - 1; | ||||||
| 		uc = mtfSymbol[i]; | 		uc = mtfSymbol[i]; | ||||||
| 
 | 
 | ||||||
|  | @ -507,7 +529,7 @@ static int get_next_block(bunzip_data *bd) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Figure out what order dbuf would be in if we sorted it. */ | 	/* Figure out what order dbuf would be in if we sorted it. */ | ||||||
| 	for (i = 0; i < dbufCount; i++) { | 	for (i = 0; i < (int)dbufCount; i++) { | ||||||
| 		uint8_t tmp_byte = (uint8_t)dbuf[i]; | 		uint8_t tmp_byte = (uint8_t)dbuf[i]; | ||||||
| 		int tmp_count = byteCount[tmp_byte]; | 		int tmp_count = byteCount[tmp_byte]; | ||||||
| 		dbuf[tmp_count] |= (i << 8); | 		dbuf[tmp_count] |= (i << 8); | ||||||
|  | @ -540,7 +562,7 @@ static int get_next_block(bunzip_data *bd) | ||||||
|    in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. |    in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. | ||||||
|    (Why? This allows to get rid of one local variable) |    (Why? This allows to get rid of one local variable) | ||||||
| */ | */ | ||||||
| int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | static int read_bunzip(bunzip_data *bd, char *outbuf, int len) | ||||||
| { | { | ||||||
| 	const uint32_t *dbuf; | 	const uint32_t *dbuf; | ||||||
| 	int pos, current, previous; | 	int pos, current, previous; | ||||||
|  | @ -619,7 +641,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | ||||||
| 				/* Subtract the 1 copy we'd output anyway to get extras */ | 				/* Subtract the 1 copy we'd output anyway to get extras */ | ||||||
| 				--bd->writeCopies; | 				--bd->writeCopies; | ||||||
| 			} | 			} | ||||||
| 		} /* for(;;) */ | 		} /* for (;;) */ | ||||||
| 
 | 
 | ||||||
| 		/* Decompression of this input block completed successfully */ | 		/* Decompression of this input block completed successfully */ | ||||||
| 		bd->writeCRC = CRC = ~CRC; | 		bd->writeCRC = CRC = ~CRC; | ||||||
|  | @ -664,7 +686,10 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | ||||||
| /* Because bunzip2 is used for help text unpacking, and because bb_show_usage()
 | /* Because bunzip2 is used for help text unpacking, and because bb_show_usage()
 | ||||||
|    should work for NOFORK applets too, we must be extremely careful to not leak |    should work for NOFORK applets too, we must be extremely careful to not leak | ||||||
|    any allocations! */ |    any allocations! */ | ||||||
| int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, | static int FAST_FUNC start_bunzip( | ||||||
|  | 		void *jmpbuf, | ||||||
|  | 		bunzip_data **bdp, | ||||||
|  | 		int in_fd, | ||||||
| 		const void *inbuf, int len) | 		const void *inbuf, int len) | ||||||
| { | { | ||||||
| 	bunzip_data *bd; | 	bunzip_data *bd; | ||||||
|  | @ -676,13 +701,16 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, | ||||||
| 
 | 
 | ||||||
| 	/* Figure out how much data to allocate */ | 	/* Figure out how much data to allocate */ | ||||||
| 	i = sizeof(bunzip_data); | 	i = sizeof(bunzip_data); | ||||||
| 	if (in_fd != -1) i += IOBUF_SIZE; | 	if (in_fd != -1) | ||||||
|  | 		i += IOBUF_SIZE; | ||||||
| 
 | 
 | ||||||
| 	/* Allocate bunzip_data.  Most fields initialize to zero. */ | 	/* Allocate bunzip_data.  Most fields initialize to zero. */ | ||||||
| 	bd = *bdp = xzalloc(i); | 	bd = *bdp = xzalloc(i); | ||||||
| 	if (bd == NULL) | 	if (bd == NULL) | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
|  | 	bd->jmpbuf = jmpbuf; | ||||||
|  | 
 | ||||||
| 	/* Setup input buffer */ | 	/* Setup input buffer */ | ||||||
| 	bd->in_fd = in_fd; | 	bd->in_fd = in_fd; | ||||||
| 	if (-1 == in_fd) { | 	if (-1 == in_fd) { | ||||||
|  | @ -697,10 +725,6 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, | ||||||
| 	/* Init the CRC32 table (big endian) */ | 	/* Init the CRC32 table (big endian) */ | ||||||
| 	crc32_filltable(bd->crc32Table, 1); | 	crc32_filltable(bd->crc32Table, 1); | ||||||
| 
 | 
 | ||||||
| 	/* Setup for I/O error handling via longjmp */ |  | ||||||
| 	i = setjmp(bd->jmpbuf); |  | ||||||
| 	if (i) return i; |  | ||||||
| 
 |  | ||||||
| 	/* Ensure that file starts with "BZh['1'-'9']." */ | 	/* Ensure that file starts with "BZh['1'-'9']." */ | ||||||
| 	/* Update: now caller verifies 1st two bytes, makes .gz/.bz2
 | 	/* Update: now caller verifies 1st two bytes, makes .gz/.bz2
 | ||||||
| 	 * integration easier */ | 	 * integration easier */ | ||||||
|  | @ -724,7 +748,7 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, | ||||||
| 	return RETVAL_OK; | 	return RETVAL_OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FAST_FUNC dealloc_bunzip(bunzip_data *bd) | static void FAST_FUNC dealloc_bunzip(bunzip_data *bd) | ||||||
| { | { | ||||||
| 	free(bd->dbuf); | 	free(bd->dbuf); | ||||||
| 	free(bd); | 	free(bd); | ||||||
|  | @ -749,8 +773,12 @@ unpack_bz2_stream(transformer_state_t *xstate) | ||||||
| 		return -1; | 		return -1; | ||||||
| 	len = 0; | 	len = 0; | ||||||
| 	while (1) { /* "Process one BZ... stream" loop */ | 	while (1) { /* "Process one BZ... stream" loop */ | ||||||
|  | 		jmp_buf jmpbuf; | ||||||
| 
 | 
 | ||||||
| 		i = start_bunzip(&bd, xstate->src_fd, outbuf + 2, len); | 		/* Setup for I/O error handling via longjmp */ | ||||||
|  | 		i = setjmp(jmpbuf); | ||||||
|  | 		if (i == 0) | ||||||
|  | 			i = start_bunzip(&jmpbuf, &bd, xstate->src_fd, outbuf + 2, len); | ||||||
| 
 | 
 | ||||||
| 		if (i == 0) { | 		if (i == 0) { | ||||||
| 			while (1) { /* "Produce some output bytes" loop */ | 			while (1) { /* "Produce some output bytes" loop */ | ||||||
|  | @ -781,7 +809,7 @@ unpack_bz2_stream(transformer_state_t *xstate) | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		if (bd->headerCRC != bd->totalCRC) { | 		if (bd->headerCRC != bd->totalCRC) { | ||||||
| 			bb_error_msg("CRC error"); | 			bb_simple_error_msg("CRC error"); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -811,6 +839,36 @@ unpack_bz2_stream(transformer_state_t *xstate) | ||||||
| 	return i ? i : IF_DESKTOP(total_written) + 0; | 	return i ? i : IF_DESKTOP(total_written) + 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | char* FAST_FUNC | ||||||
|  | unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) | ||||||
|  | { | ||||||
|  | 	char *outbuf = NULL; | ||||||
|  | 	bunzip_data *bd; | ||||||
|  | 	int i; | ||||||
|  | 	jmp_buf jmpbuf; | ||||||
|  | 
 | ||||||
|  | 	/* Setup for I/O error handling via longjmp */ | ||||||
|  | 	i = setjmp(jmpbuf); | ||||||
|  | 	if (i == 0) { | ||||||
|  | 		i = start_bunzip(&jmpbuf, | ||||||
|  | 			&bd, | ||||||
|  | 			/* src_fd: */ -1, | ||||||
|  | 			/* inbuf:  */ packed, | ||||||
|  | 			/* len:    */ packed_len | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 	/* read_bunzip can longjmp and end up here with i != 0
 | ||||||
|  | 	 * on read data errors! Not trivial */ | ||||||
|  | 	if (i == 0) { | ||||||
|  | 		/* Cannot use xmalloc: will leak bd in NOFORK case! */ | ||||||
|  | 		outbuf = malloc_or_warn(unpacked_len); | ||||||
|  | 		if (outbuf) | ||||||
|  | 			read_bunzip(bd, outbuf, unpacked_len); | ||||||
|  | 	} | ||||||
|  | 	dealloc_bunzip(bd); | ||||||
|  | 	return outbuf; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #ifdef TESTING | #ifdef TESTING | ||||||
| 
 | 
 | ||||||
| static char *const bunzip_errors[] = { | static char *const bunzip_errors[] = { | ||||||
|  |  | ||||||
|  | @ -32,8 +32,6 @@ | ||||||
|  * |  * | ||||||
|  * Licensed under GPLv2 or later, see file LICENSE in this source tree. |  * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||||||
|  */ |  */ | ||||||
| 
 |  | ||||||
| #include <setjmp.h> |  | ||||||
| #include "libbb.h" | #include "libbb.h" | ||||||
| #include "bb_archive.h" | #include "bb_archive.h" | ||||||
| 
 | 
 | ||||||
|  | @ -41,7 +39,8 @@ typedef struct huft_t { | ||||||
| 	unsigned char e;	/* number of extra bits or operation */ | 	unsigned char e;	/* number of extra bits or operation */ | ||||||
| 	unsigned char b;	/* number of bits in this code or subcode */ | 	unsigned char b;	/* number of bits in this code or subcode */ | ||||||
| 	union { | 	union { | ||||||
| 		unsigned short n;	/* literal, length base, or distance base */ | 		unsigned n;	/* literal, length base, or distance base */ | ||||||
|  | 		/* ^^^^^ was "unsigned short", but that results in larger code */ | ||||||
| 		struct huft_t *t;	/* pointer to next level of table */ | 		struct huft_t *t;	/* pointer to next level of table */ | ||||||
| 	} v; | 	} v; | ||||||
| } huft_t; | } huft_t; | ||||||
|  | @ -128,6 +127,8 @@ typedef struct state_t { | ||||||
| #define gunzip_bb           (S()gunzip_bb          ) | #define gunzip_bb           (S()gunzip_bb          ) | ||||||
| #define gunzip_bk           (S()gunzip_bk          ) | #define gunzip_bk           (S()gunzip_bk          ) | ||||||
| #define to_read             (S()to_read            ) | #define to_read             (S()to_read            ) | ||||||
|  | // #define bytebuffer_max   (S()bytebuffer_max     )
 | ||||||
|  | // Both gunzip and unzip can use constant buffer size now (16k):
 | ||||||
| #define bytebuffer_max      BB_BUFSIZE | #define bytebuffer_max      BB_BUFSIZE | ||||||
| #define bytebuffer          (S()bytebuffer         ) | #define bytebuffer          (S()bytebuffer         ) | ||||||
| #define bytebuffer_offset   (S()bytebuffer_offset  ) | #define bytebuffer_offset   (S()bytebuffer_offset  ) | ||||||
|  | @ -184,29 +185,26 @@ static const uint16_t mask_bits[] ALIGN2 = { | ||||||
| 	0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff | 	0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Copy lengths for literal codes 257..285 */ | /* Put lengths/offsets and extra bits in a struct of arrays
 | ||||||
| static const uint16_t cplens[] ALIGN2 = { |  * to make calls to huft_build() have one fewer parameter. | ||||||
| 	3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, |  */ | ||||||
| 	67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 | struct cp_ext { | ||||||
|  | 	uint16_t cp[31]; | ||||||
|  | 	uint8_t ext[31]; | ||||||
| }; | }; | ||||||
| 
 | /* Copy lengths and extra bits for literal codes 257..285 */ | ||||||
| /* note: see note #13 above about the 258 in this list. */ | /* note: see note #13 above about the 258 in this list. */ | ||||||
| /* Extra bits for literal codes 257..285 */ | static const struct cp_ext lit ALIGN2 = { | ||||||
| static const uint8_t cplext[] ALIGN1 = { | 	/*257 258 259 260 261 262 263 264 265 266 267 268 269 270 271  272  273  274  275  276   277   278   279   280   281   282   283    284    285 */ | ||||||
| 	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, | 	/*0   1   2   3   4   5   6   7   8   9   10  11  12  13   14   15   16   17   18   19    20    21    22    23    24    25    26     27     28     29  30 */ | ||||||
| 	5, 5, 5, 0, 99, 99 | 	{ 3,  4,  5,  6,  7,  8,  9,  10, 11, 13, 15, 17, 19, 23,  27,  31,  35,  43,  51,  59,   67,   83,   99,  115,  131,  163,  195,   227,   258,     0, 0  }, | ||||||
| }; /* 99 == invalid */ | 	{ 0,  0,  0,  0,  0,  0,  0,   0,  1,  1,  1,  1,  2,  2,   2,   2,   3,   3,   3,   3,    4,    4,    4,    4,    5,    5,    5,     5,     0,    99, 99 } /* 99 == invalid */ | ||||||
| 
 |  | ||||||
| /* Copy offsets for distance codes 0..29 */ |  | ||||||
| static const uint16_t cpdist[] ALIGN2 = { |  | ||||||
| 	1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, |  | ||||||
| 	769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 |  | ||||||
| }; | }; | ||||||
| 
 | /* Copy offsets and extra bits for distance codes 0..29 */ | ||||||
| /* Extra bits for distance codes */ | static const struct cp_ext dist ALIGN2 = { | ||||||
| static const uint8_t cpdext[] ALIGN1 = { | 	/*0   1   2   3   4   5   6   7   8   9   10  11  12  13   14   15   16   17   18   19    20    21    22    23    24    25    26     27     28     29 */ | ||||||
| 	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, | 	{ 1,  2,  3,  4,  5,  7,  9,  13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }, | ||||||
| 	11, 11, 12, 12, 13, 13 | 	{ 0,  0,  0,  0,  1,  1,  2,   2,  3,  3,  4,  4,  5,  5,   6,   6,   7,   7,   8,   8,    9,    9,   10,   10,   11,   11,   12,    12,    13,    13 } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Tables for deflate from PKZIP's appnote.txt. */ | /* Tables for deflate from PKZIP's appnote.txt. */ | ||||||
|  | @ -222,10 +220,19 @@ static const uint8_t border[] ALIGN1 = { | ||||||
|  * each table. |  * each table. | ||||||
|  * t: table to free |  * t: table to free | ||||||
|  */ |  */ | ||||||
|  | #define BAD_HUFT(p) ((uintptr_t)(p) & 1) | ||||||
|  | #define ERR_RET     ((huft_t*)(uintptr_t)1) | ||||||
| static void huft_free(huft_t *p) | static void huft_free(huft_t *p) | ||||||
| { | { | ||||||
| 	huft_t *q; | 	huft_t *q; | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * If 'p' has the error bit set we have to clear it, otherwise we might run | ||||||
|  | 	 * into a segmentation fault or an invalid pointer to free(p) | ||||||
|  | 	 */ | ||||||
|  | 	//if (BAD_HUFT(p)) // commented out, since bit clearing has effect only if condition is true
 | ||||||
|  | 		p = (huft_t*)((uintptr_t)p & ~(uintptr_t)ERR_RET); | ||||||
|  | 
 | ||||||
| 	/* Go through linked list, freeing from the malloced (t[-1]) address. */ | 	/* Go through linked list, freeing from the malloced (t[-1]) address. */ | ||||||
| 	while (p) { | 	while (p) { | ||||||
| 		q = (--p)->v.t; | 		q = (--p)->v.t; | ||||||
|  | @ -277,22 +284,23 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Given a list of code lengths and a maximum table size, make a set of
 | /* Given a list of code lengths and a maximum table size, make a set of
 | ||||||
|  * tables to decode that set of codes.  Return zero on success, one if |  * tables to decode that set of codes. | ||||||
|  * the given code set is incomplete (the tables are still built in this |  | ||||||
|  * case), two if the input is invalid (all zero length codes or an |  | ||||||
|  * oversubscribed set of lengths) - in this case stores NULL in *t. |  | ||||||
|  * |  * | ||||||
|  * b:	code lengths in bits (all assumed <= BMAX) |  * b:	code lengths in bits (all assumed <= BMAX) | ||||||
|  * n:	number of codes (assumed <= N_MAX) |  * n:	number of codes (assumed <= N_MAX) | ||||||
|  * s:	number of simple-valued codes (0..s-1) |  * s:	number of simple-valued codes (0..s-1) | ||||||
|  * d:	list of base values for non-simple codes |  * cp_ext->cp,ext: list of base values/extra bits for non-simple codes | ||||||
|  * e:	list of extra bits for non-simple codes |  | ||||||
|  * t:	result: starting table |  | ||||||
|  * m:	maximum lookup bits, returns actual |  * m:	maximum lookup bits, returns actual | ||||||
|  |  * result: starting table | ||||||
|  |  * | ||||||
|  |  * On error, returns a value with lowest-bit set on error. | ||||||
|  |  * It can be just the value of 0x1, | ||||||
|  |  * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table | ||||||
|  |  * is given: "fixed inflate" decoder feeds us such data. | ||||||
|  */ |  */ | ||||||
| static int huft_build(const unsigned *b, const unsigned n, | static huft_t* huft_build(const unsigned *b, const unsigned n, | ||||||
| 			const unsigned s, const unsigned short *d, | 			const unsigned s, const struct cp_ext *cp_ext, | ||||||
| 			const unsigned char *e, huft_t **t, unsigned *m) | 			unsigned *m) | ||||||
| { | { | ||||||
| 	unsigned a;             /* counter for codes of length k */ | 	unsigned a;             /* counter for codes of length k */ | ||||||
| 	unsigned c[BMAX + 1];   /* bit length count table */ | 	unsigned c[BMAX + 1];   /* bit length count table */ | ||||||
|  | @ -303,34 +311,42 @@ static int huft_build(const unsigned *b, const unsigned n, | ||||||
| 	unsigned i;             /* counter, current code */ | 	unsigned i;             /* counter, current code */ | ||||||
| 	unsigned j;             /* counter */ | 	unsigned j;             /* counter */ | ||||||
| 	int k;                  /* number of bits in current code */ | 	int k;                  /* number of bits in current code */ | ||||||
| 	unsigned *p;            /* pointer into c[], b[], or v[] */ | 	const unsigned *p;      /* pointer into c[], b[], or v[] */ | ||||||
| 	huft_t *q;              /* points to current table */ | 	huft_t *q;              /* points to current table */ | ||||||
| 	huft_t r;               /* table entry for structure assignment */ | 	huft_t r;               /* table entry for structure assignment */ | ||||||
| 	huft_t *u[BMAX];        /* table stack */ | 	huft_t *u[BMAX];        /* table stack */ | ||||||
| 	unsigned v[N_MAX];      /* values in order of bit length */ | 	unsigned v[N_MAX + 1];  /* values in order of bit length. last v[] is never used */ | ||||||
| 	int ws[BMAX + 1];       /* bits decoded stack */ | 	int ws[BMAX + 1];       /* bits decoded stack */ | ||||||
| 	int w;                  /* bits decoded */ | 	int w;                  /* bits decoded */ | ||||||
| 	unsigned x[BMAX + 1];   /* bit offsets, then code stack */ | 	unsigned x[BMAX + 1];   /* bit offsets, then code stack */ | ||||||
| 	unsigned *xp;           /* pointer into x */ | 	unsigned *xp;           /* pointer into x */ | ||||||
| 	int y;                  /* number of dummy codes added */ | 	int y;                  /* number of dummy codes added */ | ||||||
| 	unsigned z;             /* number of entries in current table */ | 	unsigned z;             /* number of entries in current table */ | ||||||
|  | 	huft_t *result; | ||||||
|  | 	huft_t **t; | ||||||
| 
 | 
 | ||||||
| 	/* Length of EOB code, if any */ | 	/* Length of EOB code, if any */ | ||||||
| 	eob_len = n > 256 ? b[256] : BMAX; | 	eob_len = n > 256 ? b[256] : BMAX; | ||||||
| 
 | 
 | ||||||
| 	*t = NULL; | 	memset(&r, 0, sizeof(r)); | ||||||
| 
 | 
 | ||||||
| 	/* Generate counts for each bit length */ | 	/* Generate counts for each bit length */ | ||||||
| 	memset(c, 0, sizeof(c)); | 	memset(c, 0, sizeof(c)); | ||||||
| 	p = (unsigned *) b; /* cast allows us to reuse p for pointing to b */ | 	p = b; | ||||||
| 	i = n; | 	i = n; | ||||||
| 	do { | 	do { | ||||||
| 		c[*p]++; /* assume all entries <= BMAX */ | 		c[*p]++; /* assume all entries <= BMAX */ | ||||||
| 		p++;     /* can't combine with above line (Solaris bug) */ | 		p++;     /* can't combine with above line (Solaris bug) */ | ||||||
| 	} while (--i); | 	} while (--i); | ||||||
| 	if (c[0] == n) {  /* null input - all zero length codes */ | 	if (c[0] == n) {  /* null input - all zero length codes */ | ||||||
| 		*m = 0; | 		q = xzalloc(3 * sizeof(*q)); | ||||||
| 		return 2; | 		//q[0].v.t = NULL;
 | ||||||
|  | 		q[1].e = 99;    /* invalid code marker */ | ||||||
|  | 		q[1].b = 1; | ||||||
|  | 		q[2].e = 99;    /* invalid code marker */ | ||||||
|  | 		q[2].b = 1; | ||||||
|  | 		*m = 1; | ||||||
|  | 		return q + 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Find minimum and maximum length, bound *m by those */ | 	/* Find minimum and maximum length, bound *m by those */ | ||||||
|  | @ -346,11 +362,11 @@ static int huft_build(const unsigned *b, const unsigned n, | ||||||
| 	for (y = 1 << j; j < i; j++, y <<= 1) { | 	for (y = 1 << j; j < i; j++, y <<= 1) { | ||||||
| 		y -= c[j]; | 		y -= c[j]; | ||||||
| 		if (y < 0) | 		if (y < 0) | ||||||
| 			return 2; /* bad input: more codes than bits */ | 			return ERR_RET; /* bad input: more codes than bits */ | ||||||
| 	} | 	} | ||||||
| 	y -= c[i]; | 	y -= c[i]; | ||||||
| 	if (y < 0) | 	if (y < 0) | ||||||
| 		return 2; | 		return ERR_RET; | ||||||
| 	c[i] += y; | 	c[i] += y; | ||||||
| 
 | 
 | ||||||
| 	/* Generate starting offsets into the value table for each length */ | 	/* Generate starting offsets into the value table for each length */ | ||||||
|  | @ -362,8 +378,12 @@ static int huft_build(const unsigned *b, const unsigned n, | ||||||
| 		*xp++ = j; | 		*xp++ = j; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Make a table of values in order of bit lengths */ | 	/* Make a table of values in order of bit lengths.
 | ||||||
| 	p = (unsigned *) b; | 	 * To detect bad input, unused v[i]'s are set to invalid value UINT_MAX. | ||||||
|  | 	 * In particular, last v[i] is never filled and must not be accessed. | ||||||
|  | 	 */ | ||||||
|  | 	memset(v, 0xff, sizeof(v)); | ||||||
|  | 	p = b; | ||||||
| 	i = 0; | 	i = 0; | ||||||
| 	do { | 	do { | ||||||
| 		j = *p++; | 		j = *p++; | ||||||
|  | @ -373,6 +393,8 @@ static int huft_build(const unsigned *b, const unsigned n, | ||||||
| 	} while (++i < n); | 	} while (++i < n); | ||||||
| 
 | 
 | ||||||
| 	/* Generate the Huffman codes and for each, make the table entries */ | 	/* Generate the Huffman codes and for each, make the table entries */ | ||||||
|  | 	result = ERR_RET; | ||||||
|  | 	t = &result; | ||||||
| 	x[0] = i = 0;   /* first Huffman code is zero */ | 	x[0] = i = 0;   /* first Huffman code is zero */ | ||||||
| 	p = v;          /* grab values in bit order */ | 	p = v;          /* grab values in bit order */ | ||||||
| 	htl = -1;       /* no tables yet--level -1 */ | 	htl = -1;       /* no tables yet--level -1 */ | ||||||
|  | @ -430,14 +452,16 @@ static int huft_build(const unsigned *b, const unsigned n, | ||||||
| 
 | 
 | ||||||
| 			/* set up table entry in r */ | 			/* set up table entry in r */ | ||||||
| 			r.b = (unsigned char) (k - w); | 			r.b = (unsigned char) (k - w); | ||||||
| 			if (p >= v + n) { | 			if (/*p >= v + n || -- redundant, caught by the second check: */ | ||||||
|  | 				*p == UINT_MAX /* do we access uninited v[i]? (see memset(v))*/ | ||||||
|  | 			) { | ||||||
| 				r.e = 99; /* out of values--invalid code */ | 				r.e = 99; /* out of values--invalid code */ | ||||||
| 			} else if (*p < s) { | 			} else if (*p < s) { | ||||||
| 				r.e = (unsigned char) (*p < 256 ? 16 : 15);	/* 256 is EOB code */ | 				r.e = (unsigned char) (*p < 256 ? 16 : 15);	/* 256 is EOB code */ | ||||||
| 				r.v.n = (unsigned short) (*p++); /* simple code is just the value */ | 				r.v.n = (unsigned short) (*p++); /* simple code is just the value */ | ||||||
| 			} else { | 			} else { | ||||||
| 				r.e = (unsigned char) e[*p - s]; /* non-simple--look up in lists */ | 				r.e = (unsigned char) cp_ext->ext[*p - s]; /* non-simple--look up in lists */ | ||||||
| 				r.v.n = d[*p++ - s]; | 				r.v.n = cp_ext->cp[*p++ - s]; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			/* fill code-like entries with r */ | 			/* fill code-like entries with r */ | ||||||
|  | @ -462,8 +486,11 @@ static int huft_build(const unsigned *b, const unsigned n, | ||||||
| 	/* return actual size of base table */ | 	/* return actual size of base table */ | ||||||
| 	*m = ws[1]; | 	*m = ws[1]; | ||||||
| 
 | 
 | ||||||
| 	/* Return 1 if we were given an incomplete table */ | 	if (y != 0 && g != 1) /* we were given an incomplete table */ | ||||||
| 	return y != 0 && g != 1; | 		/* return "result" ORed with 1 */ | ||||||
|  | 		return (void*)((uintptr_t)result | 1); | ||||||
|  | 
 | ||||||
|  | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -515,8 +542,9 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY) | ||||||
| 		e = t->e; | 		e = t->e; | ||||||
| 		if (e > 16) | 		if (e > 16) | ||||||
| 			do { | 			do { | ||||||
| 				if (e == 99) | 				if (e == 99) { | ||||||
| 					abort_unzip(PASS_STATE_ONLY);; | 					abort_unzip(PASS_STATE_ONLY); | ||||||
|  | 				} | ||||||
| 				bb >>= t->b; | 				bb >>= t->b; | ||||||
| 				k -= t->b; | 				k -= t->b; | ||||||
| 				e -= 16; | 				e -= 16; | ||||||
|  | @ -552,8 +580,9 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY) | ||||||
| 			e = t->e; | 			e = t->e; | ||||||
| 			if (e > 16) | 			if (e > 16) | ||||||
| 				do { | 				do { | ||||||
| 					if (e == 99) | 					if (e == 99) { | ||||||
| 						abort_unzip(PASS_STATE_ONLY); | 						abort_unzip(PASS_STATE_ONLY); | ||||||
|  | 					} | ||||||
| 					bb >>= t->b; | 					bb >>= t->b; | ||||||
| 					k -= t->b; | 					k -= t->b; | ||||||
| 					e -= 16; | 					e -= 16; | ||||||
|  | @ -762,14 +791,17 @@ static int inflate_block(STATE_PARAM smallint *e) | ||||||
| 		for (; i < 288; i++) /* make a complete, but wrong code set */ | 		for (; i < 288; i++) /* make a complete, but wrong code set */ | ||||||
| 			ll[i] = 8; | 			ll[i] = 8; | ||||||
| 		bl = 7; | 		bl = 7; | ||||||
| 		huft_build(ll, 288, 257, cplens, cplext, &inflate_codes_tl, &bl); | 		inflate_codes_tl = huft_build(ll, 288, 257, &lit, &bl); | ||||||
| 		/* huft_build() never return nonzero - we use known data */ | 		/* ^^^ never returns error here - we use known data */ | ||||||
| 
 | 
 | ||||||
| 		/* set up distance table */ | 		/* set up distance table */ | ||||||
| 		for (i = 0; i < 30; i++) /* make an incomplete code set */ | 		for (i = 0; i < 30; i++) /* make an incomplete code set */ | ||||||
| 			ll[i] = 5; | 			ll[i] = 5; | ||||||
| 		bd = 5; | 		bd = 5; | ||||||
| 		huft_build(ll, 30, 0, cpdist, cpdext, &inflate_codes_td, &bd); | 		inflate_codes_td = huft_build(ll, 30, 0, &dist, &bd); | ||||||
|  | 		/* ^^^ does return error here! (lsb bit is set) - we gave it incomplete code set */ | ||||||
|  | 		/* clearing error bit: */ | ||||||
|  | 		inflate_codes_td = (void*)((uintptr_t)inflate_codes_td & ~(uintptr_t)1); | ||||||
| 
 | 
 | ||||||
| 		/* set up data for inflate_codes() */ | 		/* set up data for inflate_codes() */ | ||||||
| 		inflate_codes_setup(PASS_STATE bl, bd); | 		inflate_codes_setup(PASS_STATE bl, bd); | ||||||
|  | @ -819,8 +851,9 @@ static int inflate_block(STATE_PARAM smallint *e) | ||||||
| 
 | 
 | ||||||
| 		b_dynamic >>= 4; | 		b_dynamic >>= 4; | ||||||
| 		k_dynamic -= 4; | 		k_dynamic -= 4; | ||||||
| 		if (nl > 286 || nd > 30) | 		if (nl > 286 || nd > 30) { | ||||||
| 			abort_unzip(PASS_STATE_ONLY);	/* bad lengths */ | 			abort_unzip(PASS_STATE_ONLY);	/* bad lengths */ | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		/* read in bit-length-code lengths */ | 		/* read in bit-length-code lengths */ | ||||||
| 		for (j = 0; j < nb; j++) { | 		for (j = 0; j < nb; j++) { | ||||||
|  | @ -834,9 +867,9 @@ static int inflate_block(STATE_PARAM smallint *e) | ||||||
| 
 | 
 | ||||||
| 		/* build decoding table for trees - single level, 7 bit lookup */ | 		/* build decoding table for trees - single level, 7 bit lookup */ | ||||||
| 		bl = 7; | 		bl = 7; | ||||||
| 		i = huft_build(ll, 19, 19, NULL, NULL, &inflate_codes_tl, &bl); | 		inflate_codes_tl = huft_build(ll, 19, 19, NULL, &bl); | ||||||
| 		if (i != 0) { | 		if (BAD_HUFT(inflate_codes_tl)) { | ||||||
| 			abort_unzip(PASS_STATE_ONLY); //return i;	/* incomplete code set */
 | 			abort_unzip(PASS_STATE_ONLY);	/* incomplete code set */ | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/* read in literal and distance code lengths */ | 		/* read in literal and distance code lengths */ | ||||||
|  | @ -899,14 +932,15 @@ static int inflate_block(STATE_PARAM smallint *e) | ||||||
| 
 | 
 | ||||||
| 		/* build the decoding tables for literal/length and distance codes */ | 		/* build the decoding tables for literal/length and distance codes */ | ||||||
| 		bl = lbits; | 		bl = lbits; | ||||||
| 
 | 		inflate_codes_tl = huft_build(ll, nl, 257, &lit, &bl); | ||||||
| 		i = huft_build(ll, nl, 257, cplens, cplext, &inflate_codes_tl, &bl); | 		if (BAD_HUFT(inflate_codes_tl)) { | ||||||
| 		if (i != 0) |  | ||||||
| 			abort_unzip(PASS_STATE_ONLY); | 			abort_unzip(PASS_STATE_ONLY); | ||||||
|  | 		} | ||||||
| 		bd = dbits; | 		bd = dbits; | ||||||
| 		i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &inflate_codes_td, &bd); | 		inflate_codes_td = huft_build(ll + nl, nd, 0, &dist, &bd); | ||||||
| 		if (i != 0) | 		if (BAD_HUFT(inflate_codes_td)) { | ||||||
| 			abort_unzip(PASS_STATE_ONLY); | 			abort_unzip(PASS_STATE_ONLY); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		/* set up data for inflate_codes() */ | 		/* set up data for inflate_codes() */ | ||||||
| 		inflate_codes_setup(PASS_STATE bl, bd); | 		inflate_codes_setup(PASS_STATE bl, bd); | ||||||
|  | @ -976,7 +1010,7 @@ inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate) | ||||||
| 	ssize_t nwrote; | 	ssize_t nwrote; | ||||||
| 
 | 
 | ||||||
| 	/* Allocate all global buffers (for DYN_ALLOC option) */ | 	/* Allocate all global buffers (for DYN_ALLOC option) */ | ||||||
| 	gunzip_window = xmalloc(GUNZIP_WSIZE); | 	gunzip_window = xzalloc(GUNZIP_WSIZE); | ||||||
| 	gunzip_outbuf_count = 0; | 	gunzip_outbuf_count = 0; | ||||||
| 	gunzip_bytes_out = 0; | 	gunzip_bytes_out = 0; | ||||||
| 	gunzip_src_fd = xstate->src_fd; | 	gunzip_src_fd = xstate->src_fd; | ||||||
|  | @ -995,6 +1029,7 @@ inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate) | ||||||
| 	error_msg = "corrupted data"; | 	error_msg = "corrupted data"; | ||||||
| 	if (setjmp(error_jmp)) { | 	if (setjmp(error_jmp)) { | ||||||
| 		/* Error from deep inside zip machinery */ | 		/* Error from deep inside zip machinery */ | ||||||
|  | 		bb_simple_error_msg("corrupted data"); | ||||||
| 		n = -1; | 		n = -1; | ||||||
| 		goto ret; | 		goto ret; | ||||||
| 	} | 	} | ||||||
|  | @ -1070,7 +1105,7 @@ static int top_up(STATE_PARAM unsigned n) | ||||||
| 		bytebuffer_offset = 0; | 		bytebuffer_offset = 0; | ||||||
| 		bytebuffer_size = full_read(gunzip_src_fd, &bytebuffer[count], bytebuffer_max - count); | 		bytebuffer_size = full_read(gunzip_src_fd, &bytebuffer[count], bytebuffer_max - count); | ||||||
| 		if ((int)bytebuffer_size < 0) { | 		if ((int)bytebuffer_size < 0) { | ||||||
| 			bb_error_msg(bb_msg_read_error); | 			bb_simple_error_msg(bb_msg_read_error); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
| 		bytebuffer_size += count; | 		bytebuffer_size += count; | ||||||
|  | @ -1122,9 +1157,8 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) | ||||||
| 		} PACKED formatted; | 		} PACKED formatted; | ||||||
| 	} header; | 	} header; | ||||||
| 	PRAGMA_END_PACKED | 	PRAGMA_END_PACKED | ||||||
| 	struct BUG_header { | 
 | ||||||
| 		char BUG_header[sizeof(header) == 8 ? 1 : -1]; | 	BUILD_BUG_ON(sizeof(header) != 8); | ||||||
| 	}; |  | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Rewind bytebuffer. We use the beginning because the header has 8 | 	 * Rewind bytebuffer. We use the beginning because the header has 8 | ||||||
|  | @ -1165,6 +1199,7 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) | ||||||
| 			do { | 			do { | ||||||
| 				if (!top_up(PASS_STATE 1)) | 				if (!top_up(PASS_STATE 1)) | ||||||
| 					return 0; | 					return 0; | ||||||
|  | 			// coverity[tainted_data]
 | ||||||
| 			} while (bytebuffer[bytebuffer_offset++] != 0); | 			} while (bytebuffer[bytebuffer_offset++] != 0); | ||||||
| 			if ((header.formatted.flags & 0x18) != 0x18) | 			if ((header.formatted.flags & 0x18) != 0x18) | ||||||
| 				break; | 				break; | ||||||
|  | @ -1194,16 +1229,16 @@ unpack_gz_stream(transformer_state_t *xstate) | ||||||
| 	if (check_signature16(xstate, GZIP_MAGIC)) | 	if (check_signature16(xstate, GZIP_MAGIC)) | ||||||
| 		return -1; | 		return -1; | ||||||
| #else | #else | ||||||
| 	if (xstate->check_signature) { | 	if (!xstate->signature_skipped) { | ||||||
| 		uint16_t magic2; | 		uint16_t magic2; | ||||||
| 
 | 
 | ||||||
| 		if (full_read(xstate->src_fd, &magic2, 2) != 2) { | 		if (full_read(xstate->src_fd, &magic2, 2) != 2) { | ||||||
|  bad_magic: |  bad_magic: | ||||||
| 			bb_error_msg("invalid magic"); | 			bb_simple_error_msg("invalid magic"); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		if (magic2 == COMPRESS_MAGIC) { | 		if (magic2 == COMPRESS_MAGIC) { | ||||||
| 			xstate->check_signature = 0; | 			xstate->signature_skipped = 2; | ||||||
| 			return unpack_Z_stream(xstate); | 			return unpack_Z_stream(xstate); | ||||||
| 		} | 		} | ||||||
| 		if (magic2 != GZIP_MAGIC) | 		if (magic2 != GZIP_MAGIC) | ||||||
|  | @ -1230,7 +1265,7 @@ unpack_gz_stream(transformer_state_t *xstate) | ||||||
| 
 | 
 | ||||||
|  again: |  again: | ||||||
| 	if (!check_header_gzip(PASS_STATE xstate)) { | 	if (!check_header_gzip(PASS_STATE xstate)) { | ||||||
| 		bb_error_msg("corrupted data"); | 		bb_simple_error_msg("corrupted data"); | ||||||
| 		total = -1; | 		total = -1; | ||||||
| 		goto ret; | 		goto ret; | ||||||
| 	} | 	} | ||||||
|  | @ -1243,7 +1278,7 @@ unpack_gz_stream(transformer_state_t *xstate) | ||||||
| 	total += n; | 	total += n; | ||||||
| 
 | 
 | ||||||
| 	if (!top_up(PASS_STATE 8)) { | 	if (!top_up(PASS_STATE 8)) { | ||||||
| 		bb_error_msg("corrupted data"); | 		bb_simple_error_msg("corrupted data"); | ||||||
| 		total = -1; | 		total = -1; | ||||||
| 		goto ret; | 		goto ret; | ||||||
| 	} | 	} | ||||||
|  | @ -1251,7 +1286,7 @@ unpack_gz_stream(transformer_state_t *xstate) | ||||||
| 	/* Validate decompression - crc */ | 	/* Validate decompression - crc */ | ||||||
| 	v32 = buffer_read_le_u32(PASS_STATE_ONLY); | 	v32 = buffer_read_le_u32(PASS_STATE_ONLY); | ||||||
| 	if ((~gunzip_crc) != v32) { | 	if ((~gunzip_crc) != v32) { | ||||||
| 		bb_error_msg("crc error"); | 		bb_simple_error_msg("crc error"); | ||||||
| 		total = -1; | 		total = -1; | ||||||
| 		goto ret; | 		goto ret; | ||||||
| 	} | 	} | ||||||
|  | @ -1259,7 +1294,7 @@ unpack_gz_stream(transformer_state_t *xstate) | ||||||
| 	/* Validate decompression - size */ | 	/* Validate decompression - size */ | ||||||
| 	v32 = buffer_read_le_u32(PASS_STATE_ONLY); | 	v32 = buffer_read_le_u32(PASS_STATE_ONLY); | ||||||
| 	if ((uint32_t)gunzip_bytes_out != v32) { | 	if ((uint32_t)gunzip_bytes_out != v32) { | ||||||
| 		bb_error_msg("incorrect length"); | 		bb_simple_error_msg("incorrect length"); | ||||||
| 		total = -1; | 		total = -1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| /* vi: set sw=4 ts=4: */ | /* vi: set sw=4 ts=4: */ | ||||||
| /* uncompress for busybox -- (c) 2002 Robert Griebl
 | /*
 | ||||||
|  |  * uncompress for busybox -- (c) 2002 Robert Griebl | ||||||
|  * |  * | ||||||
|  * based on the original compress42.c source |  * based on the original compress42.c source | ||||||
|  * (see disclaimer below) |  * (see disclaimer below) | ||||||
|  */ |  */ | ||||||
| 
 |  | ||||||
| /* (N)compress42.c - File compression ala IEEE Computer, Mar 1992.
 | /* (N)compress42.c - File compression ala IEEE Computer, Mar 1992.
 | ||||||
|  * |  * | ||||||
|  * Authors: |  * Authors: | ||||||
|  | @ -21,9 +21,7 @@ | ||||||
|  * marc@suse.de : a small security fix for a buffer overflow |  * marc@suse.de : a small security fix for a buffer overflow | ||||||
|  * |  * | ||||||
|  * [... History snipped ...] |  * [... History snipped ...] | ||||||
|  * |  | ||||||
|  */ |  */ | ||||||
| 
 |  | ||||||
| #include "libbb.h" | #include "libbb.h" | ||||||
| #include "bb_archive.h" | #include "bb_archive.h" | ||||||
| 
 | 
 | ||||||
|  | @ -115,7 +113,7 @@ unpack_Z_stream(transformer_state_t *xstate) | ||||||
| 	/* xread isn't good here, we have to return - caller may want
 | 	/* xread isn't good here, we have to return - caller may want
 | ||||||
| 	 * to do some cleanup (e.g. delete incomplete unpacked file etc) */ | 	 * to do some cleanup (e.g. delete incomplete unpacked file etc) */ | ||||||
| 	if (full_read(xstate->src_fd, inbuf, 1) != 1) { | 	if (full_read(xstate->src_fd, inbuf, 1) != 1) { | ||||||
| 		bb_error_msg("short read"); | 		bb_simple_error_msg("short read"); | ||||||
| 		goto err; | 		goto err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -168,7 +166,7 @@ unpack_Z_stream(transformer_state_t *xstate) | ||||||
| 		if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { | 		if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { | ||||||
| 			rsize = safe_read(xstate->src_fd, inbuf + insize, IBUFSIZ); | 			rsize = safe_read(xstate->src_fd, inbuf + insize, IBUFSIZ); | ||||||
| 			if (rsize < 0) | 			if (rsize < 0) | ||||||
| 				bb_error_msg_and_err(bb_msg_read_error); | 				bb_simple_error_msg_and_die(bb_msg_read_error); | ||||||
| 			insize += rsize; | 			insize += rsize; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -202,7 +200,7 @@ unpack_Z_stream(transformer_state_t *xstate) | ||||||
| 
 | 
 | ||||||
| 			if (oldcode == -1) { | 			if (oldcode == -1) { | ||||||
| 				if (code >= 256) | 				if (code >= 256) | ||||||
| 					bb_error_msg_and_err("corrupted data"); /* %ld", code); */ | 					bb_simple_error_msg_and_die("corrupted data"); /* %ld", code); */ | ||||||
| 				oldcode = code; | 				oldcode = code; | ||||||
| 				finchar = (int) oldcode; | 				finchar = (int) oldcode; | ||||||
| 				outbuf[outpos++] = (unsigned char) finchar; | 				outbuf[outpos++] = (unsigned char) finchar; | ||||||
|  | @ -238,7 +236,7 @@ unpack_Z_stream(transformer_state_t *xstate) | ||||||
| 						insize, posbits, p[-1], p[0], p[1], p[2], p[3], | 						insize, posbits, p[-1], p[0], p[1], p[2], p[3], | ||||||
| 						(posbits & 07)); | 						(posbits & 07)); | ||||||
| */ | */ | ||||||
| 					bb_error_msg("corrupted data"); | 					bb_simple_error_msg("corrupted data"); | ||||||
| 					goto err; | 					goto err; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | @ -249,7 +247,7 @@ unpack_Z_stream(transformer_state_t *xstate) | ||||||
| 			/* Generate output characters in reverse order */ | 			/* Generate output characters in reverse order */ | ||||||
| 			while (code >= 256) { | 			while (code >= 256) { | ||||||
| 				if (stackp <= &htabof(0)) | 				if (stackp <= &htabof(0)) | ||||||
| 					bb_error_msg_and_err("corrupted data"); | 					bb_simple_error_msg_and_die("corrupted data"); | ||||||
| 				*--stackp = tab_suffixof(code); | 				*--stackp = tab_suffixof(code); | ||||||
| 				code = tab_prefixof(code); | 				code = tab_prefixof(code); | ||||||
| 			} | 			} | ||||||
|  | @ -301,7 +299,6 @@ unpack_Z_stream(transformer_state_t *xstate) | ||||||
| 			/* Remember previous code.  */ | 			/* Remember previous code.  */ | ||||||
| 			oldcode = incode; | 			oldcode = incode; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 	} while (rsize > 0); | 	} while (rsize > 0); | ||||||
| 
 | 
 | ||||||
| 	if (outpos > 0) { | 	if (outpos > 0) { | ||||||
|  |  | ||||||
|  | @ -11,6 +11,13 @@ | ||||||
| #include "libbb.h" | #include "libbb.h" | ||||||
| #include "bb_archive.h" | #include "bb_archive.h" | ||||||
| 
 | 
 | ||||||
|  | #if 0 | ||||||
|  | # define dbg(...) bb_error_msg(__VA_ARGS__) | ||||||
|  | #else | ||||||
|  | # define dbg(...) ((void)0) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| #if ENABLE_FEATURE_LZMA_FAST | #if ENABLE_FEATURE_LZMA_FAST | ||||||
| #  define speed_inline ALWAYS_INLINE | #  define speed_inline ALWAYS_INLINE | ||||||
| #  define size_inline | #  define size_inline | ||||||
|  | @ -52,7 +59,7 @@ static void rc_read(rc_t *rc) | ||||||
| //TODO: return -1 instead
 | //TODO: return -1 instead
 | ||||||
| //This will make unlzma delete broken unpacked file on unpack errors
 | //This will make unlzma delete broken unpacked file on unpack errors
 | ||||||
| 	if (buffer_size <= 0) | 	if (buffer_size <= 0) | ||||||
| 		bb_error_msg_and_die("unexpected EOF"); | 		bb_simple_error_msg_and_die("unexpected EOF"); | ||||||
| 	rc->buffer_end = RC_BUFFER + buffer_size; | 	rc->buffer_end = RC_BUFFER + buffer_size; | ||||||
| 	rc->ptr = RC_BUFFER; | 	rc->ptr = RC_BUFFER; | ||||||
| } | } | ||||||
|  | @ -220,9 +227,10 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 	rc_t *rc; | 	rc_t *rc; | ||||||
| 	int i; | 	int i; | ||||||
| 	uint8_t *buffer; | 	uint8_t *buffer; | ||||||
|  | 	uint32_t buffer_size; | ||||||
| 	uint8_t previous_byte = 0; | 	uint8_t previous_byte = 0; | ||||||
| 	size_t buffer_pos = 0, global_pos = 0; | 	size_t buffer_pos = 0, global_pos = 0; | ||||||
| 	ssize_t nwrote; | 	ssize_t nwrote = 0; | ||||||
| 	int len = 0; | 	int len = 0; | ||||||
| 	int state = 0; | 	int state = 0; | ||||||
| 	uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; | 	uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; | ||||||
|  | @ -230,7 +238,7 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 	if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header) | 	if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header) | ||||||
| 	 || header.pos >= (9 * 5 * 5) | 	 || header.pos >= (9 * 5 * 5) | ||||||
| 	) { | 	) { | ||||||
| 		bb_error_msg("bad lzma header"); | 		bb_simple_error_msg("bad lzma header"); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -250,7 +258,8 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 	if (header.dict_size == 0) | 	if (header.dict_size == 0) | ||||||
| 		header.dict_size++; | 		header.dict_size++; | ||||||
| 
 | 
 | ||||||
| 	buffer = xmalloc((size_t)MIN(header.dst_size, header.dict_size)); | 	buffer_size = (uint32_t)MIN(header.dst_size, header.dict_size); | ||||||
|  | 	buffer = xmalloc(buffer_size); | ||||||
| 
 | 
 | ||||||
| 	{ | 	{ | ||||||
| 		int num_probs; | 		int num_probs; | ||||||
|  | @ -267,14 +276,14 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 	while ((uint64_t)global_pos + buffer_pos < header.dst_size) { | 	while ((uint64_t)global_pos + buffer_pos < header.dst_size) { | ||||||
| 		int pos_state = (buffer_pos + global_pos) & pos_state_mask; | 		int pos_state = (buffer_pos + global_pos) & pos_state_mask; | ||||||
| 		uintptr_t off1 = LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state; | 		uintptr_t off1 = LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state; | ||||||
| 		uint16_t *prob1 = p + off1; | 		uint16_t *prob = p + off1; | ||||||
| 
 | 
 | ||||||
| 		if (!rc_is_bit_1(rc, prob1)) { | 		if (!rc_is_bit_1(rc, prob)) { | ||||||
| 			static const char next_state[LZMA_NUM_STATES] = | 			static const char next_state[LZMA_NUM_STATES] = | ||||||
| 				{ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 }; | 				{ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 }; | ||||||
| 			int mi = 1; | 			int mi = 1; | ||||||
| 
 | 
 | ||||||
| 			prob1 = (p + LZMA_LITERAL | 			prob = (p + LZMA_LITERAL | ||||||
| 			        + (LZMA_LIT_SIZE * ((((buffer_pos + global_pos) & literal_pos_mask) << lc) | 			        + (LZMA_LIT_SIZE * ((((buffer_pos + global_pos) & literal_pos_mask) << lc) | ||||||
| 			                            + (previous_byte >> (8 - lc)) | 			                            + (previous_byte >> (8 - lc)) | ||||||
| 			                           ) | 			                           ) | ||||||
|  | @ -283,23 +292,27 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 
 | 
 | ||||||
| 			if (state >= LZMA_NUM_LIT_STATES) { | 			if (state >= LZMA_NUM_LIT_STATES) { | ||||||
| 				int match_byte; | 				int match_byte; | ||||||
| 				uint32_t pos = (uint32_t)(buffer_pos - rep0); | 				uint32_t pos; | ||||||
| 
 | 
 | ||||||
| 				while (pos >= header.dict_size) | 				pos = (uint32_t)(buffer_pos - rep0); | ||||||
|  | 				if ((int32_t)pos < 0) { | ||||||
| 					pos += header.dict_size; | 					pos += header.dict_size; | ||||||
|  | 					if ((int32_t)pos < 0) | ||||||
|  | 						goto bad; | ||||||
|  | 				} | ||||||
| 				match_byte = buffer[pos]; | 				match_byte = buffer[pos]; | ||||||
| 				do { | 				do { | ||||||
| 					int bit; | 					int bit; | ||||||
| 
 | 
 | ||||||
| 					match_byte <<= 1; | 					match_byte <<= 1; | ||||||
| 					bit = match_byte & 0x100; | 					bit = match_byte & 0x100; | ||||||
| 					bit ^= (rc_get_bit(rc, prob1 + 0x100 + bit + mi, &mi) << 8); /* 0x100 or 0 */ | 					bit ^= (rc_get_bit(rc, prob + 0x100 + bit + mi, &mi) << 8); /* 0x100 or 0 */ | ||||||
| 					if (bit) | 					if (bit) | ||||||
| 						break; | 						break; | ||||||
| 				} while (mi < 0x100); | 				} while (mi < 0x100); | ||||||
| 			} | 			} | ||||||
| 			while (mi < 0x100) { | 			while (mi < 0x100) { | ||||||
| 				rc_get_bit(rc, prob1 + mi, &mi); | 				rc_get_bit(rc, prob + mi, &mi); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			state = next_state[state]; | 			state = next_state[state]; | ||||||
|  | @ -336,14 +349,24 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 			} else { | 			} else { | ||||||
| 				prob2 += LZMA_IS_REP_G0 - LZMA_IS_REP; | 				prob2 += LZMA_IS_REP_G0 - LZMA_IS_REP; | ||||||
| 				if (!rc_is_bit_1(rc, prob2)) { | 				if (!rc_is_bit_1(rc, prob2)) { | ||||||
| 					uintptr_t off2 = LZMA_IS_REP_0_LONG + (state << LZMA_NUM_POS_BITS_MAX) + pos_state; | 					prob2 = (p + LZMA_IS_REP_0_LONG | ||||||
| 					prob2 = p + off2; | 					        + (state << LZMA_NUM_POS_BITS_MAX) | ||||||
|  | 					        + pos_state | ||||||
|  | 					); | ||||||
| 					if (!rc_is_bit_1(rc, prob2)) { | 					if (!rc_is_bit_1(rc, prob2)) { | ||||||
| #if ENABLE_FEATURE_LZMA_FAST | #if ENABLE_FEATURE_LZMA_FAST | ||||||
| 						uint32_t pos = buffer_pos - rep0; | 						uint32_t pos; | ||||||
| 						state = state < LZMA_NUM_LIT_STATES ? 9 : 11; | 						state = state < LZMA_NUM_LIT_STATES ? 9 : 11; | ||||||
| 						while (pos >= header.dict_size) | 
 | ||||||
|  | 						pos = buffer_pos - rep0; | ||||||
|  | 						if ((int32_t)pos < 0) { | ||||||
| 							pos += header.dict_size; | 							pos += header.dict_size; | ||||||
|  | 							/* see unzip_bad_lzma_2.zip: */ | ||||||
|  | 							if (pos >= buffer_size) { | ||||||
|  | 								dbg("%d pos:%d buffer_size:%d", __LINE__, pos, buffer_size); | ||||||
|  | 								goto bad; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
| 						previous_byte = buffer[pos]; | 						previous_byte = buffer[pos]; | ||||||
| 						goto one_byte1; | 						goto one_byte1; | ||||||
| #else | #else | ||||||
|  | @ -418,6 +441,9 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 						for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--) | 						for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--) | ||||||
| 							rep0 = (rep0 << 1) | rc_direct_bit(rc); | 							rep0 = (rep0 << 1) | rc_direct_bit(rc); | ||||||
| 						rep0 <<= LZMA_NUM_ALIGN_BITS; | 						rep0 <<= LZMA_NUM_ALIGN_BITS; | ||||||
|  | 						// Note: (int32_t)rep0 may be < 0 here
 | ||||||
|  | 						// (I have linux-3.3.4.tar.lzma which has it).
 | ||||||
|  | 						// I moved the check after "++rep0 == 0" check below.
 | ||||||
| 						prob3 = p + LZMA_ALIGN; | 						prob3 = p + LZMA_ALIGN; | ||||||
| 					} | 					} | ||||||
| 					i2 = 1; | 					i2 = 1; | ||||||
|  | @ -428,16 +454,43 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 						i2 <<= 1; | 						i2 <<= 1; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				if (++rep0 == 0) | 				rep0++; | ||||||
|  | 				if ((int32_t)rep0 <= 0) { | ||||||
|  | 					if (rep0 == 0) | ||||||
| 						break; | 						break; | ||||||
|  | 					dbg("%d rep0:%d", __LINE__, rep0); | ||||||
|  | 					goto bad; | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			len += LZMA_MATCH_MIN_LEN; | 			len += LZMA_MATCH_MIN_LEN; | ||||||
|  | 			/*
 | ||||||
|  | 			 * LZMA SDK has this optimized: | ||||||
|  | 			 * it precalculates size and copies many bytes | ||||||
|  | 			 * in a loop with simpler checks, a-la: | ||||||
|  | 			 *	do | ||||||
|  | 			 *		*(dest) = *(dest + ofs); | ||||||
|  | 			 *	while (++dest != lim); | ||||||
|  | 			 * and | ||||||
|  | 			 *	do { | ||||||
|  | 			 *		buffer[buffer_pos++] = buffer[pos]; | ||||||
|  | 			 *		if (++pos == header.dict_size) | ||||||
|  | 			 *			pos = 0; | ||||||
|  | 			 *	} while (--cur_len != 0); | ||||||
|  | 			 * Our code is slower (more checks per byte copy): | ||||||
|  | 			 */ | ||||||
|  IF_NOT_FEATURE_LZMA_FAST(string:) |  IF_NOT_FEATURE_LZMA_FAST(string:) | ||||||
| 			do { | 			do { | ||||||
| 				uint32_t pos = (uint32_t)(buffer_pos - rep0); | 				uint32_t pos = (uint32_t)(buffer_pos - rep0); | ||||||
| 				while (pos >= header.dict_size) | 				if ((int32_t)pos < 0) { | ||||||
| 					pos += header.dict_size; | 					pos += header.dict_size; | ||||||
|  | 					/* bug 10436 has an example file where this triggers: */ | ||||||
|  | 					//if ((int32_t)pos < 0)
 | ||||||
|  | 					//	goto bad;
 | ||||||
|  | 					/* more stringent test (see unzip_bad_lzma_1.zip): */ | ||||||
|  | 					if (pos >= buffer_size) | ||||||
|  | 						goto bad; | ||||||
|  | 				} | ||||||
| 				previous_byte = buffer[pos]; | 				previous_byte = buffer[pos]; | ||||||
|  IF_NOT_FEATURE_LZMA_FAST(one_byte2:) |  IF_NOT_FEATURE_LZMA_FAST(one_byte2:) | ||||||
| 				buffer[buffer_pos++] = previous_byte; | 				buffer[buffer_pos++] = previous_byte; | ||||||
|  | @ -453,6 +506,9 @@ unpack_lzma_stream(transformer_state_t *xstate) | ||||||
| 			} while (len != 0 && buffer_pos < header.dst_size); | 			} while (len != 0 && buffer_pos < header.dst_size); | ||||||
| 			/* FIXME: ...........^^^^^
 | 			/* FIXME: ...........^^^^^
 | ||||||
| 			 * shouldn't it be "global_pos + buffer_pos < header.dst_size"? | 			 * shouldn't it be "global_pos + buffer_pos < header.dst_size"? | ||||||
|  | 			 * It probably should, but it is a "do we accidentally | ||||||
|  | 			 * unpack more bytes than expected?" check - which | ||||||
|  | 			 * never happens for well-formed compression data... | ||||||
| 			 */ | 			 */ | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -312,6 +312,7 @@ IF_DESKTOP(long long) int FAST_FUNC unpack_zip_stream(transformer_state_t *xstat | ||||||
| 			xstate->dst_size = zip_header.formatted.ucmpsize; | 			xstate->dst_size = zip_header.formatted.ucmpsize; | ||||||
| 			xstate->dst_name = xzalloc(zip_header.formatted.filename_len + 1); | 			xstate->dst_name = xzalloc(zip_header.formatted.filename_len + 1); | ||||||
| 			safe_read(xstate->src_fd, xstate->dst_name, zip_header.formatted.filename_len); | 			safe_read(xstate->src_fd, xstate->dst_name, zip_header.formatted.filename_len); | ||||||
|  | 			xstate->dst_name[zip_header.formatted.filename_len] = 0; | ||||||
| 			n = transformer_switch_file(xstate); | 			n = transformer_switch_file(xstate); | ||||||
| 			free(xstate->dst_name); | 			free(xstate->dst_name); | ||||||
| 			if (n < 0) | 			if (n < 0) | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Licensed under GPLv2 or later, see file LICENSE in this source tree. |  * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||||||
|  */ |  */ | ||||||
| 
 |  | ||||||
| #include "libbb.h" | #include "libbb.h" | ||||||
| #include "bb_archive.h" | #include "bb_archive.h" | ||||||
| 
 | 
 | ||||||
|  | @ -12,6 +11,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) | ||||||
| 	struct tm *ptm = &tm_time; //localtime(&file_header->mtime);
 | 	struct tm *ptm = &tm_time; //localtime(&file_header->mtime);
 | ||||||
| 
 | 
 | ||||||
| #if ENABLE_FEATURE_TAR_UNAME_GNAME | #if ENABLE_FEATURE_TAR_UNAME_GNAME | ||||||
|  | 	char modestr[12]; | ||||||
| 	char uid[sizeof(int)*3 + 2]; | 	char uid[sizeof(int)*3 + 2]; | ||||||
| 	/*char gid[sizeof(int)*3 + 2];*/ | 	/*char gid[sizeof(int)*3 + 2];*/ | ||||||
| 	char *user; | 	char *user; | ||||||
|  | @ -30,7 +30,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) | ||||||
| 		group = utoa(file_header->gid); | 		group = utoa(file_header->gid); | ||||||
| 	} | 	} | ||||||
| 	printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", | 	printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", | ||||||
| 		bb_mode_string(file_header->mode), | 		bb_mode_string(modestr, file_header->mode), | ||||||
| 		user, | 		user, | ||||||
| 		group, | 		group, | ||||||
| 		file_header->size, | 		file_header->size, | ||||||
|  | @ -47,7 +47,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) | ||||||
| 	localtime_r(&file_header->mtime, ptm); | 	localtime_r(&file_header->mtime, ptm); | ||||||
| 
 | 
 | ||||||
| 	printf("%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", | 	printf("%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", | ||||||
| 		bb_mode_string(file_header->mode), | 		bb_mode_string(modestr, file_header->mode), | ||||||
| 		(unsigned)file_header->uid, | 		(unsigned)file_header->uid, | ||||||
| 		(unsigned)file_header->gid, | 		(unsigned)file_header->gid, | ||||||
| 		file_header->size, | 		file_header->size, | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ | ||||||
| #define IF_NOT_FEATURE_LZMA_FAST(x) x | #define IF_NOT_FEATURE_LZMA_FAST(x) x | ||||||
| 
 | 
 | ||||||
| #define uoff_t unsigned off_t | #define uoff_t unsigned off_t | ||||||
| #define OFF_FMT "I64" | #define OFF_FMT PRIi64 | ||||||
| 
 | 
 | ||||||
| #ifndef _MODE_T_ | #ifndef _MODE_T_ | ||||||
| #define _MODE_T_ | #define _MODE_T_ | ||||||
|  | @ -86,6 +86,8 @@ typedef unsigned int uid_t; | ||||||
| #define PATH_MAX MAX_PATH | #define PATH_MAX MAX_PATH | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) | ||||||
|  | 
 | ||||||
| #ifndef get_le64 | #ifndef get_le64 | ||||||
| #define get_le64(ptr) (*(const uint64_t *)(ptr)) | #define get_le64(ptr) (*(const uint64_t *)(ptr)) | ||||||
| #endif | #endif | ||||||
|  | @ -146,6 +148,9 @@ extern unsigned long* bled_cancel_request; | ||||||
| #define bb_error_msg_and_err(...) do {bb_error_msg(__VA_ARGS__); goto err;} while(0) | #define bb_error_msg_and_err(...) do {bb_error_msg(__VA_ARGS__); goto err;} while(0) | ||||||
| #define bb_perror_msg bb_error_msg | #define bb_perror_msg bb_error_msg | ||||||
| #define bb_perror_msg_and_die bb_error_msg_and_die | #define bb_perror_msg_and_die bb_error_msg_and_die | ||||||
|  | #define bb_simple_error_msg bb_error_msg | ||||||
|  | #define bb_simple_perror_msg_and_die bb_error_msg_and_die | ||||||
|  | #define bb_simple_error_msg_and_die bb_error_msg_and_die | ||||||
| #define bb_putchar putchar | #define bb_putchar putchar | ||||||
| 
 | 
 | ||||||
| static inline void *xrealloc(void *ptr, size_t size) { | static inline void *xrealloc(void *ptr, size_t size) { | ||||||
|  | @ -157,7 +162,7 @@ static inline void *xrealloc(void *ptr, size_t size) { | ||||||
| 
 | 
 | ||||||
| #define bb_msg_read_error "read error" | #define bb_msg_read_error "read error" | ||||||
| #define bb_msg_write_error "write error" | #define bb_msg_write_error "write error" | ||||||
| #define bb_mode_string(mode) "[not implemented]" | #define bb_mode_string(str, mode) "[not implemented]" | ||||||
| #define bb_copyfd_exact_size(fd1, fd2, size) bb_error_msg("Not implemented") | #define bb_copyfd_exact_size(fd1, fd2, size) bb_error_msg("Not implemented") | ||||||
| #define bb_make_directory(path, mode, flags) SHCreateDirectoryExU(NULL, path, NULL) | #define bb_make_directory(path, mode, flags) SHCreateDirectoryExU(NULL, path, NULL) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ void FAST_FUNC init_transformer_state(transformer_state_t *xstate) | ||||||
| 
 | 
 | ||||||
| int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16) | int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16) | ||||||
| { | { | ||||||
| 	if (xstate->check_signature) { | 	if (!xstate->signature_skipped) { | ||||||
| 		uint16_t magic2; | 		uint16_t magic2; | ||||||
| 		if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { | 		if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { | ||||||
| 			bb_error_msg("invalid magic"); | 			bb_error_msg("invalid magic"); | ||||||
|  |  | ||||||
|  | @ -486,11 +486,11 @@ static __always_inline void XZ_FUNC rc_normalize(struct rc_dec *rc) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Decode one bit. In some versions, this function has been splitted in three |  * Decode one bit. In some versions, this function has been split in three | ||||||
|  * functions so that the compiler is supposed to be able to more easily avoid |  * functions so that the compiler is supposed to be able to more easily avoid | ||||||
|  * an extra branch. In this particular version of the LZMA decoder, this |  * an extra branch. In this particular version of the LZMA decoder, this | ||||||
|  * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 |  * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 | ||||||
|  * on x86). Using a non-splitted version results in nicer looking code too. |  * on x86). Using a non-split version results in nicer looking code too. | ||||||
|  * |  * | ||||||
|  * NOTE: This must return an int. Do not make it return a bool or the speed |  * NOTE: This must return an int. Do not make it return a bool or the speed | ||||||
|  * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, |  * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, | ||||||
|  | @ -788,6 +788,7 @@ static void XZ_FUNC lzma_reset(struct xz_dec_lzma2 *s) | ||||||
| 	 */ | 	 */ | ||||||
| 	probs = s->lzma.is_match[0]; | 	probs = s->lzma.is_match[0]; | ||||||
| 	for (i = 0; i < PROBS_TOTAL; ++i) | 	for (i = 0; i < PROBS_TOTAL; ++i) | ||||||
|  | 		// coverity[overrun-local]
 | ||||||
| 		probs[i] = RC_BIT_MODEL_TOTAL / 2; | 		probs[i] = RC_BIT_MODEL_TOTAL / 2; | ||||||
| 
 | 
 | ||||||
| 	rc_reset(&s->rc); | 	rc_reset(&s->rc); | ||||||
|  | @ -995,10 +996,8 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( | ||||||
| 					s->lzma2.need_props = false; | 					s->lzma2.need_props = false; | ||||||
| 					s->lzma2.next_sequence | 					s->lzma2.next_sequence | ||||||
| 							= SEQ_PROPERTIES; | 							= SEQ_PROPERTIES; | ||||||
| 
 |  | ||||||
| 				} else if (s->lzma2.need_props) { | 				} else if (s->lzma2.need_props) { | ||||||
| 					return XZ_DATA_ERROR; | 					return XZ_DATA_ERROR; | ||||||
| 
 |  | ||||||
| 				} else { | 				} else { | ||||||
| 					s->lzma2.next_sequence | 					s->lzma2.next_sequence | ||||||
| 							= SEQ_LZMA_PREPARE; | 							= SEQ_LZMA_PREPARE; | ||||||
|  | @ -1044,6 +1043,7 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( | ||||||
| 				return XZ_DATA_ERROR; | 				return XZ_DATA_ERROR; | ||||||
| 
 | 
 | ||||||
| 			s->lzma2.sequence = SEQ_LZMA_PREPARE; | 			s->lzma2.sequence = SEQ_LZMA_PREPARE; | ||||||
|  | 			// Fall through
 | ||||||
| 
 | 
 | ||||||
| 		case SEQ_LZMA_PREPARE: | 		case SEQ_LZMA_PREPARE: | ||||||
| 			if (s->lzma2.compressed < RC_INIT_BYTES) | 			if (s->lzma2.compressed < RC_INIT_BYTES) | ||||||
|  | @ -1054,6 +1054,7 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( | ||||||
| 
 | 
 | ||||||
| 			s->lzma2.compressed -= RC_INIT_BYTES; | 			s->lzma2.compressed -= RC_INIT_BYTES; | ||||||
| 			s->lzma2.sequence = SEQ_LZMA_RUN; | 			s->lzma2.sequence = SEQ_LZMA_RUN; | ||||||
|  | 			// Fall through
 | ||||||
| 
 | 
 | ||||||
| 		case SEQ_LZMA_RUN: | 		case SEQ_LZMA_RUN: | ||||||
| 			/*
 | 			/*
 | ||||||
|  | @ -1080,7 +1081,6 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( | ||||||
| 
 | 
 | ||||||
| 				rc_reset(&s->rc); | 				rc_reset(&s->rc); | ||||||
| 				s->lzma2.sequence = SEQ_CONTROL; | 				s->lzma2.sequence = SEQ_CONTROL; | ||||||
| 
 |  | ||||||
| 			} else if (b->out_pos == b->out_size | 			} else if (b->out_pos == b->out_size | ||||||
| 					|| (b->in_pos == b->in_size | 					|| (b->in_pos == b->in_size | ||||||
| 						&& s->temp.size | 						&& s->temp.size | ||||||
|  |  | ||||||
|  | @ -353,7 +353,6 @@ static enum xz_ret XZ_FUNC crc32_validate(struct xz_dec *s, struct xz_buf *b) | ||||||
| 			return XZ_DATA_ERROR; | 			return XZ_DATA_ERROR; | ||||||
| 
 | 
 | ||||||
| 		s->pos += 8; | 		s->pos += 8; | ||||||
| 
 |  | ||||||
| 	} while (s->pos < 32); | 	} while (s->pos < 32); | ||||||
| 
 | 
 | ||||||
| 	s->crc32 = 0; | 	s->crc32 = 0; | ||||||
|  | @ -546,7 +545,7 @@ static enum xz_ret XZ_FUNC dec_block_header(struct xz_dec *s) | ||||||
| 	return XZ_OK; | 	return XZ_OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b) | static NOINLINE enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b) | ||||||
| { | { | ||||||
| 	enum xz_ret ret; | 	enum xz_ret ret; | ||||||
| 
 | 
 | ||||||
|  | @ -753,7 +752,6 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b) | ||||||
| 			b->in_pos = in_start; | 			b->in_pos = in_start; | ||||||
| 			b->out_pos = out_start; | 			b->out_pos = out_start; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 	} else if (ret == XZ_OK && in_start == b->in_pos | 	} else if (ret == XZ_OK && in_start == b->in_pos | ||||||
| 			&& out_start == b->out_pos) { | 			&& out_start == b->out_pos) { | ||||||
| 		if (s->allow_buf_error) | 		if (s->allow_buf_error) | ||||||
|  |  | ||||||
|  | @ -468,8 +468,11 @@ BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LP | ||||||
| 			ctime = UINT32_MAX; | 			ctime = UINT32_MAX; | ||||||
| 		inode.i_mode = 0100644; | 		inode.i_mode = 0100644; | ||||||
| 		inode.i_links_count = 1; | 		inode.i_links_count = 1; | ||||||
|  | 		// coverity[store_truncates_time_t]
 | ||||||
| 		inode.i_atime = (uint32_t)ctime; | 		inode.i_atime = (uint32_t)ctime; | ||||||
|  | 		// coverity[store_truncates_time_t]
 | ||||||
| 		inode.i_ctime = (uint32_t)ctime; | 		inode.i_ctime = (uint32_t)ctime; | ||||||
|  | 		// coverity[store_truncates_time_t]
 | ||||||
| 		inode.i_mtime = (uint32_t)ctime; | 		inode.i_mtime = (uint32_t)ctime; | ||||||
| 		inode.i_size = fsize; | 		inode.i_size = fsize; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 232, 326 | IDD_DIALOG DIALOGEX 12, 12, 232, 326 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 3.21.1934" | CAPTION "Rufus 3.21.1935" | ||||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP |     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||||
|  | @ -395,8 +395,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 3,21,1934,0 |  FILEVERSION 3,21,1935,0 | ||||||
|  PRODUCTVERSION 3,21,1934,0 |  PRODUCTVERSION 3,21,1935,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -414,13 +414,13 @@ BEGIN | ||||||
|             VALUE "Comments", "https://rufus.ie" |             VALUE "Comments", "https://rufus.ie" | ||||||
|             VALUE "CompanyName", "Akeo Consulting" |             VALUE "CompanyName", "Akeo Consulting" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "3.21.1934" |             VALUE "FileVersion", "3.21.1935" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2022 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2022 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" |             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" | ||||||
|             VALUE "OriginalFilename", "rufus-3.21.exe" |             VALUE "OriginalFilename", "rufus-3.21.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "3.21.1934" |             VALUE "ProductVersion", "3.21.1935" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue