From 75a1c87357070ec0229f1c98d887bc1c526bb81c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 28 Nov 2018 12:16:29 +0100 Subject: awk: abort if NF set to negative value Signed-off-by: Denys Vlasenko --- editors/awk.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/editors/awk.c b/editors/awk.c index bafc9ba1d..af103e3cc 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -1849,6 +1849,8 @@ static void handle_special(var *v) if (v == intvar[NF]) { n = (int)getvar_i(v); + if (n < 0) + syntax_error("NF set to negative value"); fsrealloc(n); /* recalculate $0 */ -- cgit v1.2.3-55-g6feb From c1005355718055983912ebdd79357b11894e0958 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Nov 2018 11:44:10 +0100 Subject: cat,nl: fix handling of open errors $ cat -n does_not_exist; echo $? cat: does_not_exist: No such file or directory 1 function old new delta print_numbered_lines 118 129 +11 nl_main 196 201 +5 cat_main 421 425 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 20/0) Total: 20 bytes Signed-off-by: Denys Vlasenko --- coreutils/cat.c | 6 ++++-- coreutils/nl.c | 7 +++++-- include/libbb.h | 2 +- libbb/print_numbered_lines.c | 10 ++++++++-- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/coreutils/cat.c b/coreutils/cat.c index fb735f994..65f0648f9 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -195,6 +195,7 @@ int cat_main(int argc UNUSED_PARAM, char **argv) # define CAT_OPT_b (1<<1) if (opts & (CAT_OPT_n|CAT_OPT_b)) { /* -n or -b */ struct number_state ns; + int exitcode; ns.width = 6; ns.start = 1; @@ -203,10 +204,11 @@ int cat_main(int argc UNUSED_PARAM, char **argv) ns.empty_str = "\n"; ns.all = !(opts & CAT_OPT_b); /* -n without -b */ ns.nonempty = (opts & CAT_OPT_b); /* -b (with or without -n) */ + exitcode = EXIT_SUCCESS; do { - print_numbered_lines(&ns, *argv); + exitcode |= print_numbered_lines(&ns, *argv); } while (*++argv); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit(exitcode); } /*opts >>= 2;*/ #endif diff --git a/coreutils/nl.c b/coreutils/nl.c index c2f8b1042..2fdc9d85e 100644 --- a/coreutils/nl.c +++ b/coreutils/nl.c @@ -58,6 +58,8 @@ int nl_main(int argc UNUSED_PARAM, char **argv) "number-width\0" Required_argument "w" ; #endif + int exitcode; + ns.width = 6; ns.start = 1; ns.inc = 1; @@ -72,9 +74,10 @@ int nl_main(int argc UNUSED_PARAM, char **argv) if (!*argv) *--argv = (char*)"-"; + exitcode = EXIT_SUCCESS; do { - print_numbered_lines(&ns, *argv); + exitcode |= print_numbered_lines(&ns, *argv); } while (*++argv); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit(exitcode); } diff --git a/include/libbb.h b/include/libbb.h index b560cc2eb..df3c2d3c9 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1386,7 +1386,7 @@ struct number_state { const char *empty_str; smallint all, nonempty; }; -void print_numbered_lines(struct number_state *ns, const char *filename) FAST_FUNC; +int print_numbered_lines(struct number_state *ns, const char *filename) FAST_FUNC; /* Networking */ diff --git a/libbb/print_numbered_lines.c b/libbb/print_numbered_lines.c index 9a8a51440..d6459d7c3 100644 --- a/libbb/print_numbered_lines.c +++ b/libbb/print_numbered_lines.c @@ -8,12 +8,16 @@ #include "libbb.h" -void FAST_FUNC print_numbered_lines(struct number_state *ns, const char *filename) +int FAST_FUNC print_numbered_lines(struct number_state *ns, const char *filename) { FILE *fp = fopen_or_warn_stdin(filename); - unsigned N = ns->start; + unsigned N; char *line; + if (!fp) + return EXIT_FAILURE; + + N = ns->start; while ((line = xmalloc_fgetline(fp)) != NULL) { if (ns->all || (ns->nonempty && line[0]) @@ -27,4 +31,6 @@ void FAST_FUNC print_numbered_lines(struct number_state *ns, const char *filenam ns->start = N; fclose(fp); + + return EXIT_SUCCESS; } -- cgit v1.2.3-55-g6feb From 480c7e5dfbddafa763f241aecfe3831d2b3dfca5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Nov 2018 12:34:50 +0100 Subject: libbb: @ in "\x3@" is not a valid hex digit function old new delta bb_process_escape_sequence 134 141 +7 Signed-off-by: Denys Vlasenko --- libbb/process_escape_sequence.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libbb/process_escape_sequence.c b/libbb/process_escape_sequence.c index 59d0d3ea8..11adbfcea 100644 --- a/libbb/process_escape_sequence.c +++ b/libbb/process_escape_sequence.c @@ -41,8 +41,16 @@ char FAST_FUNC bb_process_escape_sequence(const char **ptr) unsigned d = (unsigned char)(*q) - '0'; #else unsigned d = (unsigned char)_tolower(*q) - '0'; - if (d >= 10) - d += ('0' - 'a' + 10); + if (d >= 10) { + //d += ('0' - 'a' + 10); + /* The above would maps 'A'-'F' and 'a'-'f' to 10-15, + * however, some chars like '@' would map to 9 < base. + * Do not allow that, map invalid chars to N > base: + */ + d += ('0' - 'a'); + if ((int)d >= 0) + d += 10; + } #endif if (d >= base) { if (WANT_HEX_ESCAPES && base == 16) { -- cgit v1.2.3-55-g6feb From 9a2b6dcc2d3298499b88aea3b04c967f2f9ae965 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Nov 2018 13:15:57 +0100 Subject: libbb: do not misinterpret 0x10-0x19 chars in "\xNNN" too function old new delta bb_process_escape_sequence 141 151 +10 Signed-off-by: Denys Vlasenko --- libbb/process_escape_sequence.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libbb/process_escape_sequence.c b/libbb/process_escape_sequence.c index 11adbfcea..13022b83e 100644 --- a/libbb/process_escape_sequence.c +++ b/libbb/process_escape_sequence.c @@ -37,17 +37,15 @@ char FAST_FUNC bb_process_escape_sequence(const char **ptr) * We treat \2 as a valid octal escape sequence. */ do { unsigned r; -#if !WANT_HEX_ESCAPES unsigned d = (unsigned char)(*q) - '0'; -#else - unsigned d = (unsigned char)_tolower(*q) - '0'; +#if WANT_HEX_ESCAPES if (d >= 10) { - //d += ('0' - 'a' + 10); - /* The above would maps 'A'-'F' and 'a'-'f' to 10-15, + d = (unsigned char)_tolower(*q) - 'a'; + //d += 10; + /* The above would map 'A'-'F' and 'a'-'f' to 10-15, * however, some chars like '@' would map to 9 < base. * Do not allow that, map invalid chars to N > base: */ - d += ('0' - 'a'); if ((int)d >= 0) d += 10; } -- cgit v1.2.3-55-g6feb From 836d0a7ee450893e7479b5f93a501454582955a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Nov 2018 14:19:57 +0100 Subject: vi: fix FEATURE_VI_REGEX_SEARCH to respect LIMITED (one-line) search If busybox is compiled with FEATURE_VI_REGEX_SEARCH enabled, command ":s/x/y/" searches not only in the current line, but continues search after it. This makes range searches (":1,3s/x/y/") work incorrect. For example file "./test": 1 2 3 $ vi ./test :1,2s/3/e/ gives us: 1 2 e function old new delta char_search 213 241 +28 Signed-off-by: Denys Vlasenko --- editors/vi.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index 2aa0ad9dd..bff47250d 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -255,8 +255,8 @@ enum { YANKDEL = TRUE, FORWARD = 1, // code depends on "1" for array index BACK = -1, // code depends on "-1" for array index - LIMITED = 0, // how much of text[] in char_search - FULL = 1, // how much of text[] in char_search + LIMITED = 0, // char_search() only current line + FULL = 1, // char_search() to the end/beginning of entire text S_BEFORE_WS = 1, // used in skip_thing() for moving "dot" S_TO_WS = 2, // used in skip_thing() for moving "dot" @@ -1914,10 +1914,15 @@ static char *char_search(char *p, const char *pat, int dir, int range) return p; } - // assume a LIMITED forward search - q = end - 1; - if (dir == BACK) + q = end - 1; // if FULL + if (range == LIMITED) + q = next_line(p); + if (dir == BACK) { q = text; + if (range == LIMITED) + q = prev_line(p); + } + // RANGE could be negative if we are searching backwards range = q - p; q = p; -- cgit v1.2.3-55-g6feb From b7330460693f12585c7a6246f0dfafd8742af05a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Nov 2018 14:39:52 +0100 Subject: vi: code shrink function old new delta char_search 241 247 +6 get_one_address 275 272 -3 colon 2878 2875 -3 do_cmd 4726 4720 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 6/-12) Total: -6 bytes Signed-off-by: Denys Vlasenko --- editors/vi.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index bff47250d..ee3c7feb2 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -561,7 +561,7 @@ static void indicate_error(void); // use flash or beep to indicate error static void Hit_Return(void); #if ENABLE_FEATURE_VI_SEARCH -static char *char_search(char *, const char *, int, int); // search for pattern starting at p +static char *char_search(char *, const char *, int); // search for pattern starting at p #endif #if ENABLE_FEATURE_VI_COLON static char *get_one_address(char *, int *); // get colon addr, if present @@ -938,7 +938,7 @@ static char *get_one_address(char *p, int *addr) // get colon addr, if present p = q; if (*p == '/') p++; - q = char_search(dot, pat, FORWARD, FULL); + q = char_search(dot, pat, (FORWARD << 1) | FULL); if (q != NULL) { *addr = count_lines(text, q); } @@ -1442,7 +1442,7 @@ static void colon(char *buf) char *ls = q; // orig line start char *found; vc4: - found = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find" + found = char_search(q, F, (FORWARD << 1) | LIMITED); // search cur line only for "find" if (found) { uintptr_t bias; // we found the "find" pattern - delete it @@ -1895,13 +1895,14 @@ static char *new_screen(int ro, int co) # if ENABLE_FEATURE_VI_REGEX_SEARCH // search for pattern starting at p -static char *char_search(char *p, const char *pat, int dir, int range) +static char *char_search(char *p, const char *pat, int dir_and_range) { struct re_pattern_buffer preg; const char *err; char *q; int i; int size; + int range; re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; if (ignorecase) @@ -1914,10 +1915,11 @@ static char *char_search(char *p, const char *pat, int dir, int range) return p; } + range = (dir_and_range & 1); q = end - 1; // if FULL if (range == LIMITED) q = next_line(p); - if (dir == BACK) { + if (dir_and_range < 0) { // BACK? q = text; if (range == LIMITED) q = prev_line(p); @@ -1945,7 +1947,7 @@ static char *char_search(char *p, const char *pat, int dir, int range) regfree(&preg); if (i < 0) return NULL; - if (dir == FORWARD) + if (dir_and_range > 0) // FORWARD? p = p + i; else p = p - i; @@ -1966,13 +1968,15 @@ static int mycmp(const char *s1, const char *s2, int len) # define mycmp strncmp # endif -static char *char_search(char *p, const char *pat, int dir, int range) +static char *char_search(char *p, const char *pat, int dir_and_range) { char *start, *stop; int len; + int range; len = strlen(pat); - if (dir == FORWARD) { + range = (dir_and_range & 1); + if (dir_and_range > 0) { //FORWARD? stop = end - 1; // assume range is p..end-1 if (range == LIMITED) stop = next_line(p); // range is to next line @@ -1981,7 +1985,7 @@ static char *char_search(char *p, const char *pat, int dir, int range) return start; } } - } else if (dir == BACK) { + } else { //BACK stop = text; // assume range is text..p if (range == LIMITED) stop = prev_line(p); // range is to prev line @@ -3818,7 +3822,7 @@ static void do_cmd(int c) p = dot - 1; } dc4: - q = char_search(p, last_search_pattern + 1, dir, FULL); + q = char_search(p, last_search_pattern + 1, (dir << 1) | FULL); if (q != NULL) { dot = q; // good search, update "dot" msg = NULL; @@ -3829,7 +3833,7 @@ static void do_cmd(int c) if (dir == BACK) { p = end - 1; } - q = char_search(p, last_search_pattern + 1, dir, FULL); + q = char_search(p, last_search_pattern + 1, (dir << 1) | FULL); if (q != NULL) { // found something dot = q; // found new pattern- goto it msg = "search hit BOTTOM, continuing at TOP"; @@ -3845,13 +3849,13 @@ static void do_cmd(int c) } while (--cmdcnt > 0); break; case '{': // {- move backward paragraph - q = char_search(dot, "\n\n", BACK, FULL); + q = char_search(dot, "\n\n", (BACK << 1) | FULL); if (q != NULL) { // found blank line dot = next_line(q); // move to next blank line } break; case '}': // }- move forward paragraph - q = char_search(dot, "\n\n", FORWARD, FULL); + q = char_search(dot, "\n\n", (FORWARD << 1) | FULL); if (q != NULL) { // found blank line dot = next_line(q); // move to next blank line } -- cgit v1.2.3-55-g6feb From d08206dce1291f512d7de9037d9ef1ffbf705cac Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 3 Dec 2018 10:07:58 +0100 Subject: vi: correctly detect when a deletion empties the buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Michał Berger has reported two issues: - Repeatedly deleting and undoing the deletion of the last line results in characters being lost from the end of the line. - Deleting the bottom line twice then attempting to undo each of these deletions results in a segfault. The problem seems to be an incorrect test for whether the text buffer is empty. Reported-by: Michał Berger Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/vi.c b/editors/vi.c index ee3c7feb2..271529404 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2364,7 +2364,7 @@ static void undo_push(char *src, unsigned int length, uint8_t u_type) // Add to // Allocate a new undo object if (u_type == UNDO_DEL || u_type == UNDO_DEL_CHAIN) { // For UNDO_DEL objects, save deleted text - if ((src + length) == end) + if ((text + length) == end) length--; // If this deletion empties text[], strip the newline. When the buffer becomes // zero-length, a newline is added back, which requires this to compensate. -- cgit v1.2.3-55-g6feb