From 20a4f70ecaad79bb932af09b7317a058872cd867 Mon Sep 17 00:00:00 2001 From: Roger Knecht Date: Mon, 18 Apr 2022 12:54:20 +0000 Subject: tree: new applet Adds the tree program to list directories and files in a tree structure. function old new delta tree_print - 343 +343 scandir64 - 330 +330 scandir - 330 +330 tree_main - 86 +86 .rodata 105150 105228 +78 packed_usage 34511 34557 +46 alphasort64 - 31 +31 alphasort - 31 +31 strcoll - 5 +5 applet_names 2801 2806 +5 applet_main 1616 1620 +4 applet_suid 101 102 +1 applet_install_loc 202 203 +1 ------------------------------------------------------------------------------ (add/remove: 11/0 grow/shrink: 6/0 up/down: 1291/0) Total: 1291 bytes Signed-off-by: Roger Knecht Signed-off-by: Denys Vlasenko --- AUTHORS | 3 ++ miscutils/tree.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ testsuite/tree.tests | 100 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 miscutils/tree.c create mode 100755 testsuite/tree.tests diff --git a/AUTHORS b/AUTHORS index 5c9a634c9..9ec0e2ee4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -181,3 +181,6 @@ Jie Zhang Maxime Coste paste implementation + +Roger Knecht + tree diff --git a/miscutils/tree.c b/miscutils/tree.c new file mode 100644 index 000000000..8b16c5383 --- /dev/null +++ b/miscutils/tree.c @@ -0,0 +1,118 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2022 Roger Knecht + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//config:config TREE +//config: bool "tree (0.6 kb)" +//config: default y +//config: help +//config: List files and directories in a tree structure. + +//applet:IF_TREE(APPLET(tree, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_TREE) += tree.o + +//usage:#define tree_trivial_usage NOUSAGE_STR +//usage:#define tree_full_usage "" + +#include "libbb.h" +#include "common_bufsiz.h" + +#define prefix_buf bb_common_bufsiz1 + +static void tree_print(unsigned count[2], const char* directory_name, char* prefix_pos) +{ + struct dirent **entries; + int index, size; + + // read directory entries + size = scandir(directory_name, &entries, NULL, alphasort); + + if (size < 0) { + fputs_stdout(directory_name); + puts(" [error opening dir]"); + return; + } + + // print directory name + puts(directory_name); + + // switch to sub directory + xchdir(directory_name); + + // print all directory entries + for (index = 0; index < size;) { + struct dirent *dirent = entries[index++]; + + // filter hidden files and directories + if (dirent->d_name[0] != '.') { + int status; + struct stat statBuf; + +//TODO: when -l is implemented, use stat, not lstat, if -l + status = lstat(dirent->d_name, &statBuf); + + if (index == size) { + strcpy(prefix_pos, "└── "); + } else { + strcpy(prefix_pos, "├── "); + } + fputs_stdout(prefix_buf); + + if (status == 0 && S_ISLNK(statBuf.st_mode)) { + // handle symlink + char* symlink_path = xmalloc_readlink(dirent->d_name); + printf("%s -> %s\n", dirent->d_name, symlink_path); + free(symlink_path); + count[1]++; + } else if (status == 0 && S_ISDIR(statBuf.st_mode) + && (prefix_pos - prefix_buf) < (COMMON_BUFSIZE - 16) + ) { + // handle directory + char* pos; + if (index == size) { + pos = stpcpy(prefix_pos, " "); + } else { + pos = stpcpy(prefix_pos, "│   "); + } + tree_print(count, dirent->d_name, pos); + count[0]++; + } else { + // handle file + puts(dirent->d_name); + count[1]++; + } + } + + // release directory entry + free(dirent); + } + + // release directory array + free(entries); + + // switch to parent directory + xchdir(".."); +} + +int tree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int tree_main(int argc UNUSED_PARAM, char **argv) +{ + unsigned count[2] = { 0, 0 }; + + setup_common_bufsiz(); + + if (!argv[1]) + *argv-- = (char*)"."; + + // list directories given as command line arguments + while (*(++argv)) + tree_print(count, *argv, prefix_buf); + + // print statistic + printf("\n%u directories, %u files\n", count[0], count[1]); + + return EXIT_SUCCESS; +} diff --git a/testsuite/tree.tests b/testsuite/tree.tests new file mode 100755 index 000000000..4f4a9e30b --- /dev/null +++ b/testsuite/tree.tests @@ -0,0 +1,100 @@ +#!/bin/sh + +# Copyright 2022 by Roger Knecht +# Licensed under GPLv2, see file LICENSE in this source tree. + +. ./testing.sh -v + +# testing "description" "command" "result" "infile" "stdin" + +testing "tree error opening dir" \ + "tree tree.tempdir" \ + "\ +tree.tempdir [error opening dir]\n\ +\n\ +0 directories, 0 files\n" \ + "" "" + +mkdir -p tree2.tempdir +touch tree2.tempdir/testfile + +testing "tree single file" \ + "cd tree2.tempdir && tree" \ + "\ +.\n\ +└── testfile\n\ +\n\ +0 directories, 1 files\n" \ + "" "" + +mkdir -p tree3.tempdir/test1 \ + tree3.tempdir/test2/a \ + tree3.tempdir/test2/b \ + tree3.tempdir/test3/c \ + tree3.tempdir/test3/d + +touch tree3.tempdir/test2/a/testfile1 \ + tree3.tempdir/test2/a/testfile2 \ + tree3.tempdir/test2/a/testfile3 \ + tree3.tempdir/test2/b/testfile4 \ + tree3.tempdir/test3/c/testfile5 \ + tree3.tempdir/test3/d/testfile6 \ + tree3.tempdir/test3/d/.testfile7 + +(cd tree3.tempdir/test2/a && ln -s ../b/testfile4 .) +(cd tree3.tempdir/test2/b && ln -s ../../test3 .) + +testing "tree nested directories and files" \ + "cd tree3.tempdir && tree" \ + "\ +.\n\ +├── test1\n\ +├── test2\n\ +│   ├── a\n\ +│   │   ├── testfile1\n\ +│   │   ├── testfile2\n\ +│   │   ├── testfile3\n\ +│   │   └── testfile4 -> ../b/testfile4\n\ +│   └── b\n\ +│   ├── test3 -> ../../test3\n\ +│   └── testfile4\n\ +└── test3\n\ + ├── c\n\ + │   └── testfile5\n\ + └── d\n\ + └── testfile6\n\ +\n\ +7 directories, 8 files\n" \ + "" "" +#note: tree v2.0.1 says "8 directories, 7 files": +#it counts "test3 -> ../../test3" as a directory, even though it does not follow this symlink + +testing "tree multiple directories" \ + "tree tree2.tempdir tree3.tempdir" \ + "\ +tree2.tempdir\n\ +└── testfile\n\ +tree3.tempdir\n\ +├── test1\n\ +├── test2\n\ +│   ├── a\n\ +│   │   ├── testfile1\n\ +│   │   ├── testfile2\n\ +│   │   ├── testfile3\n\ +│   │   └── testfile4 -> ../b/testfile4\n\ +│   └── b\n\ +│   ├── test3 -> ../../test3\n\ +│   └── testfile4\n\ +└── test3\n\ + ├── c\n\ + │   └── testfile5\n\ + └── d\n\ + └── testfile6\n\ +\n\ +7 directories, 9 files\n" \ + "" "" +#note: tree v2.0.1 says "8 directories, 7 files" (not "8 files", probably a/testfile4 -> ../b/testfile4 and b/testfile4 are counted as one file, not 2?) + +rm -rf tree.tempdir tree2.tempdir tree3.tempdir + +exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 298ac9507bb6cb932162f863c7b9623c0a37dedb Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 28 Jun 2022 13:40:49 +0100 Subject: lineedit: get PWD from ash The line editing code and ash disagree when the current directory is changed to a symbolic link: ~ $ mkdir real ~ $ ln -s real link ~ $ cd link ~/real $ pwd /home/rmyf36/link Note the prompt says we're in ~/real. Bash does: [rmy@random ~]$ cd link [rmy@random link]$ pwd /home/rmyf36/link Ash uses the name supplied by the user while the line editing code calls getcwd(3). The discrepancy can be avoided by fetching the value of PWD from ash. Hush calls getcwd(3) when the directory is changed so there's no disagreement with the line editing code. There is no standard how shells should handle cd'ing into symlinks. function old new delta parse_and_put_prompt 838 869 +31 Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b685399f9..697f2a577 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2035,7 +2035,13 @@ static void parse_and_put_prompt(const char *prmt_ptr) case 'W': /* basename of cur dir */ if (!cwd_buf) { const char *home; +#if ENABLE_SHELL_ASH + cwd_buf = state->sh_get_var + ? xstrdup(state->sh_get_var("PWD")) + : xrealloc_getcwd_or_warn(NULL); +#else cwd_buf = xrealloc_getcwd_or_warn(NULL); +#endif if (!cwd_buf) cwd_buf = (char *)bb_msg_unknown; else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { -- cgit v1.2.3-55-g6feb From 3ad3aa6441ebaf817137051de2b74cb6b4379e7f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jul 2022 14:36:39 +0200 Subject: shaNNNsum: accept one-space "HASH FILENAME" format for -c, closes 14866 function old new delta md5_sha1_sum_main 496 501 +5 Signed-off-by: Denys Vlasenko --- coreutils/md5_sha1_sum.c | 13 ++++++++----- testsuite/sha1sum.tests | 10 ++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 0e57673f1..b4bdc262c 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c @@ -301,9 +301,7 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv) count_total++; filename_ptr = strchr(line, ' '); - if (filename_ptr == NULL - || (filename_ptr[1] != ' ' && filename_ptr[1] != '*') - ) { + if (!filename_ptr) { if (flags & FLAG_WARN) { bb_simple_error_msg("invalid format"); } @@ -312,8 +310,13 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv) free(line); continue; } - *filename_ptr = '\0'; - filename_ptr += 2; + *filename_ptr++ = '\0'; + /* coreutils 9.1 allows "HASH FILENAME" format, + * with only one space. Skip the 'correct' + * " " or " *" delimiter if it is there: + */ + if (*filename_ptr == ' ' || *filename_ptr == '*') + filename_ptr++; hash_value = hash_file(in_buf, filename_ptr, sha3_width); diff --git a/testsuite/sha1sum.tests b/testsuite/sha1sum.tests index a968fa87c..7ad1334c3 100755 --- a/testsuite/sha1sum.tests +++ b/testsuite/sha1sum.tests @@ -1,3 +1,13 @@ #!/bin/sh +. ./testing.sh + +# testing "test name" "cmd" "expected result" "file input" "stdin" +>EMPTY +testing "sha1sum: one-space separated input for -c" \ + 'echo "da39a3ee5e6b4b0d3255bfef95601890afd80709 EMPTY" | sha1sum -c' \ + "EMPTY: OK\n" \ + "" "" +rm EMPTY + . ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f -- cgit v1.2.3-55-g6feb From e63d7cdfdac78c6fd27e9e63150335767592b85e Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 17 Jun 2022 17:45:34 +0200 Subject: awk: fix use after free (CVE-2022-30065) fixes https://bugs.busybox.net/show_bug.cgi?id=14781 function old new delta evaluate 3343 3357 +14 Signed-off-by: Natanael Copa Signed-off-by: Denys Vlasenko --- editors/awk.c | 3 +++ testsuite/awk.tests | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/editors/awk.c b/editors/awk.c index 079d0bde5..728ee8685 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -3128,6 +3128,9 @@ static var *evaluate(node *op, var *res) case XC( OC_MOVE ): debug_printf_eval("MOVE\n"); + /* make sure that we never return a temp var */ + if (L.v == TMPVAR0) + L.v = res; /* if source is a temporary string, jusk relink it to dest */ if (R.v == TMPVAR1 && !(R.v->type & VF_NUMBER) diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 93e25d8c1..bbf0fbff1 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -479,4 +479,10 @@ testing 'awk backslash+newline eaten with no trace' \ "Hello world\n" \ '' '' +testing 'awk assign while test' \ + "awk '\$1==\$1=\"foo\" {print \$1}'" \ + "foo\n" \ + "" \ + "foo" + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 7b969bb2ada4d7757229fd735135f7720ef8008c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Jul 2022 16:11:17 +0200 Subject: tls: P256: remove NOP macro sp_256_norm_8() Signed-off-by: Denys Vlasenko --- networking/tls_sp_c32.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c index 292dda24e..a593c5c40 100644 --- a/networking/tls_sp_c32.c +++ b/networking/tls_sp_c32.c @@ -68,9 +68,6 @@ static const sp_digit p256_mod[8] ALIGNED(8) = { #define p256_mp_mod ((sp_digit)0x000001) -/* Normalize the values in each word to 32 bits - NOP */ -#define sp_256_norm_8(a) ((void)0) - /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 * @@ -83,8 +80,6 @@ static void sp_256_to_bin_8(const sp_digit* rr, uint8_t* a) int i; const uint64_t* r = (void*)rr; - sp_256_norm_8(rr); - r += 4; for (i = 0; i < 4; i++) { r--; @@ -97,8 +92,6 @@ static void sp_256_to_bin_8(const sp_digit* r, uint8_t* a) { int i; - sp_256_norm_8(r); - r += 8; for (i = 0; i < 8; i++) { r--; @@ -641,7 +634,6 @@ static void sp_256_div2_8(sp_digit* r /*, const sp_digit* m*/) int carry = 0; if (r[0] & 1) carry = sp_256_add_8(r, r, m); - sp_256_norm_8(r); sp_256_rshift1_8(r, carry); } @@ -652,10 +644,8 @@ static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b // const sp_digit* m = p256_mod; int carry = sp_256_add_8(r, a, b); - sp_256_norm_8(r); if (carry) { sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } } @@ -667,10 +657,8 @@ static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b int borrow; borrow = sp_256_sub_8(r, a, b); - sp_256_norm_8(r); if (borrow) { sp_256_add_8(r, r, m); - sp_256_norm_8(r); } } @@ -680,10 +668,8 @@ static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a /*, const sp_digit* // const sp_digit* m = p256_mod; int carry = sp_256_add_8(r, a, a); - sp_256_norm_8(r); if (carry) sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } /* Triple a Montgomery form number (r = a + a + a % m) */ @@ -692,16 +678,12 @@ static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a /*, const sp_digit* // const sp_digit* m = p256_mod; int carry = sp_256_add_8(r, a, a); - sp_256_norm_8(r); if (carry) { sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } carry = sp_256_add_8(r, r, a); - sp_256_norm_8(r); if (carry) { sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } } @@ -844,7 +826,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* aa/*, const sp_digi sp_512to256_mont_shift_8(r, aa); if (carry != 0) sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } #else /* Generic 32-bit version */ @@ -1003,8 +984,6 @@ static int sp_256_mul_add_8(sp_digit* r /*, const sp_digit* a, sp_digit b*/) * [In our case, it is (p256_mp_mod * a[1]) << 32.] * And so on. Eventually T is divisible by R, and after division by R * the algorithm is in the same place as the usual Montgomery reduction. - * - * TODO: Can conditionally use 64-bit (if bit-little-endian arch) logic? */ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit* m, sp_digit mp*/) { @@ -1032,7 +1011,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit sp_512to256_mont_shift_8(r, a); if (word16th != 0) sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } else { /* Same code for explicit mp == 1 (which is always the case for P256) */ sp_digit word16th = 0; @@ -1052,7 +1030,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit sp_512to256_mont_shift_8(r, a); if (word16th != 0) sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } } #endif @@ -1208,14 +1185,12 @@ static void sp_256_map_8(sp_point* r, sp_point* p) /* Reduce x to less than modulus */ if (sp_256_cmp_8(r->x, p256_mod) >= 0) sp_256_sub_8_p256_mod(r->x); - sp_256_norm_8(r->x); /* y /= z^3 */ sp_256_mont_mul_and_reduce_8(r->y, p->y, t1 /*, p256_mod, p256_mp_mod*/); /* Reduce y to less than modulus */ if (sp_256_cmp_8(r->y, p256_mod) >= 0) sp_256_sub_8_p256_mod(r->y); - sp_256_norm_8(r->y); memset(r->z, 0, sizeof(r->z)); r->z[0] = 1; @@ -1300,7 +1275,6 @@ static NOINLINE void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* /* Check double */ sp_256_sub_8(t1, p256_mod, q->y); - sp_256_norm_8(t1); if (sp_256_cmp_equal_8(p->x, q->x) && sp_256_cmp_equal_8(p->z, q->z) && (sp_256_cmp_equal_8(p->y, q->y) || sp_256_cmp_equal_8(p->y, t1)) @@ -1422,14 +1396,15 @@ static void sp_256_ecc_mulmod_8(sp_point* r, const sp_point* g, const sp_digit* static void sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k /*, int map*/) { /* Since this function is called only once, save space: - * don't have "static const sp_point p256_base = {...}", - * it would have more zeros than data. + * don't have "static const sp_point p256_base = {...}". */ static const uint8_t p256_base_bin[] = { /* x (big-endian) */ - 0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2,0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96, + 0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2, + 0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96, /* y */ - 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16,0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5, + 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16, + 0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5, /* z will be set to 1, infinity flag to "false" */ }; sp_point p256_base; -- cgit v1.2.3-55-g6feb From 9b6eb2a8ef4f1cfeeea821e270d49ef9c6ae4503 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Jul 2022 16:15:04 +0200 Subject: udhcpc6: add missed big-endian conversions function old new delta option_to_env 686 694 +8 Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 9fc690315..d4cdd0c3a 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -295,6 +295,7 @@ static void option_to_env(const uint8_t *option, const uint8_t *option_end) *new_env() = xasprintf("ipv6=%s", ipv6str); move_from_unaligned32(v32, option + 4 + 16 + 4); + v32 = ntohl(v32); *new_env() = xasprintf("lease=%u", (unsigned)v32); break; @@ -332,6 +333,7 @@ static void option_to_env(const uint8_t *option, const uint8_t *option_end) * +-+-+-+-+-+-+-+-+ */ move_from_unaligned32(v32, option + 4 + 4); + v32 = ntohl(v32); *new_env() = xasprintf("ipv6prefix_lease=%u", (unsigned)v32); sprint_nip6(ipv6str, option + 4 + 4 + 4 + 1); -- cgit v1.2.3-55-g6feb From 00f2a35b835c6f49617f5379073e9063e7e683ce Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 29 Jul 2022 16:05:50 +0200 Subject: sort: fix -k2M (wasn't skipping leading whitespace) function old new delta compare_keys 848 862 +14 Signed-off-by: Denys Vlasenko --- coreutils/sort.c | 4 ++-- testsuite/sort.tests | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/coreutils/sort.c b/coreutils/sort.c index 9aac656fe..80b578fc2 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -357,9 +357,9 @@ static int compare_keys(const void *xarg, const void *yarg) int dx; char *xx, *yy; - xx = strptime(x, "%b", &thyme); + xx = strptime(skip_whitespace(x), "%b", &thyme); dx = thyme.tm_mon; - yy = strptime(y, "%b", &thyme); + yy = strptime(skip_whitespace(y), "%b", &thyme); if (!xx) retval = (!yy) ? 0 : -1; else if (!yy) diff --git a/testsuite/sort.tests b/testsuite/sort.tests index ff33e21b4..fb2cc91bd 100755 --- a/testsuite/sort.tests +++ b/testsuite/sort.tests @@ -219,4 +219,15 @@ testing "sort -h" \ # testing "description" "command(s)" "result" "infile" "stdin" +testing "sort -k2,2M" \ +"sort -k2,2M input" "\ +3 March +2 April +1 May +" "\ +2 April +1 May +3 March +" "" + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 5479c435fde32e720af5e177e95d6364a422885a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 29 Jul 2022 16:40:00 +0200 Subject: sort: fix sort -s -u, closes 14871 function old new delta sort_main 851 856 +5 Signed-off-by: Denys Vlasenko --- coreutils/sort.c | 9 +++++---- testsuite/sort.tests | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/coreutils/sort.c b/coreutils/sort.c index 80b578fc2..01b7c44e5 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -652,11 +652,12 @@ int sort_main(int argc UNUSED_PARAM, char **argv) /* Handle -u */ if (option_mask32 & FLAG_u) { int j = 0; - /* coreutils 6.3 drop lines for which only key is the same - * -- disabling last-resort compare, or else compare_keys() - * will be the same only for completely identical lines. + /* coreutils 6.3 drop lines for which only key is the same: + * - disabling last-resort compare, or else compare_keys() + * will be the same only for completely identical lines + * - disabling -s (same reasons) */ - option_mask32 |= FLAG_no_tie_break; + option_mask32 = (option_mask32 | FLAG_no_tie_break) & (~FLAG_s); for (i = 1; i < linecount; i++) { if (compare_keys(&lines[j], &lines[i]) == 0) free(lines[i]); diff --git a/testsuite/sort.tests b/testsuite/sort.tests index fb2cc91bd..8dbadbdae 100755 --- a/testsuite/sort.tests +++ b/testsuite/sort.tests @@ -230,4 +230,14 @@ testing "sort -k2,2M" \ 3 March " "" +testing "sort -s -u" \ +"sort -s -u -k 2 input" "\ +z a +z b +" "\ +z b +a b +z a +a a" "" + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 1c5455284234e894dfb6086bf7f3e9a6d5d9611f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Aug 2022 11:13:44 +0200 Subject: ash: fix ifs cleanup on error paths Patch by Alex Gorinson function old new delta evalvar 477 495 +18 varvalue 603 618 +15 subevalvar 1557 1572 +15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 48/0) Total: 48 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 ++ shell/ash_test/ash-heredoc/heredoc_and_cmd.right | 2 ++ shell/ash_test/ash-heredoc/heredoc_and_cmd.tests | 8 ++++++++ shell/hush_test/hush-heredoc/heredoc_and_cmd.right | 2 ++ shell/hush_test/hush-heredoc/heredoc_and_cmd.tests | 8 ++++++++ 5 files changed, 22 insertions(+) create mode 100644 shell/ash_test/ash-heredoc/heredoc_and_cmd.right create mode 100755 shell/ash_test/ash-heredoc/heredoc_and_cmd.tests create mode 100644 shell/hush_test/hush-heredoc/heredoc_and_cmd.right create mode 100755 shell/hush_test/hush-heredoc/heredoc_and_cmd.tests diff --git a/shell/ash.c b/shell/ash.c index d29de37b7..c731a333b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7028,6 +7028,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags) msg = umsg; } } + ifsfree(); ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail); } @@ -7453,6 +7454,7 @@ varvalue(char *name, int varflags, int flags, int quoted) if (discard) return -1; + ifsfree(); raise_error_syntax("bad substitution"); } diff --git a/shell/ash_test/ash-heredoc/heredoc_and_cmd.right b/shell/ash_test/ash-heredoc/heredoc_and_cmd.right new file mode 100644 index 000000000..25ae70561 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_and_cmd.right @@ -0,0 +1,2 @@ +./heredoc_and_cmd.tests: line 4: D: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Y diff --git a/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests b/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests new file mode 100755 index 000000000..197542de7 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests @@ -0,0 +1,8 @@ +# The bug was only happening with < Date: Tue, 2 Aug 2022 12:41:18 +0200 Subject: ash: fix use-after-free in pattern substituon code Patch by soeren@soeren-tempel.net The idx variable points to a value in the stack string (as managed by STPUTC). STPUTC may resize this stack string via realloc(3). If this happens, the idx pointer needs to be updated. Otherwise, dereferencing idx may result in a use-after free. function old new delta subevalvar 1562 1566 +4 Signed-off-by: Denys Vlasenko --- shell/ash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index c731a333b..105edd4c8 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7324,13 +7324,15 @@ subevalvar(char *start, char *str, int strloc, if (idx >= end) break; STPUTC(*idx, expdest); + if (stackblock() != restart_detect) + goto restart; if (quotes && (unsigned char)*idx == CTLESC) { idx++; len++; STPUTC(*idx, expdest); + if (stackblock() != restart_detect) + goto restart; } - if (stackblock() != restart_detect) - goto restart; idx++; len++; rmesc++; -- cgit v1.2.3-55-g6feb From 9eddf164bf22a20e8033fad2dc35cde2d6bd2305 Mon Sep 17 00:00:00 2001 From: Henrique Rodrigues Date: Mon, 1 Aug 2022 12:55:32 +0100 Subject: ping: fix typo in --help text Signed-off-by: Henrique Rodrigues Signed-off-by: Denys Vlasenko --- networking/ping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/ping.c b/networking/ping.c index 86d8088de..9805695a1 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -74,7 +74,7 @@ //usage: "\n -c CNT Send only CNT pings" //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" //usage: "\n -i SECS Interval" -//usage: "\n -A Ping as soon as reply is recevied" +//usage: "\n -A Ping as soon as reply is received" //usage: "\n -t TTL Set TTL" //usage: "\n -I IFACE/IP Source interface or IP address" //usage: "\n -W SEC Seconds to wait for the first response (default 10)" @@ -91,7 +91,7 @@ //usage: "\n -c CNT Send only CNT pings" //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" //usage: "\n -i SECS Interval" -//usage: "\n -A Ping as soon as reply is recevied" +//usage: "\n -A Ping as soon as reply is received" ///////: "\n -t TTL Set TTL" ///////^^^^^ -t not tested for IPv6, might be not working //usage: "\n -I IFACE/IP Source interface or IP address" -- cgit v1.2.3-55-g6feb From 3147552a230cfd4a4943a46f63e3313655acf566 Mon Sep 17 00:00:00 2001 From: Grob Grobmann Date: Wed, 8 Jun 2022 16:51:54 -0300 Subject: vi: add 'ZQ' quitting command Busybox vi provides the 'ZZ' command to save and close the similar 'ZQ' command just exits without saving. function old new delta do_cmd 4222 4244 +22 Signed-off-by: Grob Grobmann Signed-off-by: Denys Vlasenko --- editors/vi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/editors/vi.c b/editors/vi.c index d799a8170..1f997e8e5 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -4324,8 +4324,14 @@ static void do_cmd(int c) goto dc_i; // start inserting break; case 'Z': // Z- if modified, {write}; exit - // ZZ means to save file (if necessary), then exit c1 = get_one_char(); + // ZQ means to exit without saving + if (c1 == 'Q') { + editing=0; + optind = cmdline_filecnt; + break; + } + // ZZ means to save file (if necessary), then exit if (c1 != 'Z') { indicate_error(); break; -- cgit v1.2.3-55-g6feb From 75aaa8b3118d4a34b83ece4ec953b8448b19b519 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Aug 2022 15:33:51 +0200 Subject: udhcpc6: fix sending of renew messages function old new delta d6_listen_socket - 150 +150 Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index d4cdd0c3a..9666f0446 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -844,7 +844,7 @@ static NOINLINE int send_d6_renew(struct in6_addr *server_ipv6, struct in6_addr uint8_t *opt_ptr; /* Fill in: msg type, xid, ELAPSED_TIME */ - opt_ptr = init_d6_packet(&packet, DHCPREQUEST); + opt_ptr = init_d6_packet(&packet, D6_MSG_RENEW); /* server id */ opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); @@ -1083,7 +1083,7 @@ static void change_listen_mode(int new_mode) client_data.sockfd = -1; } if (new_mode == LISTEN_KERNEL) - client_data.sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_data.interface); + client_data.sockfd = d6_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_data.interface); else if (new_mode != LISTEN_NONE) client_data.sockfd = d6_raw_socket(client_data.ifindex); /* else LISTEN_NONE: client_data.sockfd stays closed */ @@ -1489,6 +1489,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_l) send_d6_info_request(); else /* send a broadcast renew request */ +//TODO: send_d6_renew uses D6_MSG_RENEW message, should we use D6_MSG_REBIND here instead? send_d6_renew(/*server_ipv6:*/ NULL, requested_ipv6); timeout = discover_timeout; packet_num++; -- cgit v1.2.3-55-g6feb From 84b89b4c22ab7c8348d00e31d5319fad6e43defe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Aug 2022 18:04:51 +0200 Subject: udhcpc6: downgrade "opening listen socket" log level to 2 This matches udhcpc for IPv4. Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 2 +- networking/udhcp/d6_socket.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 9666f0446..c7f130a70 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1083,7 +1083,7 @@ static void change_listen_mode(int new_mode) client_data.sockfd = -1; } if (new_mode == LISTEN_KERNEL) - client_data.sockfd = d6_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_data.interface); + client_data.sockfd = d6_listen_socket(CLIENT_PORT6, client_data.interface); else if (new_mode != LISTEN_NONE) client_data.sockfd = d6_raw_socket(client_data.ifindex); /* else LISTEN_NONE: client_data.sockfd stays closed */ diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c index 8ddee5a8e..21cf61c6e 100644 --- a/networking/udhcp/d6_socket.c +++ b/networking/udhcp/d6_socket.c @@ -110,7 +110,7 @@ int FAST_FUNC d6_listen_socket(int port, const char *inf) int fd; struct sockaddr_in6 addr; - log1("opening listen socket on *:%d %s", port, inf); + log2("opening listen socket on *:%d %s", port, inf); fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); setsockopt_reuseaddr(fd); -- cgit v1.2.3-55-g6feb From 7c2a3bdde0a1316771fdd07ff03413f00383f70e Mon Sep 17 00:00:00 2001 From: Sören Tempel Date: Tue, 2 Aug 2022 18:23:32 +0200 Subject: ash: fix use-after-free in bash pattern substitution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit function old new delta subevalvar 1566 1564 -2 Signed-off-by: Sören Tempel Signed-off-by: Denys Vlasenko --- shell/ash.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/shell/ash.c b/shell/ash.c index 105edd4c8..55c1034f5 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7357,6 +7357,13 @@ subevalvar(char *start, char *str, int strloc, idx = loc; } + /* The STPUTC invocations above may resize and move the + * stack via realloc(3). Since repl is a pointer into the + * stack, we need to reconstruct it relative to stackblock(). + */ + if (slash_pos >= 0) + repl = (char *)stackblock() + strloc + slash_pos + 1; + //bb_error_msg("repl:'%s'", repl); for (loc = (char*)repl; *loc; loc++) { char *restart_detect = stackblock(); -- cgit v1.2.3-55-g6feb From 41d5f800a14769704082f7faeabb8435285499be Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 18 Aug 2022 16:23:55 +0200 Subject: bc: hopefully fix bug 14956 (use-after-free) Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/miscutils/bc.c b/miscutils/bc.c index ab785bbc8..1300a63fb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2892,6 +2892,8 @@ static char peek_inbuf(void) ) { xc_read_line(&G.input_buffer, G.prs.lex_input_fp); G.prs.lex_inbuf = G.input_buffer.v; + // lex_next_at may point to now-freed data, update it: + G.prs.lex_next_at = G.prs.lex_inbuf; if (G.input_buffer.len <= 1) // on EOF, len is 1 (NUL byte) G.prs.lex_input_fp = NULL; } -- cgit v1.2.3-55-g6feb From 5a9d2b6e024e6c20d4d7b8c170985554c0df043d Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 1 May 2022 09:45:37 +0100 Subject: libbb: make '--help' handling more consistent Running an applet with '--help' as its only argument is treated as a special case. If additional arguments follow '--help' the behaviour is inconsistent: - applets which call single_argv() print help and do nothing else; - applets which call getopt() report "unrecognized option '--help'" and print help anyway; - expr says "expr: syntax error" and doesn't print help; - printenv silently ignores '--help', prints any other variables and doesn't print help; - realpath says "--help: No such file or directory", prints the path of any other files and doesn't print help. If the first argument is '--help' ignore any other arguments and print help. This is more consistent and most likely what the user wanted. See also commit 6bdfbc4cb (libbb: fix '--help' handling in FEATURE_SH_NOFORK=y). function old new delta show_usage_if_dash_dash_help 75 69 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-6) Total: -6 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index d8ab2a450..9b9d7dbd6 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -258,7 +258,6 @@ void lbb_prepare(const char *applet /* Redundant for busybox (run_applet_and_exit covers that case) * but needed for "individual applet" mode */ if (argv[1] - && !argv[2] && strcmp(argv[1], "--help") == 0 && !is_prefixed_with(applet, "busybox") ) { @@ -940,8 +939,8 @@ void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv) && applet_no != APPLET_NO_echo # endif ) { - if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0) { - /* Make "foo --help" exit with 0: */ + if (argv[1] && strcmp(argv[1], "--help") == 0) { + /* Make "foo --help [...]" exit with 0: */ xfunc_error_retval = 0; bb_show_usage(); } -- cgit v1.2.3-55-g6feb From f318adaaab3288fe72cb853bf7ede56790a13182 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Aug 2022 15:40:47 +0200 Subject: xxd -r: without -p, stop at more than one whitespace, closes 14786 function old new delta xxd_main 888 1076 +188 Signed-off-by: Denys Vlasenko --- testsuite/xxd.tests | 9 ++++++++ util-linux/hexdump_xxd.c | 56 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/testsuite/xxd.tests b/testsuite/xxd.tests index 76fa96af9..359e7f8f7 100755 --- a/testsuite/xxd.tests +++ b/testsuite/xxd.tests @@ -37,4 +37,13 @@ testing 'xxd -p -r' \ '' \ '30313233343536373736353433323130 30313233343536373736353433323130' +testing 'xxd -r skips leading whitespace and truncates at two spaces' \ + 'xxd -r' \ + '0123456789:;<=>?@' \ + '' \ +"\ + 00000000: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? + 00000010: 40 @ +" + exit $FAILCOUNT diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 4372ac770..dbda34bc5 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -76,12 +76,14 @@ static void reverse(unsigned opt, const char *filename) fp = filename ? xfopen_for_read(filename) : stdin; + get_new_line: while ((buf = xmalloc_fgetline(fp)) != NULL) { char *p; p = buf; if (!(opt & OPT_p)) { - /* skip address */ + skip_address: + p = skip_whitespace(p); while (isxdigit(*p)) p++; /* NB: for xxd -r, first hex portion is address even without colon */ /* If it's there, skip it: */ @@ -94,36 +96,45 @@ static void reverse(unsigned opt, const char *filename) /* Process hex bytes optionally separated by whitespace */ for (;;) { uint8_t val, c; + int badchar = 0; nibble1: - p = skip_whitespace(p); - + if (opt & OPT_p) + p = skip_whitespace(p); c = *p++; if (isdigit(c)) val = c - '0'; else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') val = (c|0x20) - ('a' - 10); else { - /* xxd V1.10 is inconsistent here. + /* xxd V1.10 allows one non-hexnum char: * echo -e "31 !3 0a 0a" | xxd -r -p * is "10" (no ) - "!" is ignored, - * but + * but stops for more than one: * echo -e "31 !!343434\n30 0a" | xxd -r -p * is "10" - "!!" drops rest of the line. - * We will ignore all invalid chars: + * Note: this also covers whitespace chars: + * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? + * detects this ^ - skips this one space + * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? + * detects this ^^ - skips the rest */ - if (c != '\0') - goto nibble1; - break; + if (c == '\0' || badchar) + break; + badchar++; + goto nibble1; } val <<= 4; - /* Works the same with xxd V1.10: - * echo "31 09 32 0a" | xxd -r -p - * echo "31 0 9 32 0a" | xxd -r -p - * thus allow whitespace even within the byte: - */ nibble2: - p = skip_whitespace(p); + if (opt & OPT_p) { + /* Works the same with xxd V1.10: + * echo "31 09 32 0a" | xxd -r -p + * echo "31 0 9 32 0a" | xxd -r -p + * thus allow whitespace (even multiple chars) + * after byte's 1st char: + */ + p = skip_whitespace(p); + } c = *p++; if (isdigit(c)) @@ -132,7 +143,16 @@ static void reverse(unsigned opt, const char *filename) val |= (c|0x20) - ('a' - 10); else { if (c != '\0') { - /* "...3..." ignores both chars */ + /* "...3...": ignore "3", + * skip everything up to next hexchar or newline: + */ + while (!isxdigit(*p)) { + if (*p == '\0') { + free(buf); + goto get_new_line; + } + p++; + } goto nibble1; } /* Nibbles can join even through newline: @@ -143,10 +163,12 @@ static void reverse(unsigned opt, const char *filename) p = buf = xmalloc_fgetline(fp); if (!buf) break; + if (!(opt & OPT_p)) /* -p and !-p: different behavior */ + goto skip_address; goto nibble2; } putchar(val); - } + } /* for(;;) */ free(buf); } //fclose(fp); -- cgit v1.2.3-55-g6feb From 0011a6bc2024ec4ee6d8edea203524e758d67833 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Aug 2022 15:57:57 +0200 Subject: xxd: add two more testcases Signed-off-by: Denys Vlasenko --- testsuite/xxd.tests | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/testsuite/xxd.tests b/testsuite/xxd.tests index 359e7f8f7..2c740abc8 100755 --- a/testsuite/xxd.tests +++ b/testsuite/xxd.tests @@ -40,10 +40,24 @@ testing 'xxd -p -r' \ testing 'xxd -r skips leading whitespace and truncates at two spaces' \ 'xxd -r' \ '0123456789:;<=>?@' \ - '' \ -"\ + '' "\ 00000000: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? 00000010: 40 @ " +testing 'xxd -p -r skips one bad char, truncates at two bad chars' \ + 'xxd -p -r' \ + '01' \ + '' "\ +30 !31 !!32 +" + +testing 'xxd -p -r ignores the nibble with 2nd char bad' \ + 'xxd -p -r' \ + '3C6' \ + '' "\ +33 3!4 3!!5 +36 +" + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 5eceafb1f812ec4dca7fdf6896cfcea6783a78b9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Aug 2022 17:28:43 +0200 Subject: xxd -r: handle offsets function old new delta xxd_main 1076 1439 +363 .rodata 105239 105251 +12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 375/0) Total: 375 bytes Signed-off-by: Denys Vlasenko --- util-linux/hexdump_xxd.c | 58 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index dbda34bc5..6629407de 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -55,6 +55,7 @@ //usage: "\n -r Reverse (with -p, assumes no offsets in input)" #include "libbb.h" +#include "common_bufsiz.h" #include "dump.h" /* This is a NOEXEC applet. Be very careful! */ @@ -69,10 +70,32 @@ #define OPT_c (1 << 7) #define OPT_o (1 << 8) -static void reverse(unsigned opt, const char *filename) +#define fillbuf bb_common_bufsiz1 + +static void write_zeros(off_t count) +{ + errno = 0; + do { + unsigned sz = count < COMMON_BUFSIZE ? (unsigned)count : COMMON_BUFSIZE; + if (fwrite(fillbuf, 1, sz, stdout) != sz) + bb_perror_msg_and_die("write error"); + count -= sz; + } while (count != 0); +} + +static void reverse(unsigned opt, const char *filename, char *opt_s) { FILE *fp; char *buf; + off_t cur, opt_s_ofs; + + memset(fillbuf, 0, COMMON_BUFSIZE); + opt_s_ofs = cur = 0; + if (opt_s) { + opt_s_ofs = BB_STRTOOFF(opt_s, NULL, 0); + if (errno || opt_s_ofs < 0) + bb_error_msg_and_die("invalid number '%s'", opt_s); + } fp = filename ? xfopen_for_read(filename) : stdin; @@ -82,15 +105,31 @@ static void reverse(unsigned opt, const char *filename) p = buf; if (!(opt & OPT_p)) { + char *end; + off_t ofs; skip_address: p = skip_whitespace(p); - while (isxdigit(*p)) p++; + ofs = BB_STRTOOFF(p, &end, 16); + if ((errno && errno != EINVAL) + || ofs < 0 + /* -s SEEK value should be added before seeking */ + || (ofs += opt_s_ofs) < 0 + ) { + bb_error_msg_and_die("invalid number '%s'", p); + } + if (ofs != cur) { + if (fseeko(stdout, ofs, SEEK_SET) != 0) { + if (ofs < cur) + bb_perror_msg_and_die("cannot seek"); + write_zeros(ofs - cur); + } + cur = ofs; + } + p = end; /* NB: for xxd -r, first hex portion is address even without colon */ - /* If it's there, skip it: */ - if (*p == ':') p++; - -//TODO: seek (or zero-pad if unseekable) to the address position -//NOTE: -s SEEK value should be added to the address before seeking + /* But if colon is there, skip it: */ + if (*p == ':') + p++; } /* Process hex bytes optionally separated by whitespace */ @@ -168,6 +207,7 @@ static void reverse(unsigned opt, const char *filename) goto nibble2; } putchar(val); + cur++; } /* for(;;) */ free(buf); } @@ -195,6 +235,8 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) unsigned opt; int r; + setup_common_bufsiz(); + dumper = alloc_dumper(); opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, @@ -222,7 +264,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) } if (opt & OPT_r) { - reverse(opt, argv[0]); + reverse(opt, argv[0], opt_s); } if (opt & OPT_o) { -- cgit v1.2.3-55-g6feb From b30d345cfd995f111797f3377a3caaa263616081 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 26 Aug 2022 14:41:42 +0200 Subject: tree: make it unicode-aware function old new delta tree_print 396 420 +24 .rodata 105251 105266 +15 tree_main 86 91 +5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 44/0) Total: 44 bytes Signed-off-by: Denys Vlasenko --- miscutils/tree.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/miscutils/tree.c b/miscutils/tree.c index 8b16c5383..10e5481c4 100644 --- a/miscutils/tree.c +++ b/miscutils/tree.c @@ -19,6 +19,7 @@ #include "libbb.h" #include "common_bufsiz.h" +#include "unicode.h" #define prefix_buf bb_common_bufsiz1 @@ -26,6 +27,17 @@ static void tree_print(unsigned count[2], const char* directory_name, char* pref { struct dirent **entries; int index, size; + const char *bar = "| "; + const char *mid = "|-- "; + const char *end = "`-- "; + +#if ENABLE_UNICODE_SUPPORT + if (unicode_status == UNICODE_ON) { + bar = "│   "; + mid = "├── "; + end = "└── "; + } +#endif // read directory entries size = scandir(directory_name, &entries, NULL, alphasort); @@ -55,9 +67,9 @@ static void tree_print(unsigned count[2], const char* directory_name, char* pref status = lstat(dirent->d_name, &statBuf); if (index == size) { - strcpy(prefix_pos, "└── "); + strcpy(prefix_pos, end); } else { - strcpy(prefix_pos, "├── "); + strcpy(prefix_pos, mid); } fputs_stdout(prefix_buf); @@ -75,7 +87,7 @@ static void tree_print(unsigned count[2], const char* directory_name, char* pref if (index == size) { pos = stpcpy(prefix_pos, " "); } else { - pos = stpcpy(prefix_pos, "│   "); + pos = stpcpy(prefix_pos, bar); } tree_print(count, dirent->d_name, pos); count[0]++; @@ -103,6 +115,7 @@ int tree_main(int argc UNUSED_PARAM, char **argv) unsigned count[2] = { 0, 0 }; setup_common_bufsiz(); + init_unicode(); if (!argv[1]) *argv-- = (char*)"."; -- cgit v1.2.3-55-g6feb From 1a1220a5b05ca7fd86fde22c4a8bb9692a06670e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 26 Aug 2022 14:54:45 +0200 Subject: tree: unicode tweak (use normal space char, 0x20) Signed-off-by: Denys Vlasenko --- miscutils/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/tree.c b/miscutils/tree.c index 10e5481c4..fa55696c6 100644 --- a/miscutils/tree.c +++ b/miscutils/tree.c @@ -33,7 +33,7 @@ static void tree_print(unsigned count[2], const char* directory_name, char* pref #if ENABLE_UNICODE_SUPPORT if (unicode_status == UNICODE_ON) { - bar = "│   "; + bar = "│ "; mid = "├── "; end = "└── "; } -- cgit v1.2.3-55-g6feb From d432049f288c9acdc4a7caa729c68ceba3c5dca1 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 25 Aug 2022 18:47:02 +0300 Subject: devmem: add 128-bit width Add 128-bit width if the compiler provides the needed type. function old new delta devmem_main 405 464 +59 .rodata 109025 109043 +18 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 77/0) Total: 77 bytes Signed-off-by: Aaro Koskinen Signed-off-by: Aaro Koskinen Signed-off-by: Denys Vlasenko --- miscutils/devmem.c | 68 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/miscutils/devmem.c b/miscutils/devmem.c index f9f0276bc..f21621bd6 100644 --- a/miscutils/devmem.c +++ b/miscutils/devmem.c @@ -29,7 +29,6 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) { void *map_base, *virt_addr; uint64_t read_result; - uint64_t writeval = writeval; /* for compiler */ off_t target; unsigned page_size, mapped_size, offset_in_page; int fd; @@ -64,9 +63,6 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) width = strchrnul(bhwl, (argv[2][0] | 0x20)) - bhwl; width = sizes[width]; } - /* VALUE */ - if (argv[3]) - writeval = bb_strtoull(argv[3], NULL, 0); } else { /* argv[2] == NULL */ /* make argv[3] to be a valid thing to fetch */ argv--; @@ -96,28 +92,46 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) virt_addr = (char*)map_base + offset_in_page; if (!argv[3]) { - switch (width) { - case 8: - read_result = *(volatile uint8_t*)virt_addr; - break; - case 16: - read_result = *(volatile uint16_t*)virt_addr; - break; - case 32: - read_result = *(volatile uint32_t*)virt_addr; - break; - case 64: - read_result = *(volatile uint64_t*)virt_addr; - break; - default: - bb_simple_error_msg_and_die("bad width"); +#ifdef __SIZEOF_INT128__ + if (width == 128) { + unsigned __int128 rd = + *(volatile unsigned __int128 *)virt_addr; + printf("0x%016llX%016llX\n", + (unsigned long long)(uint64_t)(rd >> 64), + (unsigned long long)(uint64_t)rd + ); + } else +#endif + { + switch (width) { + case 8: + read_result = *(volatile uint8_t*)virt_addr; + break; + case 16: + read_result = *(volatile uint16_t*)virt_addr; + break; + case 32: + read_result = *(volatile uint32_t*)virt_addr; + break; + case 64: + read_result = *(volatile uint64_t*)virt_addr; + break; + default: + bb_simple_error_msg_and_die("bad width"); + } +// printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n", +// target, virt_addr, +// (unsigned long long)read_result); + /* Zero-padded output shows the width of access just done */ + printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result); } -// printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n", -// target, virt_addr, -// (unsigned long long)read_result); - /* Zero-padded output shows the width of access just done */ - printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result); } else { + /* parse VALUE */ +#ifdef __SIZEOF_INT128__ + unsigned __int128 writeval = strtoumax(argv[3], NULL, 0); +#else + uint64_t writeval = bb_strtoull(argv[3], NULL, 0); +#endif switch (width) { case 8: *(volatile uint8_t*)virt_addr = writeval; @@ -135,6 +149,12 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) *(volatile uint64_t*)virt_addr = writeval; // read_result = *(volatile uint64_t*)virt_addr; break; +#ifdef __SIZEOF_INT128__ + case 128: + *(volatile unsigned __int128 *)virt_addr = writeval; +// read_result = *(volatile uint64_t*)virt_addr; + break; +#endif default: bb_simple_error_msg_and_die("bad width"); } -- cgit v1.2.3-55-g6feb From 58598eb7093561d914a6254697e137b815f1fdfc Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Sat, 27 Aug 2022 19:56:21 +0200 Subject: ash: optional sleep builtin function old new delta sleepcmd - 10 +10 builtintab 352 360 +8 .rodata 105264 105271 +7 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/0 up/down: 25/0) Total: 25 bytes Signed-off-by: Shawn Landden Signed-off-by: Denys Vlasenko --- coreutils/sleep.c | 1 + include/libbb.h | 1 + libbb/duration.c | 6 ++++++ shell/ash.c | 11 +++++++++++ 4 files changed, 19 insertions(+) diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 2658e84df..442841210 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -37,6 +37,7 @@ //applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_SLEEP) += sleep.o +//kbuild:lib-$(CONFIG_ASH_SLEEP) += sleep.o /* BB_AUDIT SUSv3 compliant */ /* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */ diff --git a/include/libbb.h b/include/libbb.h index abbc9ac59..19ed9ec09 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1510,6 +1510,7 @@ int ash_main(int argc, char** argv) IF_SHELL_ASH(MAIN_EXTERNALLY_VISIBLE); int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE); /* If shell needs them, they exist even if not enabled as applets */ int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); +int sleep_main(int argc, char **argv) IF_SLEEP(MAIN_EXTERNALLY_VISIBLE); int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); int test_main(int argc, char **argv) #if ENABLE_TEST || ENABLE_TEST1 || ENABLE_TEST2 diff --git a/libbb/duration.c b/libbb/duration.c index a6a29ddae..793d02f42 100644 --- a/libbb/duration.c +++ b/libbb/duration.c @@ -76,6 +76,12 @@ void FAST_FUNC sleep_for_duration(duration_t duration) ts.tv_sec = duration; ts.tv_nsec = (duration - ts.tv_sec) * 1000000000; } + /* NB: if ENABLE_ASH_SLEEP, we end up here if "sleep N" + * is run in ash. ^C will still work, because ash's signal handler + * does not return (it longjumps), the below loop + * will not continue looping. + * (This wouldn't work in hush) + */ do { errno = 0; nanosleep(&ts, &ts); diff --git a/shell/ash.c b/shell/ash.c index 55c1034f5..326f8b2a9 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -134,6 +134,11 @@ //config: default y //config: depends on SHELL_ASH //config: +//config:config ASH_SLEEP +//config: bool "sleep builtin" +//config: default y +//config: depends on SHELL_ASH +//config: //config:config ASH_HELP //config: bool "help builtin" //config: default y @@ -10155,6 +10160,9 @@ static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, #if ENABLE_ASH_TEST || BASH_TEST2 static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } #endif +#if ENABLE_ASH_SLEEP +static int FAST_FUNC sleepcmd(int argc, char **argv) { return sleep_main(argc, argv); } +#endif /* Keep these in proper order since it is searched via bsearch() */ static const struct builtincmd builtintab[] = { @@ -10217,6 +10225,9 @@ static const struct builtincmd builtintab[] = { { BUILTIN_SPEC_REG "return" , returncmd }, { BUILTIN_SPEC_REG "set" , setcmd }, { BUILTIN_SPEC_REG "shift" , shiftcmd }, +#if ENABLE_ASH_SLEEP + { BUILTIN_REGULAR "sleep" , sleepcmd }, +#endif #if BASH_SOURCE { BUILTIN_SPEC_REG "source" , dotcmd }, #endif -- cgit v1.2.3-55-g6feb From fe73c8d55795a8fe7e95fc2c00af6899817b96b8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Aug 2022 16:41:17 +0200 Subject: *: style fix Signed-off-by: Denys Vlasenko --- archival/dpkg.c | 2 +- coreutils/cut.c | 2 +- coreutils/test.c | 2 +- editors/patch.c | 16 ++++++------- editors/patch_toybox.c | 36 ++++++++++++++--------------- editors/vi.c | 2 +- examples/shutdown-1.0/script/hardshutdown.c | 4 ++-- miscutils/bc.c | 2 +- miscutils/devfsd.c | 6 ++--- miscutils/hdparm.c | 24 +++++++++---------- modutils/modutils-24.c | 2 +- networking/tc.c | 2 +- procps/nmeter.c | 4 ++-- 13 files changed, 52 insertions(+), 52 deletions(-) diff --git a/archival/dpkg.c b/archival/dpkg.c index bf070a001..8031956e9 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -1115,7 +1115,7 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count if (package_edge->type == EDGE_PRE_DEPENDS || package_edge->type == EDGE_DEPENDS ) { - int result=1; + int result = 1; status_num = 0; /* If we are inside an alternative then check diff --git a/coreutils/cut.c b/coreutils/cut.c index 7009e74cf..55bdd9386 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c @@ -167,7 +167,7 @@ static void cut_file(FILE *file, const char *delim, const char *odelim, if (!cl_pos && !dcount && !shoe) { if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) goto next_line; - } else if (dcountop_type == BINOP) unnest_msg_and_return(binop(), "1 && *dlist->data != TT.state) + if (TT.state > 1 && *dlist->data != TT.state) fdprintf(TT.state == 2 ? 2 : TT.fileout, - "%s\n", dlist->data+(TT.state>3 ? 1 : 0)); + "%s\n", dlist->data + (TT.state > 3 ? 1 : 0)); if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); @@ -221,7 +221,7 @@ static int apply_one_hunk(void) // Match EOF if there aren't as many ending context lines as beginning for (plist = TT.current_hunk; plist; plist = plist->next) { - if (plist->data[0]==' ') matcheof++; + if (plist->data[0] == ' ') matcheof++; else matcheof = 0; if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); } @@ -433,15 +433,15 @@ int patch_main(int argc UNUSED_PARAM, char **argv) // Are we assembling a hunk? if (state >= 2) { - if (*patchline==' ' || *patchline=='+' || *patchline=='-') { + if (*patchline == ' ' || *patchline == '+' || *patchline == '-') { dlist_add(&TT.current_hunk, patchline); if (*patchline != '+') oldlen--; if (*patchline != '-') newlen--; // Context line? - if (*patchline==' ' && state==2) TT.context++; - else state=3; + if (*patchline == ' ' && state == 2) TT.context++; + else state = 3; // If we've consumed all expected hunk lines, apply the hunk. @@ -469,9 +469,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv) free(*name); // Trim date from end of filename (if any). We don't care. for (s = patchline+4; *s && *s!='\t'; s++) - if (*s=='\\' && s[1]) s++; + if (*s == '\\' && s[1]) s++; i = atoi(s); - if (i>1900 && i<=1970) + if (i > 1900 && i <= 1970) *name = xstrdup("/dev/null"); else { *s = 0; diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c index 69a508b2e..5478ece7d 100644 --- a/editors/patch_toybox.c +++ b/editors/patch_toybox.c @@ -79,7 +79,7 @@ void TOY_llist_free(void *list, void (*freeit)(void *data)) else free(pop); // End doubly linked list too. - if (list==pop) break; + if (list == pop) break; } } @@ -137,11 +137,11 @@ char *get_rawline(int fd, long *plen, char end) long len = 0; for (;;) { - if (1>read(fd, &c, 1)) break; + if (1 > read(fd, &c, 1)) break; if (!(len & 63)) buf=xrealloc(buf, len+65); - if ((buf[len++]=c) == end) break; + if ((buf[len++] = c) == end) break; } - if (buf) buf[len]=0; + if (buf) buf[len] = 0; if (plen) *plen = len; return buf; @@ -153,7 +153,7 @@ char *get_line(int fd) long len; char *buf = get_rawline(fd, &len, '\n'); - if (buf && buf[--len]=='\n') buf[len]=0; + if (buf && buf[--len] == '\n') buf[len] = 0; return buf; } @@ -165,10 +165,10 @@ void xsendfile(int in, int out) long len; char buf[4096]; - if (in<0) return; + if (in < 0) return; for (;;) { len = safe_read(in, buf, 4096); - if (len<1) break; + if (len < 1) break; xwrite(out, buf, len); } } @@ -179,7 +179,7 @@ void replace_tempfile(int fdin, int fdout, char **tempname) { char *temp = xstrdup(*tempname); - temp[strlen(temp)-6]=0; + temp[strlen(temp)-6] = 0; if (fdin != -1) { xsendfile(fdin, fdout); xclose(fdin); @@ -263,9 +263,9 @@ static void do_line(void *data) { struct double_list *dlist = (struct double_list *)data; - if (TT.state>1 && *dlist->data != TT.state) + if (TT.state > 1 && *dlist->data != TT.state) fdprintf(TT.state == 2 ? 2 : TT.fileout, - "%s\n", dlist->data+(TT.state>3 ? 1 : 0)); + "%s\n", dlist->data + (TT.state > 3 ? 1 : 0)); if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); @@ -314,7 +314,7 @@ static int apply_one_hunk(void) // Match EOF if there aren't as many ending context lines as beginning for (plist = TT.current_hunk; plist; plist = plist->next) { - if (plist->data[0]==' ') matcheof++; + if (plist->data[0] == ' ') matcheof++; else matcheof = 0; if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); } @@ -385,7 +385,7 @@ static int apply_one_hunk(void) // If we've reached the end of the buffer without confirming a // match, read more lines. - if (check==buf) { + if (check == buf) { buf = 0; break; } @@ -456,15 +456,15 @@ int patch_main(int argc UNUSED_PARAM, char **argv) // Are we assembling a hunk? if (state >= 2) { - if (*patchline==' ' || *patchline=='+' || *patchline=='-') { + if (*patchline == ' ' || *patchline == '+' || *patchline == '-') { dlist_add(&TT.current_hunk, patchline); if (*patchline != '+') TT.oldlen--; if (*patchline != '-') TT.newlen--; // Context line? - if (*patchline==' ' && state==2) TT.context++; - else state=3; + if (*patchline == ' ' && state == 2) TT.context++; + else state = 3; // If we've consumed all expected hunk lines, apply the hunk. @@ -491,9 +491,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv) // Trim date from end of filename (if any). We don't care. for (s = patchline+4; *s && *s!='\t'; s++) - if (*s=='\\' && s[1]) s++; + if (*s == '\\' && s[1]) s++; i = atoi(s); - if (i>1900 && i<=1970) + if (i > 1900 && i <= 1970) *name = xstrdup("/dev/null"); else { *s = 0; @@ -537,7 +537,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) // handle -p path truncation. for (i=0, s = name; *s;) { if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) break; - if (*(s++)=='/') { + if (*(s++) == '/') { name = s; i++; } diff --git a/editors/vi.c b/editors/vi.c index 1f997e8e5..2645afe87 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -4327,7 +4327,7 @@ static void do_cmd(int c) c1 = get_one_char(); // ZQ means to exit without saving if (c1 == 'Q') { - editing=0; + editing = 0; optind = cmdline_filecnt; break; } diff --git a/examples/shutdown-1.0/script/hardshutdown.c b/examples/shutdown-1.0/script/hardshutdown.c index b4af26f0f..c90f55396 100644 --- a/examples/shutdown-1.0/script/hardshutdown.c +++ b/examples/shutdown-1.0/script/hardshutdown.c @@ -115,7 +115,7 @@ int main(int argc, char **argv) if (ptr) prog = ptr+1; - for (c=1; c < argc; c++) { + for (c = 1; c < argc; c++) { if (argv[c][0] >= '0' && argv[c][0] <= '9') { t.tv_sec = strtol(argv[c], NULL, 10); continue; @@ -124,7 +124,7 @@ int main(int argc, char **argv) usage(); return 1; } - for (i=1; argv[c][i]; i++) { + for (i = 1; argv[c][i]; i++) { switch (argv[c][i]) { case 'h': action = HALT; diff --git a/miscutils/bc.c b/miscutils/bc.c index 1300a63fb..c629c4763 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3105,7 +3105,7 @@ static BC_STATUS zbc_lex_identifier(void) continue; match: // buf starts with keyword bc_lex_kws[i] - if (isalnum(buf[j]) || buf[j]=='_') + if (isalnum(buf[j]) || buf[j] == '_') continue; // "ifz" does not match "if" keyword, "if." does p->lex = BC_LEX_KEY_1st_keyword + i; if (!keyword_is_POSIX(i)) { diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index fb9ebcf60..297693f8c 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c @@ -976,7 +976,7 @@ static void action_compat(const struct devfsd_notify_struct *info, unsigned int rewind_ = info->devname[info->namelen - 1]; if (rewind_ != 'n') rewind_ = '\0'; - mode=0; + mode = 0; if (ptr[2] == 'l' /*108*/ || ptr[2] == 'm'/*109*/) mode = ptr[2] - 107; /* 1 or 2 */ if (ptr[2] == 'a') @@ -1595,11 +1595,11 @@ static char *write_old_sd_name(char *buffer, return buffer; } if ((major > 64) && (major < 72)) { - disc_index = ((major - 64) << 4) +(minor >> 4); + disc_index = ((major - 64) << 4) + (minor >> 4); if (disc_index < 26) sprintf(buffer, "sd%c%s", 'a' + disc_index, part); else - sprintf(buffer, "sd%c%c%s", 'a' +(disc_index / 26) - 1, 'a' + disc_index % 26, part); + sprintf(buffer, "sd%c%c%s", 'a' + (disc_index / 26) - 1, 'a' + disc_index % 26, part); return buffer; } return NULL; diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index d8d8f6166..83e2f8d53 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c @@ -798,7 +798,7 @@ static void identify(uint16_t *val) if (!(val[GEN_CONFIG] & NOT_ATA)) { dev = ATA_DEV; printf("ATA device, with "); - } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) { + } else if (val[GEN_CONFIG] == CFA_SUPPORT_VAL) { dev = ATA_DEV; like_std = 4; printf("CompactFlash ATA device, with "); @@ -819,13 +819,13 @@ static void identify(uint16_t *val) * specific, it should be safe to check it now, even though we don't * know yet what standard this device is using. */ - if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) - || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) + if ((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == STBY_ID_VAL) + || (val[CONFIG] == PWRD_NID_VAL) || (val[CONFIG] == PWRD_ID_VAL) ) { like_std = 5; - if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)) + if ((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == STBY_ID_VAL)) puts("powers-up in standby; SET FEATURES subcmd spins-up."); - if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE)) + if (((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE)) puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n"); } @@ -853,7 +853,7 @@ static void identify(uint16_t *val) printf("\n\tSupported: "); jj = val[MAJOR] << 1; kk = like_std >4 ? like_std-4: 0; - for (ii = 14; (ii >0)&&(ii>kk); ii--) { + for (ii = 14; (ii > 0) && (ii > kk); ii--) { if (jj & 0x8000) { printf("%u ", ii); if (like_std < ii) { @@ -943,7 +943,7 @@ static void identify(uint16_t *val) for (ii = 1; ii < 15; ii++) { if (jj & 0x0001) printf("\t%s\n", nth_string(ata1_cfg_str, ii)); - jj >>=1; + jj >>= 1; } } if (dev == ATAPI_DEV) { @@ -952,7 +952,7 @@ static void identify(uint16_t *val) else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL) strng = "<=10ms with INTRQ"; else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL) - strng ="50us"; + strng = "50us"; else strng = "unknown"; printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ @@ -1014,7 +1014,7 @@ static void identify(uint16_t *val) } if (!bbbig) - bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */ + bbbig = (uint64_t)(ll > mm ? ll : mm); /* # 512 byte blocks */ printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11); bbbig = (bbbig << 9) / 1000000; printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig); @@ -1160,7 +1160,7 @@ static void identify(uint16_t *val) jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; for (ii = 0; ii <= PIO_MODE_MAX; ii++) { if (jj & 0x0001) printf("pio%d ", ii); - jj >>=1; + jj >>= 1; } bb_putchar('\n'); } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) { @@ -1199,7 +1199,7 @@ static void identify(uint16_t *val) } if (ii == 31) { if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL) - ii +=16; + ii += 16; } } } @@ -1220,7 +1220,7 @@ static void identify(uint16_t *val) printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "", nth_string(secu_str, ii)); - jj >>=1; + jj >>= 1; } if (val[SECU_STATUS] & SECU_ENABLED) { printf("\tSecurity level %s\n", diff --git a/modutils/modutils-24.c b/modutils/modutils-24.c index d0bc2a6ef..37c303f90 100644 --- a/modutils/modutils-24.c +++ b/modutils/modutils-24.c @@ -981,7 +981,7 @@ arch_apply_relocation(struct obj_file *f, (loc[1] & 0xFFFF); /* Add reloc offset */ - temp1+=v; + temp1 += v; /* Store back into code */ loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16; diff --git a/networking/tc.c b/networking/tc.c index 46ad23d8b..43187f7ee 100644 --- a/networking/tc.c +++ b/networking/tc.c @@ -214,7 +214,7 @@ static int prio_print_opt(struct rtattr *opt) return 0; parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt)); printf("bands %u priomap ", qopt->bands); - for (i=0; i<=TC_PRIO_MAX; i++) + for (i = 0; i <= TC_PRIO_MAX; i++) printf(" %d", qopt->priomap[i]); if (tb[TCA_PRIO_MQ]) diff --git a/procps/nmeter.c b/procps/nmeter.c index 088d366bf..68e6f3325 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -515,7 +515,7 @@ static void FAST_FUNC collect_blk(blk_stat *s) return; } - for (i=0; i<2; i++) { + for (i = 0; i < 2; i++) { ullong old = s->old[i]; if (data[i] < old) old = data[i]; //sanitize s->old[i] = data[i]; @@ -597,7 +597,7 @@ static void FAST_FUNC collect_if(if_stat *s) return; } - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { ullong old = s->old[i]; if (data[i] < old) old = data[i]; //sanitize s->old[i] = data[i]; -- cgit v1.2.3-55-g6feb From dd79e1d4d3b9725e927d1c26e0d3fdb49e29ba9c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Aug 2022 17:12:34 +0200 Subject: fix [ --help ] and [[ --help ]] function old new delta show_usage_if_dash_dash_help 72 79 +7 Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 9b9d7dbd6..d5335d353 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -937,6 +937,9 @@ void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv) # endif # if defined APPLET_NO_echo && applet_no != APPLET_NO_echo +# endif +# if ENABLE_TEST1 || ENABLE_TEST2 + && argv[0][0] != '[' /* exclude [ --help ] and [[ --help ]] too */ # endif ) { if (argv[1] && strcmp(argv[1], "--help") == 0) { -- cgit v1.2.3-55-g6feb From 526625bc83e63e6e5a3ec5296a1b868e72b3b01e Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Thu, 25 Aug 2022 12:48:07 +0200 Subject: libbb: mark stack in assembly files read-only Signed-off-by: Ludwig Nussel Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha256_x86-32_shaNI.S | 3 +++ libbb/hash_md5_sha256_x86-64_shaNI.S | 3 +++ libbb/hash_md5_sha_x86-32_shaNI.S | 3 +++ libbb/hash_md5_sha_x86-64.S | 3 +++ libbb/hash_md5_sha_x86-64.S.sh | 3 +++ libbb/hash_md5_sha_x86-64_shaNI.S | 3 +++ 6 files changed, 18 insertions(+) diff --git a/libbb/hash_md5_sha256_x86-32_shaNI.S b/libbb/hash_md5_sha256_x86-32_shaNI.S index 3905bad9a..a0e4a571a 100644 --- a/libbb/hash_md5_sha256_x86-32_shaNI.S +++ b/libbb/hash_md5_sha256_x86-32_shaNI.S @@ -19,6 +19,9 @@ // We do not check SSSE3 in cpuid, // all SHA-capable CPUs support it as well. +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif .section .text.sha256_process_block64_shaNI, "ax", @progbits .globl sha256_process_block64_shaNI .hidden sha256_process_block64_shaNI diff --git a/libbb/hash_md5_sha256_x86-64_shaNI.S b/libbb/hash_md5_sha256_x86-64_shaNI.S index 082ceafe4..172c2eae2 100644 --- a/libbb/hash_md5_sha256_x86-64_shaNI.S +++ b/libbb/hash_md5_sha256_x86-64_shaNI.S @@ -19,6 +19,9 @@ // We do not check SSSE3 in cpuid, // all SHA-capable CPUs support it as well. +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif .section .text.sha256_process_block64_shaNI, "ax", @progbits .globl sha256_process_block64_shaNI .hidden sha256_process_block64_shaNI diff --git a/libbb/hash_md5_sha_x86-32_shaNI.S b/libbb/hash_md5_sha_x86-32_shaNI.S index 2366b046a..7455a29f0 100644 --- a/libbb/hash_md5_sha_x86-32_shaNI.S +++ b/libbb/hash_md5_sha_x86-32_shaNI.S @@ -25,6 +25,9 @@ // We do not check SSSE3/SSE4.1 in cpuid, // all SHA-capable CPUs support them as well. +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif .section .text.sha1_process_block64_shaNI, "ax", @progbits .globl sha1_process_block64_shaNI .hidden sha1_process_block64_shaNI diff --git a/libbb/hash_md5_sha_x86-64.S b/libbb/hash_md5_sha_x86-64.S index 1d55b91f8..2cdd22015 100644 --- a/libbb/hash_md5_sha_x86-64.S +++ b/libbb/hash_md5_sha_x86-64.S @@ -1,6 +1,9 @@ ### Generated by hash_md5_sha_x86-64.S.sh ### #if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif .section .text.sha1_process_block64, "ax", @progbits .globl sha1_process_block64 .hidden sha1_process_block64 diff --git a/libbb/hash_md5_sha_x86-64.S.sh b/libbb/hash_md5_sha_x86-64.S.sh index 40c979d35..653fe4989 100755 --- a/libbb/hash_md5_sha_x86-64.S.sh +++ b/libbb/hash_md5_sha_x86-64.S.sh @@ -127,6 +127,9 @@ echo \ "### Generated by hash_md5_sha_x86-64.S.sh ### #if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) +#ifdef __linux__ + .section .note.GNU-stack, \"\", @progbits +#endif .section .text.sha1_process_block64, \"ax\", @progbits .globl sha1_process_block64 .hidden sha1_process_block64 diff --git a/libbb/hash_md5_sha_x86-64_shaNI.S b/libbb/hash_md5_sha_x86-64_shaNI.S index 794e97040..2f03e1ce4 100644 --- a/libbb/hash_md5_sha_x86-64_shaNI.S +++ b/libbb/hash_md5_sha_x86-64_shaNI.S @@ -25,6 +25,9 @@ // We do not check SSSE3/SSE4.1 in cpuid, // all SHA-capable CPUs support them as well. +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif .section .text.sha1_process_block64_shaNI, "ax", @progbits .globl sha1_process_block64_shaNI .hidden sha1_process_block64_shaNI -- cgit v1.2.3-55-g6feb From 9bab580cd4337a3b9daf7d63f1fc863b7a569ae0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Sep 2022 16:31:44 +0200 Subject: tls: include signature_algorithms extension in client hello message function old new delta tls_xread_record 629 645 +16 .rodata 105167 105179 +12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 28/0) Total: 28 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 91 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 415952f16..935ca76a4 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -948,11 +948,46 @@ static int tls_has_buffered_record(tls_state_t *tls) static const char *alert_text(int code) { + //10 unexpected_message + //20 bad_record_mac + //21 decryption_failed + //22 record_overflow + //30 decompression_failure + //40 handshake_failure + //41 no_certificate + //42 bad_certificate + //43 unsupported_certificate + //44 certificate_revoked + //45 certificate_expired + //46 certificate_unknown + //47 illegal_parameter + //48 unknown_ca + //49 access_denied + //50 decode_error + //51 decrypt_error + //52 too_many_cids_requested + //60 export_restriction + //70 protocol_version + //71 insufficient_security + //80 internal_error + //86 inappropriate_fallback + //90 user_canceled + //100 no_renegotiation + //109 missing_extension + //110 unsupported_extension + //111 certificate_unobtainable + //112 unrecognized_name + //113 bad_certificate_status_response + //114 bad_certificate_hash_value + //115 unknown_psk_identity + //116 certificate_required + //120 no_application_protocol switch (code) { case 20: return "bad MAC"; case 50: return "decode error"; - case 51: return "decrypt error"; case 40: return "handshake failure"; + case 51: return "decrypt error"; + case 80: return "internal error"; case 112: return "unrecognized name"; } return itoa(code); @@ -1531,26 +1566,47 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) #endif 0x01,0x00, //not a cipher - comprtypes_len, comprtype }; - static const uint8_t supported_groups[] = { + // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml + static const uint8_t extensions[] = { + // is.gd responds with "handshake failure" to our hello if there's no supported_groups 0x00,0x0a, //extension_type: "supported_groups" - 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len - 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len + 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len + 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len #if ALLOW_CURVE_P256 - 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1) + 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1) #endif - //0x00,0x18, //curve_secp384r1 - //0x00,0x19, //curve_secp521r1 + //0x00,0x18, //curve_secp384r1 + //0x00,0x19, //curve_secp521r1 #if ALLOW_CURVE_X25519 - 0x00,0x1d, //curve_x25519 (RFC 7748) + 0x00,0x1d, //curve_x25519 (RFC 7748) +#endif + //0x00,0x1e, //curve_x448 (RFC 7748) + + //0x00,0x0b,0x00,0x04,0x03,0x00,0x01,0x02, //extension_type: "ec_point_formats" + //0x00,0x16,0x00,0x00, //extension_type: "encrpypt-then-mac" + //0x00,0x17,0x00,0x00, //extension_type: "extended_master" + //0x00,0x23,0x00,0x00, //extension_type: "session_ticket" + + // kojipkgs.fedoraproject.org responds with alert code 80 ("internal error") + // to our hello without signature_algorithms. + // It is satisfied with just 0x04,0x01. + 0x00,0x0d, //extension_type: "signature_algorithms" (RFC5246 section 7.4.1.4.1): +#define SIGALGS (3 + 3 * ENABLE_FEATURE_TLS_SHA1) + 0x00,2 * (1 + SIGALGS), //ext len + 0x00,2 * (0 + SIGALGS), //list len + //Format: two bytes + // byte 1: 0:none,1:md5,2:sha1,3:sha224,4:sha256,5:sha384,6:sha512 + // byte 2: 1:rsa,2:dsa,3:ecdsa + // (note that TLS 1.3 changes this, see RFC8446 section 4.2.3) +#if ENABLE_FEATURE_TLS_SHA1 + 0x02,0x01, //sha1 + rsa + 0x02,0x02, //sha1 + dsa + 0x02,0x03, //sha1 + ecdsa #endif - //0x00,0x1e, //curve_x448 (RFC 7748) + 0x04,0x01, //sha256 + rsa - kojipkgs.fedoraproject.org wants this + 0x04,0x02, //sha256 + dsa + 0x04,0x03, //sha256 + ecdsa }; - //static const uint8_t signature_algorithms[] = { - // 000d - // 0020 - // 001e - // 0601 0602 0603 0501 0502 0503 0401 0402 0403 0301 0302 0303 0201 0202 0203 - //}; struct client_hello { uint8_t type; @@ -1591,8 +1647,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) int sni_len = sni ? strnlen(sni, 127 - 5) : 0; ext_len = 0; - /* is.gd responds with "handshake failure" to our hello if there's no supported_groups element */ - ext_len += sizeof(supported_groups); + ext_len += sizeof(extensions); if (sni_len) ext_len += 9 + sni_len; @@ -1626,7 +1681,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) ptr[8] = sni_len; //name len ptr = mempcpy(&ptr[9], sni, sni_len); } - memcpy(ptr, supported_groups, sizeof(supported_groups)); + memcpy(ptr, extensions, sizeof(extensions)); tls->hsd = xzalloc(sizeof(*tls->hsd)); /* HANDSHAKE HASH: ^^^ + len if need to save saved_client_hello */ -- cgit v1.2.3-55-g6feb From c8c1fcdba163f264a503380bc63485aacd09214c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Sep 2022 16:56:54 +0200 Subject: tls: move definitions around, no code changes Signed-off-by: Denys Vlasenko --- networking/tls.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 935ca76a4..8d074c058 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1566,6 +1566,18 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) #endif 0x01,0x00, //not a cipher - comprtypes_len, comprtype }; + struct client_hello { + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t proto_maj, proto_min; + uint8_t rand32[32]; + uint8_t session_id_len; + /* uint8_t session_id[]; */ + uint8_t cipherid_len16_hi, cipherid_len16_lo; + uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ + uint8_t comprtypes_len; + uint8_t comprtypes[1]; /* actually variable */ + }; // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml static const uint8_t extensions[] = { // is.gd responds with "handshake failure" to our hello if there's no supported_groups @@ -1606,28 +1618,6 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 0x04,0x01, //sha256 + rsa - kojipkgs.fedoraproject.org wants this 0x04,0x02, //sha256 + dsa 0x04,0x03, //sha256 + ecdsa - }; - - struct client_hello { - uint8_t type; - uint8_t len24_hi, len24_mid, len24_lo; - uint8_t proto_maj, proto_min; - uint8_t rand32[32]; - uint8_t session_id_len; - /* uint8_t session_id[]; */ - uint8_t cipherid_len16_hi, cipherid_len16_lo; - uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ - uint8_t comprtypes_len; - uint8_t comprtypes[1]; /* actually variable */ - /* Extensions (SNI shown): - * hi,lo // len of all extensions - * 00,00 // extension_type: "Server Name" - * 00,0e // list len (there can be more than one SNI) - * 00,0c // len of 1st Server Name Indication - * 00 // name type: host_name - * 00,09 // name len - * "localhost" // name - */ // GNU Wget 1.18 to cdn.kernel.org sends these extensions: // 0055 // 0005 0005 0100000000 - status_request -- cgit v1.2.3-55-g6feb