From f5018dac21df54647d0982ed4bebd0286d77cc56 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Apr 2018 17:58:21 +0200 Subject: hush: fix "unset PS1/PS2", and put them into initial variable set "unset PS1/PS2" causes prompts to be empty strings function old new delta hush_main 1031 1089 +58 goto_new_line 27 33 +6 fgetc_interactive 244 245 +1 unset_local_var 155 149 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/1 up/down: 65/-6) Total: 59 bytes Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 678c4d29c..d5e92e84c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -430,7 +430,8 @@ static void put_till_end_and_adv_cursor(void) static void goto_new_line(void) { put_till_end_and_adv_cursor(); - if (cmdedit_x != 0) + /* "cursor == 0" is only if prompt is "" and user input is empty */ + if (cursor == 0 || cmdedit_x != 0) bb_putchar('\n'); } -- cgit v1.2.3-55-g6feb From 2ab994f7079daa052f8816b72e215e1609d41f76 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Apr 2018 18:26:33 +0200 Subject: placate gcc-8.0.1 warnings Signed-off-by: Denys Vlasenko --- libbb/dump.c | 6 +++--- runit/sv.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'libbb') diff --git a/libbb/dump.c b/libbb/dump.c index db91fcfe7..5941ef902 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -464,11 +464,9 @@ static const char conv_str[] ALIGN1 = "\v" "\\""v""\0" ; - static void conv_c(PR *pr, unsigned char *p) { const char *str = conv_str; - char buf[10]; do { if (*p == *str) { @@ -482,7 +480,9 @@ static void conv_c(PR *pr, unsigned char *p) *pr->cchar = 'c'; printf(pr->fmt, *p); } else { - sprintf(buf, "%03o", (int) *p); + char buf[4]; + /* gcc-8.0.1 needs lots of casts to shut up */ + sprintf(buf, "%03o", (unsigned)(uint8_t)*p); str = buf; strpr: *pr->cchar = 's'; diff --git a/runit/sv.c b/runit/sv.c index 86d181872..8054daedf 100644 --- a/runit/sv.c +++ b/runit/sv.c @@ -222,6 +222,7 @@ struct globals { #define str_equal(s,t) (strcmp((s), (t)) == 0) +#if ENABLE_SV || ENABLE_SVC static void fatal_cannot(const char *m1) NORETURN; static void fatal_cannot(const char *m1) { @@ -688,6 +689,7 @@ static int sv(char **argv) } return rc > 99 ? 99 : rc; } +#endif #if ENABLE_SV int sv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -- cgit v1.2.3-55-g6feb From 2f094ae82106e91cb210e79ddc2e5285377b549e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Apr 2018 15:02:20 +0200 Subject: telnet: move winsize detection closer to I/O loop, delete non-functioning debug code Signed-off-by: Denys Vlasenko --- libbb/bb_askpass.c | 12 +----------- networking/telnet.c | 17 +++++------------ 2 files changed, 6 insertions(+), 23 deletions(-) (limited to 'libbb') diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c index aae35ec41..5599c82ef 100644 --- a/libbb/bb_askpass.c +++ b/libbb/bb_askpass.c @@ -37,15 +37,6 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) tcgetattr(fd, &oldtio); tio = oldtio; -#if 0 - /* Switch off UPPERCASE->lowercase conversion (never used since 198x) - * and XON/XOFF (why we want to mess with this??) - */ -# ifndef IUCLC -# define IUCLC 0 -# endif - tio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY); -#endif /* Switch off echo */ tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL); tcsetattr(fd, TCSANOW, &tio); @@ -66,9 +57,8 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) while (1) { int r = read(fd, &ret[i], 1); if ((i == 0 && r == 0) /* EOF (^D) with no password */ - || r < 0 + || r < 0 /* read is interrupted by timeout or ^C */ ) { - /* read is interrupted by timeout or ^C */ ret = NULL; break; } diff --git a/networking/telnet.c b/networking/telnet.c index 8b0df7f5c..15d6a08d8 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -89,12 +89,6 @@ # define TELOPT_NAWS 31 /* window size */ #endif -#ifdef DOTRACE -# define TRACE(x, y) do { if (x) printf y; } while (0) -#else -# define TRACE(x, y) -#endif - enum { DATABUFSIZE = 128, IACBUFSIZE = 128, @@ -627,10 +621,6 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) INIT_G(); -#if ENABLE_FEATURE_TELNET_WIDTH - get_terminal_width_height(0, &G.win_width, &G.win_height); -#endif - #if ENABLE_FEATURE_TELNET_TTYPE G.ttype = getenv("TERM"); #endif @@ -661,6 +651,11 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) setsockopt_keepalive(netfd); +#if ENABLE_FEATURE_TELNET_WIDTH + get_terminal_width_height(0, &G.win_width, &G.win_height); +//TODO: support dynamic resize? +#endif + signal(SIGINT, record_signo); ufds[0].fd = STDIN_FILENO; @@ -684,7 +679,6 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) len = safe_read(STDIN_FILENO, G.buf, DATABUFSIZE); if (len <= 0) doexit(EXIT_SUCCESS); - TRACE(0, ("Read con: %d\n", len)); handle_net_output(len); } @@ -694,7 +688,6 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) full_write1_str("Connection closed by foreign host\r\n"); doexit(EXIT_FAILURE); } - TRACE(0, ("Read netfd (%d): %d\n", netfd, len)); handle_net_input(len); } } /* while (1) */ -- cgit v1.2.3-55-g6feb From 77cb6b99a436c20bb171e6cdad7b8b8b5ce3692c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Apr 2018 15:08:12 +0200 Subject: libbb: rename bb_ask -> bb_ask_noecho, bb_ask_confirmation -> bb_ask_y_confirmation Signed-off-by: Denys Vlasenko --- coreutils/mv.c | 2 +- include/libbb.h | 8 ++++---- libbb/ask_confirmation.c | 4 ++-- libbb/bb_askpass.c | 6 +++--- libbb/copy_file.c | 2 +- libbb/correct_password.c | 2 +- libbb/remove_file.c | 6 +++--- loginutils/cryptpw.c | 2 +- loginutils/passwd.c | 10 +++++----- mailutils/mail.c | 4 ++-- miscutils/i2c_tools.c | 2 +- 11 files changed, 24 insertions(+), 24 deletions(-) (limited to 'libbb') diff --git a/coreutils/mv.c b/coreutils/mv.c index aeafd1e40..6e11197a1 100644 --- a/coreutils/mv.c +++ b/coreutils/mv.c @@ -101,7 +101,7 @@ int mv_main(int argc, char **argv) if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) { goto RET_1; /* Ouch! fprintf failed! */ } - if (!bb_ask_confirmation()) { + if (!bb_ask_y_confirmation()) { goto RET_0; } } diff --git a/include/libbb.h b/include/libbb.h index ad1c7346f..c7e830c09 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1408,11 +1408,11 @@ extern int set_loop(char **devname, const char *file, unsigned long long offset, #define BB_LO_FLAGS_READ_ONLY 1 #define BB_LO_FLAGS_AUTOCLEAR 4 -/* Like bb_ask below, but asks on stdin with no timeout. */ -char *bb_ask_stdin(const char * prompt) FAST_FUNC; +/* Like bb_ask_noecho below, but asks on stdin with no timeout. */ +char *bb_ask_noecho_stdin(const char *prompt) FAST_FUNC; //TODO: pass buf pointer or return allocated buf (avoid statics)? -char *bb_ask(const int fd, int timeout, const char * prompt) FAST_FUNC; -int bb_ask_confirmation(void) FAST_FUNC; +char *bb_ask_noecho(const int fd, int timeout, const char *prompt) FAST_FUNC; +int bb_ask_y_confirmation(void) FAST_FUNC; /* Returns -1 if input is invalid. current_mode is a base for e.g. "u+rw" */ int bb_parse_mode(const char* s, unsigned cur_mode) FAST_FUNC; diff --git a/libbb/ask_confirmation.c b/libbb/ask_confirmation.c index 6fbed89f4..ccd983c29 100644 --- a/libbb/ask_confirmation.c +++ b/libbb/ask_confirmation.c @@ -1,6 +1,6 @@ /* vi: set sw=4 ts=4: */ /* - * bb_ask_confirmation implementation for busybox + * bb_ask_y_confirmation implementation for busybox * * Copyright (C) 2003 Manuel Novoa III * @@ -11,7 +11,7 @@ /* Read a line from stdin. If the first non-whitespace char is 'y' or 'Y', * return 1. Otherwise return 0. */ -int FAST_FUNC bb_ask_confirmation(void) +int FAST_FUNC bb_ask_y_confirmation(void) { char first = 0; int c; diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c index 5599c82ef..aadc69108 100644 --- a/libbb/bb_askpass.c +++ b/libbb/bb_askpass.c @@ -13,11 +13,11 @@ static void askpass_timeout(int UNUSED_PARAM ignore) { } -char* FAST_FUNC bb_ask_stdin(const char *prompt) +char* FAST_FUNC bb_ask_noecho_stdin(const char *prompt) { - return bb_ask(STDIN_FILENO, 0, prompt); + return bb_ask_noecho(STDIN_FILENO, 0, prompt); } -char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) +char* FAST_FUNC bb_ask_noecho(const int fd, int timeout, const char *prompt) { /* Was static char[BIGNUM] */ enum { sizeof_passwd = 128 }; diff --git a/libbb/copy_file.c b/libbb/copy_file.c index be9006631..1b8befd65 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -48,7 +48,7 @@ static int ask_and_unlink(const char *dest, int flags) // (No "opening without O_EXCL", no "unlink only if -f") // Or else we will end up having 3 open()s! fprintf(stderr, "%s: overwrite '%s'? ", applet_name, dest); - if (!bb_ask_confirmation()) + if (!bb_ask_y_confirmation()) return 0; /* not allowed to overwrite */ } if (unlink(dest) < 0) { diff --git a/libbb/correct_password.c b/libbb/correct_password.c index a6f7d9b3d..cbe6cb387 100644 --- a/libbb/correct_password.c +++ b/libbb/correct_password.c @@ -106,7 +106,7 @@ int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw, if (!pw_pass[0]) /* empty password field? */ return CHECKPASS_PW_HAS_EMPTY_PASSWORD; - plaintext = bb_ask(STDIN_FILENO, timeout, prompt); + plaintext = bb_ask_noecho(STDIN_FILENO, timeout, prompt); if (!plaintext) { /* EOF (such as ^D) or error (such as ^C) or timeout */ return -1; diff --git a/libbb/remove_file.c b/libbb/remove_file.c index 8a1324393..074ffae70 100644 --- a/libbb/remove_file.c +++ b/libbb/remove_file.c @@ -41,7 +41,7 @@ int FAST_FUNC remove_file(const char *path, int flags) ) { fprintf(stderr, "%s: descend into directory '%s'? ", applet_name, path); - if (!bb_ask_confirmation()) + if (!bb_ask_y_confirmation()) return 0; } @@ -68,7 +68,7 @@ int FAST_FUNC remove_file(const char *path, int flags) if (flags & FILEUTILS_INTERACTIVE) { fprintf(stderr, "%s: remove directory '%s'? ", applet_name, path); - if (!bb_ask_confirmation()) + if (!bb_ask_y_confirmation()) return status; } @@ -92,7 +92,7 @@ int FAST_FUNC remove_file(const char *path, int flags) || (flags & FILEUTILS_INTERACTIVE) ) { fprintf(stderr, "%s: remove '%s'? ", applet_name, path); - if (!bb_ask_confirmation()) + if (!bb_ask_y_confirmation()) return 0; } diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index 76138a61f..3ca7eda4a 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c @@ -134,7 +134,7 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv) /* Only mkpasswd, and only from tty, prompts. * Otherwise it is a plain read. */ password = (ENABLE_MKPASSWD && isatty(STDIN_FILENO) && applet_name[0] == 'm') - ? bb_ask_stdin("Password: ") + ? bb_ask_noecho_stdin("Password: ") : xmalloc_fgetline(stdin) ; /* may still be NULL on EOF/error */ diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 3e1ef9abf..02303b575 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c @@ -52,7 +52,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo if (myuid != 0 && pw->pw_passwd[0]) { char *encrypted; - orig = bb_ask_stdin("Old password: "); /* returns ptr to static */ + orig = bb_ask_noecho_stdin("Old password: "); /* returns ptr to static */ if (!orig) goto err_ret; encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */ @@ -65,11 +65,11 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo if (ENABLE_FEATURE_CLEAN_UP) free(encrypted); } - orig = xstrdup(orig); /* or else bb_ask_stdin() will destroy it */ - newp = bb_ask_stdin("New password: "); /* returns ptr to static */ + orig = xstrdup(orig); /* or else bb_ask_noecho_stdin() will destroy it */ + newp = bb_ask_noecho_stdin("New password: "); /* returns ptr to static */ if (!newp) goto err_ret; - newp = xstrdup(newp); /* we are going to bb_ask_stdin() again, so save it */ + newp = xstrdup(newp); /* we are going to bb_ask_noecho_stdin() again, so save it */ if (ENABLE_FEATURE_PASSWD_WEAK_CHECK && obscure(orig, newp, pw) && myuid != 0 @@ -77,7 +77,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo goto err_ret; /* non-root is not allowed to have weak passwd */ } - cp = bb_ask_stdin("Retype password: "); + cp = bb_ask_noecho_stdin("Retype password: "); if (!cp) goto err_ret; if (strcmp(cp, newp) != 0) { diff --git a/mailutils/mail.c b/mailutils/mail.c index eceb89071..0fc615a7f 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c @@ -163,8 +163,8 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol) void FAST_FUNC get_cred_or_die(int fd) { if (isatty(fd)) { - G.user = xstrdup(bb_ask(fd, /* timeout: */ 0, "User: ")); - G.pass = xstrdup(bb_ask(fd, /* timeout: */ 0, "Password: ")); + G.user = xstrdup(bb_ask_noecho(fd, /* timeout: */ 0, "User: ")); + G.pass = xstrdup(bb_ask_noecho(fd, /* timeout: */ 0, "Password: ")); } else { G.user = xmalloc_reads(fd, /* maxsize: */ NULL); G.pass = xmalloc_reads(fd, /* maxsize: */ NULL); diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 82f9842bd..8b201c0b1 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -422,7 +422,7 @@ static void confirm_or_abort(void) { fprintf(stderr, "Continue? [y/N] "); fflush_all(); - if (!bb_ask_confirmation()) + if (!bb_ask_y_confirmation()) bb_error_msg_and_die("aborting"); } -- cgit v1.2.3-55-g6feb From bae8fc4436f9aeb43ef0aaccd1c9b1b35b5a4617 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Apr 2018 15:21:35 +0200 Subject: xargs: use bb_ask_y_confirmation_FILE() instead of homegrown copy function old new delta bb_ask_y_confirmation_FILE - 83 +83 inetd_main 2033 2043 +10 udhcp_send_kernel_packet 295 301 +6 rmescapes 306 310 +4 send_tree 353 355 +2 i2cdetect_main 674 672 -2 confirm_or_abort 43 38 -5 get_terminal_width_height 242 234 -8 bb_ask_y_confirmation 76 10 -66 xargs_main 823 755 -68 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/5 up/down: 105/-149) Total: -44 bytes Signed-off-by: Denys Vlasenko --- findutils/xargs.c | 12 ++++++------ include/libbb.h | 1 + libbb/ask_confirmation.c | 12 +++++++++--- libbb/remove_file.c | 7 ++++--- miscutils/i2c_tools.c | 1 - 5 files changed, 20 insertions(+), 13 deletions(-) (limited to 'libbb') diff --git a/findutils/xargs.c b/findutils/xargs.c index 117a39b62..1d85d50e8 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -496,16 +496,16 @@ static char* FAST_FUNC process_stdin_with_replace(int n_max_chars, int n_max_arg static int xargs_ask_confirmation(void) { FILE *tty_stream; - int c, savec; + int r; tty_stream = xfopen_for_read(CURRENT_TTY); + fputs(" ?...", stderr); - fflush_all(); - c = savec = getc(tty_stream); - while (c != EOF && c != '\n') - c = getc(tty_stream); + r = bb_ask_y_confirmation_FILE(tty_stream); + fclose(tty_stream); - return (savec == 'y' || savec == 'Y'); + + return r; } #else # define xargs_ask_confirmation() 1 diff --git a/include/libbb.h b/include/libbb.h index c7e830c09..5388d9d95 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1412,6 +1412,7 @@ extern int set_loop(char **devname, const char *file, unsigned long long offset, char *bb_ask_noecho_stdin(const char *prompt) FAST_FUNC; //TODO: pass buf pointer or return allocated buf (avoid statics)? char *bb_ask_noecho(const int fd, int timeout, const char *prompt) FAST_FUNC; +int bb_ask_y_confirmation_FILE(FILE *fp) FAST_FUNC; int bb_ask_y_confirmation(void) FAST_FUNC; /* Returns -1 if input is invalid. current_mode is a base for e.g. "u+rw" */ diff --git a/libbb/ask_confirmation.c b/libbb/ask_confirmation.c index ccd983c29..e4814e215 100644 --- a/libbb/ask_confirmation.c +++ b/libbb/ask_confirmation.c @@ -8,15 +8,16 @@ */ #include "libbb.h" -/* Read a line from stdin. If the first non-whitespace char is 'y' or 'Y', +/* Read a line from fp. If the first non-whitespace char is 'y' or 'Y', * return 1. Otherwise return 0. */ -int FAST_FUNC bb_ask_y_confirmation(void) +int FAST_FUNC bb_ask_y_confirmation_FILE(FILE *fp) { char first = 0; int c; - while (((c = getchar()) != EOF) && (c != '\n')) { + fflush_all(); + while (((c = fgetc(fp)) != EOF) && (c != '\n')) { if (first == 0 && !isblank(c)) { first = c|0x20; } @@ -24,3 +25,8 @@ int FAST_FUNC bb_ask_y_confirmation(void) return first == 'y'; } + +int FAST_FUNC bb_ask_y_confirmation(void) +{ + return bb_ask_y_confirmation_FILE(stdin); +} diff --git a/libbb/remove_file.c b/libbb/remove_file.c index 074ffae70..86c9a5c56 100644 --- a/libbb/remove_file.c +++ b/libbb/remove_file.c @@ -39,8 +39,8 @@ int FAST_FUNC remove_file(const char *path, int flags) if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 && isatty(0)) || (flags & FILEUTILS_INTERACTIVE) ) { - fprintf(stderr, "%s: descend into directory '%s'? ", applet_name, - path); + fprintf(stderr, "%s: descend into directory '%s'? ", + applet_name, path); if (!bb_ask_y_confirmation()) return 0; } @@ -67,7 +67,8 @@ int FAST_FUNC remove_file(const char *path, int flags) } if (flags & FILEUTILS_INTERACTIVE) { - fprintf(stderr, "%s: remove directory '%s'? ", applet_name, path); + fprintf(stderr, "%s: remove directory '%s'? ", + applet_name, path); if (!bb_ask_y_confirmation()) return status; } diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 8b201c0b1..6a2134063 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -421,7 +421,6 @@ static void check_write_funcs(int fd, int mode, int pec) static void confirm_or_abort(void) { fprintf(stderr, "Continue? [y/N] "); - fflush_all(); if (!bb_ask_y_confirmation()) bb_error_msg_and_die("aborting"); } -- cgit v1.2.3-55-g6feb From 17058a06c4333fc0c492c168c8a971ebd0fd5a5a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Apr 2018 15:50:30 +0200 Subject: libbb: switch bb_ask_noecho() to "mallocing" string return API function old new delta bb_ask_noecho 313 330 +17 get_cred_or_die 125 115 -10 passwd_main 995 958 -37 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 17/-47) Total: -30 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 7 ++++--- libbb/bb_askpass.c | 45 +++++++++++++++++++++++++++++++-------------- loginutils/cryptpw.c | 2 +- loginutils/passwd.c | 3 +-- mailutils/mail.c | 4 ++-- 5 files changed, 39 insertions(+), 22 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index 5388d9d95..ed9a562ff 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1408,10 +1408,11 @@ extern int set_loop(char **devname, const char *file, unsigned long long offset, #define BB_LO_FLAGS_READ_ONLY 1 #define BB_LO_FLAGS_AUTOCLEAR 4 -/* Like bb_ask_noecho below, but asks on stdin with no timeout. */ +/* Returns malloced str */ +char *bb_ask_noecho(int fd, int timeout, const char *prompt) FAST_FUNC; +/* Like bb_ask_noecho, but asks on stdin with no timeout. */ char *bb_ask_noecho_stdin(const char *prompt) FAST_FUNC; -//TODO: pass buf pointer or return allocated buf (avoid statics)? -char *bb_ask_noecho(const int fd, int timeout, const char *prompt) FAST_FUNC; + int bb_ask_y_confirmation_FILE(FILE *fp) FAST_FUNC; int bb_ask_y_confirmation(void) FAST_FUNC; diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c index aadc69108..2dcead35a 100644 --- a/libbb/bb_askpass.c +++ b/libbb/bb_askpass.c @@ -13,16 +13,9 @@ static void askpass_timeout(int UNUSED_PARAM ignore) { } -char* FAST_FUNC bb_ask_noecho_stdin(const char *prompt) -{ - return bb_ask_noecho(STDIN_FILENO, 0, prompt); -} -char* FAST_FUNC bb_ask_noecho(const int fd, int timeout, const char *prompt) +char* FAST_FUNC bb_ask_noecho(int fd, int timeout, const char *prompt) { - /* Was static char[BIGNUM] */ - enum { sizeof_passwd = 128 }; - - char *passwd; +#define MAX_LINE 0xfff char *ret; int i; struct sigaction sa, oldsa; @@ -37,7 +30,17 @@ char* FAST_FUNC bb_ask_noecho(const int fd, int timeout, const char *prompt) tcgetattr(fd, &oldtio); tio = oldtio; - /* Switch off echo */ + /* Switch off echo. ECHOxyz meaning: + * ECHO echo input chars + * ECHOE echo BS-SP-BS on erase character + * ECHOK echo kill char specially, not as ^c (ECHOKE controls how exactly) + * ECHOKE erase all input via BS-SP-BS on kill char (else go to next line) + * ECHOCTL Echo ctrl chars as ^c (else echo verbatim: + * e.g. up arrow emits "ESC-something" and thus moves cursor up!) + * ECHONL Echo NL even if ECHO is not set + * ECHOPRT On erase, echo erased chars + * [qwe input looks like "qwe\ewq/" on screen] + */ tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL); tcsetattr(fd, TCSANOW, &tio); @@ -51,20 +54,30 @@ char* FAST_FUNC bb_ask_noecho(const int fd, int timeout, const char *prompt) alarm(timeout); } - passwd = auto_string(xmalloc(sizeof_passwd)); - ret = passwd; + ret = NULL; i = 0; while (1) { - int r = read(fd, &ret[i], 1); + int r; + + /* User input is uber-slow, no need to optimize reallocs. + * Grow it on every char. + */ + ret = xrealloc(ret, i + 2); + r = read(fd, &ret[i], 1); + if ((i == 0 && r == 0) /* EOF (^D) with no password */ || r < 0 /* read is interrupted by timeout or ^C */ ) { + ret[i] = '\0'; /* paranoia */ + nuke_str(ret); /* paranoia */ + free(ret); ret = NULL; break; } + if (r == 0 /* EOF */ || ret[i] == '\r' || ret[i] == '\n' /* EOL */ - || ++i == sizeof_passwd-1 /* line limit */ + || ++i == MAX_LINE /* line limit */ ) { ret[i] = '\0'; break; @@ -80,3 +93,7 @@ char* FAST_FUNC bb_ask_noecho(const int fd, int timeout, const char *prompt) fflush_all(); return ret; } +char* FAST_FUNC bb_ask_noecho_stdin(const char *prompt) +{ + return bb_ask_noecho(STDIN_FILENO, 0, prompt); +} diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index 3ca7eda4a..fbb7f0515 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c @@ -133,7 +133,7 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv) if (!password) { /* Only mkpasswd, and only from tty, prompts. * Otherwise it is a plain read. */ - password = (ENABLE_MKPASSWD && isatty(STDIN_FILENO) && applet_name[0] == 'm') + password = (ENABLE_MKPASSWD && applet_name[0] == 'm' && isatty(STDIN_FILENO)) ? bb_ask_noecho_stdin("Password: ") : xmalloc_fgetline(stdin) ; diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 02303b575..d0408d8b4 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c @@ -65,11 +65,9 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo if (ENABLE_FEATURE_CLEAN_UP) free(encrypted); } - orig = xstrdup(orig); /* or else bb_ask_noecho_stdin() will destroy it */ newp = bb_ask_noecho_stdin("New password: "); /* returns ptr to static */ if (!newp) goto err_ret; - newp = xstrdup(newp); /* we are going to bb_ask_noecho_stdin() again, so save it */ if (ENABLE_FEATURE_PASSWD_WEAK_CHECK && obscure(orig, newp, pw) && myuid != 0 @@ -99,6 +97,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo if (ENABLE_FEATURE_CLEAN_UP) free(newp); nuke_str(cp); + if (ENABLE_FEATURE_CLEAN_UP) free(cp); return ret; } diff --git a/mailutils/mail.c b/mailutils/mail.c index 0fc615a7f..7af7edd6c 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c @@ -163,8 +163,8 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol) void FAST_FUNC get_cred_or_die(int fd) { if (isatty(fd)) { - G.user = xstrdup(bb_ask_noecho(fd, /* timeout: */ 0, "User: ")); - G.pass = xstrdup(bb_ask_noecho(fd, /* timeout: */ 0, "Password: ")); + G.user = bb_ask_noecho(fd, /* timeout: */ 0, "User: "); + G.pass = bb_ask_noecho(fd, /* timeout: */ 0, "Password: "); } else { G.user = xmalloc_reads(fd, /* maxsize: */ NULL); G.pass = xmalloc_reads(fd, /* maxsize: */ NULL); -- cgit v1.2.3-55-g6feb From 38ccd6af8abbafff98d458a1c62909acfc09a514 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Apr 2018 20:02:01 +0200 Subject: bzip2: fix two crashes on corrupted archives As it turns out, longjmp'ing into freed stack is not healthy... function old new delta unpack_usage_messages - 97 +97 unpack_bz2_stream 369 409 +40 get_next_block 1667 1677 +10 get_bits 156 155 -1 start_bunzip 212 183 -29 bb_show_usage 181 120 -61 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/3 up/down: 147/-91) Total: 56 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_bunzip2.c | 78 ++++++++++++++++++++++--------- archival/libarchive/decompress_gunzip.c | 1 - coreutils/test.c | 1 - include/bb_archive.h | 2 +- libbb/appletlib.c | 17 +++++-- miscutils/bbconfig.c | 19 ++++++-- shell/ash.c | 1 - testsuite/bunzip2.tests | 16 +++++++ testsuite/bz2_issue_11.bz2 | Bin 0 -> 12000 bytes testsuite/bz2_issue_12.bz2 | Bin 0 -> 11000 bytes 10 files changed, 99 insertions(+), 36 deletions(-) create mode 100644 testsuite/bz2_issue_11.bz2 create mode 100644 testsuite/bz2_issue_12.bz2 (limited to 'libbb') diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index bec89edd3..7ef4e035f 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c @@ -100,7 +100,7 @@ struct bunzip_data { unsigned dbufSize; /* For I/O error handling */ - jmp_buf jmpbuf; + jmp_buf *jmpbuf; /* Big things go last (register-relative addressing can be larger for big offsets) */ uint32_t crc32Table[256]; @@ -127,7 +127,7 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted) /* if "no input fd" case: in_fd == -1, read fails, we jump */ bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE); if (bd->inbufCount <= 0) - longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF); + longjmp(*bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF); bd->inbufPos = 0; } @@ -151,12 +151,12 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted) 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. */ static int get_next_block(bunzip_data *bd) { - struct group_data *hufGroup; - int groupCount, *base, *limit, selector, + int groupCount, selector, i, j, symCount, symTotal, nSelectors, byteCount[256]; uint8_t uc, symToByte[256], mtfSymbol[256], *selectors; uint32_t *dbuf; @@ -179,15 +179,19 @@ static int get_next_block(bunzip_data *bd) i = get_bits(bd, 24); j = get_bits(bd, 24); bd->headerCRC = get_bits(bd, 32); - if ((i == 0x177245) && (j == 0x385090)) return RETVAL_LAST_BLOCK; - if ((i != 0x314159) || (j != 0x265359)) return RETVAL_NOT_BZIP_DATA; + if ((i == 0x177245) && (j == 0x385090)) + 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 some code for this in busybox 1.0.0-pre3, but nobody ever noticed that 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); - if (origPtr > bd->dbufSize) return RETVAL_DATA_ERROR; + if (origPtr > bd->dbufSize) + return RETVAL_DATA_ERROR; /* mapping table: if some byte values are never used (encoding things like ascii text), the compression code removes the gaps to have fewer @@ -231,13 +235,21 @@ static int get_next_block(bunzip_data *bd) /* Get next value */ int n = 0; while (get_bits(bd, 1)) { - if (n >= groupCount) return RETVAL_DATA_ERROR; + if (n >= groupCount) + return RETVAL_DATA_ERROR; n++; } /* Decode MTF to get the next selector */ tmp_byte = mtfSymbol[n]; while (--n >= 0) mtfSymbol[n + 1] = mtfSymbol[n]; +//We catch it later, in the second loop where we use selectors[i]. +//Maybe this is a better place, though? +// if (tmp_byte >= groupCount) { +// dbg("%d: selectors[%d]:%d groupCount:%d", +// __LINE__, i, tmp_byte, groupCount); +// return RETVAL_DATA_ERROR; +// } mtfSymbol[0] = selectors[i] = tmp_byte; } @@ -248,6 +260,8 @@ static int get_next_block(bunzip_data *bd) uint8_t length[MAX_SYMBOLS]; /* 8 bits is ALMOST enough for temp[], see below */ unsigned temp[MAX_HUFCODE_BITS+1]; + struct group_data *hufGroup; + int *base, *limit; int minLen, maxLen, pp, len_m1; /* Read Huffman code lengths for each symbol. They're stored in @@ -283,8 +297,10 @@ static int get_next_block(bunzip_data *bd) /* Find largest and smallest lengths in this group */ minLen = maxLen = length[0]; for (i = 1; i < symCount; i++) { - if (length[i] > maxLen) maxLen = length[i]; - else if (length[i] < minLen) minLen = length[i]; + if (length[i] > maxLen) + maxLen = length[i]; + else if (length[i] < minLen) + minLen = length[i]; } /* Calculate permute[], base[], and limit[] tables from length[]. @@ -320,7 +336,8 @@ static int get_next_block(bunzip_data *bd) /* Count symbols coded for at each bit length */ /* NB: in pathological cases, temp[8] can end ip being 256. * 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 * length, which is (previous limit<<1)+symbols at this level), and @@ -363,12 +380,22 @@ static int get_next_block(bunzip_data *bd) runPos = dbufCount = selector = 0; for (;;) { + struct group_data *hufGroup; + int *base, *limit; int nextSym; + uint8_t ngrp; /* Fetch next Huffman coding group from list. */ symCount = GROUP_SIZE - 1; - if (selector >= nSelectors) return RETVAL_DATA_ERROR; - hufGroup = bd->groups + selectors[selector++]; + if (selector >= nSelectors) + 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; limit = hufGroup->limit - 1; @@ -403,7 +430,8 @@ static int get_next_block(bunzip_data *bd) } /* Figure how many bits are in next symbol and unget extras */ i = hufGroup->minLen; - while (nextSym > limit[i]) ++i; + while (nextSym > limit[i]) + ++i; j = hufGroup->maxLen - i; if (j < 0) return RETVAL_DATA_ERROR; @@ -671,7 +699,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() should work for NOFORK applets too, we must be extremely careful to not leak any allocations! */ -int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, +int FAST_FUNC start_bunzip( + void *jmpbuf, + bunzip_data **bdp, + int in_fd, const void *inbuf, int len) { bunzip_data *bd; @@ -683,11 +714,14 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, /* Figure out how much data to allocate */ 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. */ bd = *bdp = xzalloc(i); + bd->jmpbuf = jmpbuf; + /* Setup input buffer */ bd->in_fd = in_fd; if (-1 == in_fd) { @@ -702,10 +736,6 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, /* Init the CRC32 table (big endian) */ 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']." */ /* Update: now caller verifies 1st two bytes, makes .gz/.bz2 * integration easier */ @@ -752,8 +782,12 @@ unpack_bz2_stream(transformer_state_t *xstate) outbuf = xmalloc(IOBUF_SIZE); len = 0; 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) { while (1) { /* "Produce some output bytes" loop */ diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 9a58d10d4..7f9046b82 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c @@ -32,7 +32,6 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -#include #include "libbb.h" #include "bb_archive.h" diff --git a/coreutils/test.c b/coreutils/test.c index a8286525a..824ce3b5a 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -76,7 +76,6 @@ //usage: "1\n" #include "libbb.h" -#include /* This is a NOFORK applet. Be very careful! */ diff --git a/include/bb_archive.h b/include/bb_archive.h index a5c61e95b..b437f1920 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -210,7 +210,7 @@ const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_ /* A bit of bunzip2 internals are exposed for compressed help support: */ typedef struct bunzip_data bunzip_data; -int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; +int start_bunzip(void *, 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; diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 022455da4..769b7881c 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -102,14 +102,21 @@ static const char *unpack_usage_messages(void) char *outbuf = NULL; bunzip_data *bd; int i; + jmp_buf jmpbuf; - i = start_bunzip(&bd, + /* Setup for I/O error handling via longjmp */ + i = setjmp(jmpbuf); + if (i == 0) { + i = start_bunzip(&jmpbuf, + &bd, /* src_fd: */ -1, /* inbuf: */ packed_usage, - /* len: */ sizeof(packed_usage)); - /* read_bunzip can longjmp to start_bunzip, and ultimately - * end up here with i != 0 on read data errors! Not trivial */ - if (!i) { + /* len: */ sizeof(packed_usage) + ); + } + /* 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(sizeof(UNPACKED_USAGE)); if (outbuf) diff --git a/miscutils/bbconfig.c b/miscutils/bbconfig.c index 9ab57876e..501349548 100644 --- a/miscutils/bbconfig.c +++ b/miscutils/bbconfig.c @@ -44,13 +44,22 @@ int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { #if ENABLE_FEATURE_COMPRESS_BBCONFIG bunzip_data *bd; - int i = start_bunzip(&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: */ bbconfig_config_bz2, - /* len: */ sizeof(bbconfig_config_bz2)); - /* read_bunzip can longjmp to start_bunzip, and ultimately - * end up here with i != 0 on read data errors! Not trivial */ - if (!i) { + /* len: */ sizeof(bbconfig_config_bz2) + ); + } + /* 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! */ char *outbuf = malloc_or_warn(sizeof(bbconfig_config)); if (outbuf) { diff --git a/shell/ash.c b/shell/ash.c index 56fba4a57..24958c0fc 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -177,7 +177,6 @@ #define JOBS ENABLE_ASH_JOB_CONTROL -#include #include #include #include /* for setting $HOSTNAME */ diff --git a/testsuite/bunzip2.tests b/testsuite/bunzip2.tests index fcfce1a31..edb332748 100755 --- a/testsuite/bunzip2.tests +++ b/testsuite/bunzip2.tests @@ -552,6 +552,22 @@ if test "${0##*/}" = "bunzip2.tests"; then echo "FAIL: $unpack: pbzip_4m_zeros file" FAILCOUNT=$((FAILCOUNT + 1)) fi + + errout="`${bb}bunzip2 &1 >/dev/null`" + if test x"$errout:$?" = x"bunzip2: bunzip error -5:1"; then + echo "PASS: $unpack: bz2_issue_11.bz2 corrupted example" + else + echo "FAIL: $unpack: bz2_issue_11.bz2 corrupted example" + FAILCOUNT=$((FAILCOUNT + 1)) + fi + + errout="`${bb}bunzip2 &1 >/dev/null`" + if test x"$errout:$?" = x"bunzip2: bunzip error -3:1"; then + echo "PASS: $unpack: bz2_issue_12.bz2 corrupted example" + else + echo "FAIL: $unpack: bz2_issue_12.bz2 corrupted example" + FAILCOUNT=$((FAILCOUNT + 1)) + fi fi exit $((FAILCOUNT <= 255 ? FAILCOUNT : 255)) diff --git a/testsuite/bz2_issue_11.bz2 b/testsuite/bz2_issue_11.bz2 new file mode 100644 index 000000000..62b252046 Binary files /dev/null and b/testsuite/bz2_issue_11.bz2 differ diff --git a/testsuite/bz2_issue_12.bz2 b/testsuite/bz2_issue_12.bz2 new file mode 100644 index 000000000..4215f08d6 Binary files /dev/null and b/testsuite/bz2_issue_12.bz2 differ -- cgit v1.2.3-55-g6feb