From b920a38dc0a87f5884444d4731a8b887b5e16018 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Jul 2017 17:20:13 +0200 Subject: tar: postpone creation of symlinks with "suspicious" targets. Closes 8411 function old new delta data_extract_all 968 1038 +70 tar_main 952 986 +34 scan_tree 258 262 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 108/0) Total: 108 bytes Signed-off-by: Denys Vlasenko --- include/bb_archive.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/bb_archive.h b/include/bb_archive.h index 2b9c5f04c..d3762415f 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -64,6 +64,9 @@ typedef struct archive_handle_t { /* Currently processed file's header */ file_header_t *file_header; + /* List of symlink placeholders */ + llist_t *symlink_placeholders; + /* Process the header component, e.g. tar -t */ void FAST_FUNC (*action_header)(const file_header_t *); @@ -188,6 +191,7 @@ char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC; char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC; char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC; char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC; +char get_header_tar_xz(archive_handle_t *archive_handle) FAST_FUNC; char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC; char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC; char get_header_tar_xz(archive_handle_t *archive_handle) FAST_FUNC; -- cgit v1.2.3-55-g6feb From 619d9b5e6848a72350126ea9c1e413fd133181e3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 28 Jul 2017 15:28:33 +0200 Subject: ash: less hackish implementation of evaltreenr() Defining a function alias with __attribute__ ((alias("evaltree"),__noreturn__)) is not that usual, and clang had a bug which made it misunderstand this construct. Switch to: ALWAYS_INLINE NORETURN evaltreenr() { evaltree(); unreachable(); } Older gcc's do not know unreachable(), on them we pay the price of having a few extra calls to abort(): function old new delta evalsubshell 151 156 +5 evalpipe 357 362 +5 argstr 1141 1144 +3 On newer gcc, code size does not change. Signed-off-by: Denys Vlasenko --- include/platform.h | 7 +++++++ shell/ash.c | 20 ++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/platform.h b/include/platform.h index 8210e5c49..ea49c7e92 100644 --- a/include/platform.h +++ b/include/platform.h @@ -45,6 +45,13 @@ #define UNUSED_PARAM __attribute__ ((__unused__)) #define NORETURN __attribute__ ((__noreturn__)) + +#if __GNUC_PREREQ(4,5) +# define bb_unreachable(altcode) __builtin_unreachable() +#else +# define bb_unreachable(altcode) altcode +#endif + /* "The malloc attribute is used to tell the compiler that a function * may be treated as if any non-NULL pointer it returns cannot alias * any other pointer valid when the function returns. This will often diff --git a/shell/ash.c b/shell/ash.c index f74fbd72f..1f5a8dae0 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6137,6 +6137,19 @@ struct backcmd { /* result of evalbackcmd */ #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ static int evaltree(union node *, int); +/* An evaltree() which is known to never return. + * Used to use an alias: + * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__)); + * but clang was reported to "transfer" noreturn-ness to evaltree() as well. + */ +static ALWAYS_INLINE NORETURN void +evaltreenr(union node *n, int flags) +{ + evaltree(n, flags); + bb_unreachable(abort()); + /* NOTREACHED */ +} + static void FAST_FUNC evalbackcmd(union node *n, struct backcmd *result) { @@ -6173,7 +6186,7 @@ evalbackcmd(union node *n, struct backcmd *result) */ eflag = 0; ifsfree(); - evaltree(n, EV_EXIT); /* actually evaltreenr... */ + evaltreenr(n, EV_EXIT); /* NOTREACHED */ } /* parent */ @@ -8796,11 +8809,6 @@ evaltree(union node *n, int flags) return exitstatus; } -#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) -static -#endif -int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__)); - static int skiploop(void) { -- cgit v1.2.3-55-g6feb From be366e5afac1d9f5b3958bd3899a389308d5d9d3 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 27 Jul 2017 13:53:39 +0100 Subject: ash: support platforms that don't have '%m' printf specifier The '%m' conversion specifier prints an error message based on the current value of 'errno'. It is available in the GNU C library, Cygwin (since 2012), uClibc and musl. It is not available in various BSDs, BSD-derived systems (MacOS, Android) or Microsoft Windows. Use a symbol defined in platform.h to control how error messages can be formatted to display the 'errno' message. On platforms that support it use '%m'; on other platforms use '%s' and strerror(). On platforms that have '%m' there is essentially no change in the size of the binary. Otherwise: function old new delta redirect 1287 1310 +23 xtcsetpgrp 27 44 +17 dup2_or_raise 34 51 +17 setinputfile 267 275 +8 .rodata 163379 163371 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 65/-8) Total: 57 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- include/platform.h | 4 ++++ shell/ash.c | 22 +++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/platform.h b/include/platform.h index ea49c7e92..b81c59d4e 100644 --- a/include/platform.h +++ b/include/platform.h @@ -406,6 +406,7 @@ typedef unsigned smalluint; #define HAVE_MNTENT_H 1 #define HAVE_NET_ETHERNET_H 1 #define HAVE_SYS_STATFS_H 1 +#define HAVE_PRINTF_PERCENTM 1 #if defined(__UCLIBC__) # if UCLIBC_VERSION < KERNEL_VERSION(0, 9, 32) @@ -461,6 +462,7 @@ typedef unsigned smalluint; # undef HAVE_DPRINTF # undef HAVE_UNLOCKED_STDIO # undef HAVE_UNLOCKED_LINE_OPS +# undef HAVE_PRINTF_PERCENTM #endif #if defined(__dietlibc__) @@ -483,6 +485,7 @@ typedef unsigned smalluint; # undef HAVE_STRVERSCMP # undef HAVE_XTABS # undef HAVE_UNLOCKED_LINE_OPS +# undef HAVE_PRINTF_PERCENTM # include # if __FreeBSD_version < 1000029 # undef HAVE_STRCHRNUL /* FreeBSD added strchrnul() between 1000028 and 1000029 */ @@ -517,6 +520,7 @@ typedef unsigned smalluint; # undef HAVE_STRVERSCMP # undef HAVE_UNLOCKED_LINE_OPS # undef HAVE_NET_ETHERNET_H +# undef HAVE_PRINTF_PERCENTM #endif /* diff --git a/shell/ash.c b/shell/ash.c index 1f5a8dae0..f9c78ee78 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -1306,6 +1306,18 @@ ash_msg_and_raise_error(const char *msg, ...) va_end(ap); } +/* + * Use '%m' to append error string on platforms that support it, '%s' and + * strerror() on those that don't. + * + * 'fmt' must be a string literal. + */ +#ifdef HAVE_PRINTF_PERCENTM +#define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__) +#else +#define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno)) +#endif + static void raise_error_syntax(const char *) NORETURN; static void raise_error_syntax(const char *msg) @@ -3827,7 +3839,7 @@ static void xtcsetpgrp(int fd, pid_t pgrp) { if (tcsetpgrp(fd, pgrp)) - ash_msg_and_raise_error("can't set tty process group (%m)"); + ash_msg_and_raise_perror("can't set tty process group"); } /* @@ -5313,7 +5325,7 @@ savefd(int from) err = newfd < 0 ? errno : 0; if (err != EBADF) { if (err) - ash_msg_and_raise_error("%d: %m", from); + ash_msg_and_raise_perror("%d", from); close(from); fcntl(newfd, F_SETFD, FD_CLOEXEC); } @@ -5328,7 +5340,7 @@ dup2_or_raise(int from, int to) newfd = (from != to) ? dup2(from, to) : to; if (newfd < 0) { /* Happens when source fd is not open: try "echo >&99" */ - ash_msg_and_raise_error("%d: %m", from); + ash_msg_and_raise_perror("%d", from); } return newfd; } @@ -5459,7 +5471,7 @@ redirect(union node *redir, int flags) /* "echo >&10" and 10 is a fd opened to a sh script? */ if (is_hidden_fd(sv, right_fd)) { errno = EBADF; /* as if it is closed */ - ash_msg_and_raise_error("%d: %m", right_fd); + ash_msg_and_raise_perror("%d", right_fd); } newfd = -1; } else { @@ -5493,7 +5505,7 @@ redirect(union node *redir, int flags) if (newfd >= 0) close(newfd); errno = i; - ash_msg_and_raise_error("%d: %m", fd); + ash_msg_and_raise_perror("%d", fd); /* NOTREACHED */ } /* EBADF: it is not open - good, remember to close it */ -- cgit v1.2.3-55-g6feb