diff options
67 files changed, 2156 insertions, 1604 deletions
diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 062fd0f54..74f957544 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c | |||
@@ -107,7 +107,7 @@ void fallbackSimpleSort(uint32_t* fmap, | |||
107 | #define FALLBACK_QSORT_SMALL_THRESH 10 | 107 | #define FALLBACK_QSORT_SMALL_THRESH 10 |
108 | #define FALLBACK_QSORT_STACK_SIZE 100 | 108 | #define FALLBACK_QSORT_STACK_SIZE 100 |
109 | 109 | ||
110 | static | 110 | static NOINLINE |
111 | void fallbackQSort3(uint32_t* fmap, | 111 | void fallbackQSort3(uint32_t* fmap, |
112 | uint32_t* eclass, | 112 | uint32_t* eclass, |
113 | int32_t loSt, | 113 | int32_t loSt, |
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index 2ab3c04b8..d26868bf8 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c | |||
@@ -147,6 +147,12 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g | |||
147 | #endif | 147 | #endif |
148 | } | 148 | } |
149 | 149 | ||
150 | static void die_if_bad_fnamesize(off_t sz) | ||
151 | { | ||
152 | if ((uoff_t)sz > 0xfff) /* more than 4k?! no funny business please */ | ||
153 | bb_simple_error_msg_and_die("bad archive"); | ||
154 | } | ||
155 | |||
150 | char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | 156 | char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) |
151 | { | 157 | { |
152 | file_header_t *file_header = archive_handle->file_header; | 158 | file_header_t *file_header = archive_handle->file_header; |
@@ -331,8 +337,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
331 | file_header->name = xstrdup(tar.name); | 337 | file_header->name = xstrdup(tar.name); |
332 | } | 338 | } |
333 | 339 | ||
334 | /* Set bits 12-15 of the files mode */ | ||
335 | /* (typeflag was not trashed because chksum does not use getOctal) */ | ||
336 | switch (tar_typeflag) { | 340 | switch (tar_typeflag) { |
337 | case '1': /* hardlink */ | 341 | case '1': /* hardlink */ |
338 | /* we mark hardlinks as regular files with zero size and a link name */ | 342 | /* we mark hardlinks as regular files with zero size and a link name */ |
@@ -341,7 +345,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
341 | * ... For tar archives written by pre POSIX.1-1988 | 345 | * ... For tar archives written by pre POSIX.1-1988 |
342 | * implementations, the size field usually contains the size of | 346 | * implementations, the size field usually contains the size of |
343 | * the file and needs to be ignored as no data may follow this | 347 | * the file and needs to be ignored as no data may follow this |
344 | * header type. For POSIX.1- 1988 compliant archives, the size | 348 | * header type. For POSIX.1-1988 compliant archives, the size |
345 | * field needs to be 0. For POSIX.1-2001 compliant archives, | 349 | * field needs to be 0. For POSIX.1-2001 compliant archives, |
346 | * the size field may be non zero, indicating that file data is | 350 | * the size field may be non zero, indicating that file data is |
347 | * included in the archive. | 351 | * included in the archive. |
@@ -390,6 +394,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
390 | /* free: paranoia: tar with several consecutive longnames */ | 394 | /* free: paranoia: tar with several consecutive longnames */ |
391 | free(p_longname); | 395 | free(p_longname); |
392 | /* For paranoia reasons we allocate extra NUL char */ | 396 | /* For paranoia reasons we allocate extra NUL char */ |
397 | die_if_bad_fnamesize(file_header->size); | ||
393 | p_longname = xzalloc(file_header->size + 1); | 398 | p_longname = xzalloc(file_header->size + 1); |
394 | /* We read ASCIZ string, including NUL */ | 399 | /* We read ASCIZ string, including NUL */ |
395 | xread(archive_handle->src_fd, p_longname, file_header->size); | 400 | xread(archive_handle->src_fd, p_longname, file_header->size); |
@@ -400,6 +405,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
400 | goto again; | 405 | goto again; |
401 | case 'K': | 406 | case 'K': |
402 | free(p_linkname); | 407 | free(p_linkname); |
408 | die_if_bad_fnamesize(file_header->size); | ||
403 | p_linkname = xzalloc(file_header->size + 1); | 409 | p_linkname = xzalloc(file_header->size + 1); |
404 | xread(archive_handle->src_fd, p_linkname, file_header->size); | 410 | xread(archive_handle->src_fd, p_linkname, file_header->size); |
405 | archive_handle->offset += file_header->size; | 411 | archive_handle->offset += file_header->size; |
diff --git a/archival/libarchive/unxz/xz_dec_stream.c b/archival/libarchive/unxz/xz_dec_stream.c index bf791055b..31158b4e8 100644 --- a/archival/libarchive/unxz/xz_dec_stream.c +++ b/archival/libarchive/unxz/xz_dec_stream.c | |||
@@ -545,7 +545,7 @@ static enum xz_ret XZ_FUNC dec_block_header(struct xz_dec *s) | |||
545 | return XZ_OK; | 545 | return XZ_OK; |
546 | } | 546 | } |
547 | 547 | ||
548 | static enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b) | 548 | static NOINLINE enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b) |
549 | { | 549 | { |
550 | enum xz_ret ret; | 550 | enum xz_ret ret; |
551 | 551 | ||
diff --git a/console-tools/resize.c b/console-tools/resize.c index 59d468d48..056e33750 100644 --- a/console-tools/resize.c +++ b/console-tools/resize.c | |||
@@ -74,7 +74,19 @@ int resize_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
74 | + (1 << SIGTERM) | 74 | + (1 << SIGTERM) |
75 | + (1 << SIGALRM) | 75 | + (1 << SIGALRM) |
76 | , onintr); | 76 | , onintr); |
77 | tcsetattr(STDERR_FILENO, TCSANOW, &new); | 77 | /* Users report: |
78 | * The resize command messes up the terminal. | ||
79 | * In my case it looks like it is hanging and | ||
80 | * I need to press ctrl-c to get a prompt. | ||
81 | * Actually the program does not hang but just | ||
82 | * the terminal is messed up. | ||
83 | * Replaced TCSANOW with TCSAFLUSH: | ||
84 | * "the change occurs after all output written to fd | ||
85 | * has been transmitted, and all input that has been | ||
86 | * received but not read will be discarded before | ||
87 | * the change is made. | ||
88 | */ | ||
89 | tcsetattr(STDERR_FILENO, TCSAFLUSH, &new); | ||
78 | 90 | ||
79 | /* save_cursor_pos 7 | 91 | /* save_cursor_pos 7 |
80 | * scroll_whole_screen [r | 92 | * scroll_whole_screen [r |
diff --git a/coreutils/Config.src b/coreutils/Config.src index 1bded03a6..6c9e47551 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src | |||
@@ -5,10 +5,6 @@ | |||
5 | 5 | ||
6 | menu "Coreutils" | 6 | menu "Coreutils" |
7 | 7 | ||
8 | INSERT | ||
9 | |||
10 | comment "Common options" | ||
11 | |||
12 | config FEATURE_VERBOSE | 8 | config FEATURE_VERBOSE |
13 | bool "Support verbose options (usually -v) for various applets" | 9 | bool "Support verbose options (usually -v) for various applets" |
14 | default y | 10 | default y |
@@ -17,6 +13,19 @@ config FEATURE_VERBOSE | |||
17 | Also enables long option (--verbose) if it exists. | 13 | Also enables long option (--verbose) if it exists. |
18 | Without this option, -v is accepted but ignored. | 14 | Without this option, -v is accepted but ignored. |
19 | 15 | ||
16 | comment "Common options for date and touch" | ||
17 | |||
18 | config FEATURE_TIMEZONE | ||
19 | bool "Allow timezone in dates" | ||
20 | default y | ||
21 | depends on DESKTOP | ||
22 | help | ||
23 | Permit the use of timezones when parsing user-provided data | ||
24 | strings, e.g. '1996-04-09 12:45:00 -0500'. | ||
25 | |||
26 | This requires support for the '%z' extension to strptime() which | ||
27 | may not be available in all implementations. | ||
28 | |||
20 | comment "Common options for cp and mv" | 29 | comment "Common options for cp and mv" |
21 | depends on CP || MV | 30 | depends on CP || MV |
22 | 31 | ||
@@ -37,4 +46,6 @@ config FEATURE_HUMAN_READABLE | |||
37 | help | 46 | help |
38 | Allow df, du, and ls to have human readable output. | 47 | Allow df, du, and ls to have human readable output. |
39 | 48 | ||
49 | INSERT | ||
50 | |||
40 | endmenu | 51 | endmenu |
diff --git a/coreutils/df.c b/coreutils/df.c index 9f8b3a71e..176aa079f 100644 --- a/coreutils/df.c +++ b/coreutils/df.c | |||
@@ -32,6 +32,26 @@ | |||
32 | //config: -a Show all filesystems | 32 | //config: -a Show all filesystems |
33 | //config: -i Inodes | 33 | //config: -i Inodes |
34 | //config: -B <SIZE> Blocksize | 34 | //config: -B <SIZE> Blocksize |
35 | //config: | ||
36 | //config:config FEATURE_SKIP_ROOTFS | ||
37 | //config: bool "Skip rootfs in mount table" | ||
38 | //config: default y | ||
39 | //config: depends on DF | ||
40 | //config: help | ||
41 | //config: Ignore rootfs entry in mount table. | ||
42 | //config: | ||
43 | //config: In Linux, kernel has a special filesystem, rootfs, which is initially | ||
44 | //config: mounted on /. It contains initramfs data, if kernel is configured | ||
45 | //config: to have one. Usually, another file system is mounted over / early | ||
46 | //config: in boot process, and therefore most tools which manipulate | ||
47 | //config: mount table, such as df, will skip rootfs entry. | ||
48 | //config: | ||
49 | //config: However, some systems do not mount anything on /. | ||
50 | //config: If you need to configure busybox for one of these systems, | ||
51 | //config: you may find it useful to turn this option off to make df show | ||
52 | //config: initramfs statistics. | ||
53 | //config: | ||
54 | //config: Otherwise, choose Y. | ||
35 | 55 | ||
36 | //applet:IF_DF(APPLET_NOEXEC(df, df, BB_DIR_BIN, BB_SUID_DROP, df)) | 56 | //applet:IF_DF(APPLET_NOEXEC(df, df, BB_DIR_BIN, BB_SUID_DROP, df)) |
37 | 57 | ||
diff --git a/coreutils/mktemp.c b/coreutils/mktemp.c index 5393320a5..33e2720de 100644 --- a/coreutils/mktemp.c +++ b/coreutils/mktemp.c | |||
@@ -72,13 +72,27 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv) | |||
72 | OPT_t = 1 << 2, | 72 | OPT_t = 1 << 2, |
73 | OPT_p = 1 << 3, | 73 | OPT_p = 1 << 3, |
74 | OPT_u = 1 << 4, | 74 | OPT_u = 1 << 4, |
75 | OPT_tmpdir = (1 << 5) * ENABLE_LONG_OPTS, | ||
75 | }; | 76 | }; |
76 | 77 | ||
77 | path = getenv("TMPDIR"); | 78 | path = getenv("TMPDIR"); |
78 | if (!path || path[0] == '\0') | 79 | if (!path || path[0] == '\0') |
79 | path = "/tmp"; | 80 | path = "/tmp"; |
80 | 81 | ||
82 | #if ENABLE_LONG_OPTS | ||
83 | opts = getopt32long(argv, "^" | ||
84 | "dqtp:u" | ||
85 | "\0" | ||
86 | "?1" /* 1 arg max */, | ||
87 | "directory\0" No_argument "d" | ||
88 | "quiet\0" No_argument "q" | ||
89 | "dry-run\0" No_argument "u" | ||
90 | "tmpdir\0" Optional_argument "\xff" | ||
91 | , &path, &path | ||
92 | ); | ||
93 | #else | ||
81 | opts = getopt32(argv, "^" "dqtp:u" "\0" "?1"/*1 arg max*/, &path); | 94 | opts = getopt32(argv, "^" "dqtp:u" "\0" "?1"/*1 arg max*/, &path); |
95 | #endif | ||
82 | 96 | ||
83 | chp = argv[optind]; | 97 | chp = argv[optind]; |
84 | if (!chp) { | 98 | if (!chp) { |
@@ -95,7 +109,7 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv) | |||
95 | goto error; | 109 | goto error; |
96 | } | 110 | } |
97 | #endif | 111 | #endif |
98 | if (opts & (OPT_t|OPT_p)) | 112 | if (opts & (OPT_t|OPT_p|OPT_tmpdir)) |
99 | chp = concat_path_file(path, chp); | 113 | chp = concat_path_file(path, chp); |
100 | 114 | ||
101 | if (opts & OPT_u) { | 115 | if (opts & OPT_u) { |
diff --git a/coreutils/test.c b/coreutils/test.c index 7c6574334..a914c7490 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -435,7 +435,7 @@ struct test_statics { | |||
435 | }; | 435 | }; |
436 | 436 | ||
437 | /* See test_ptr_hack.c */ | 437 | /* See test_ptr_hack.c */ |
438 | extern struct test_statics *const test_ptr_to_statics; | 438 | extern struct test_statics *BB_GLOBAL_CONST test_ptr_to_statics; |
439 | 439 | ||
440 | #define S (*test_ptr_to_statics) | 440 | #define S (*test_ptr_to_statics) |
441 | #define args (S.args ) | 441 | #define args (S.args ) |
@@ -446,8 +446,7 @@ extern struct test_statics *const test_ptr_to_statics; | |||
446 | #define leaving (S.leaving ) | 446 | #define leaving (S.leaving ) |
447 | 447 | ||
448 | #define INIT_S() do { \ | 448 | #define INIT_S() do { \ |
449 | (*(struct test_statics**)not_const_pp(&test_ptr_to_statics)) = xzalloc(sizeof(S)); \ | 449 | XZALLOC_CONST_PTR(&test_ptr_to_statics, sizeof(S)); \ |
450 | barrier(); \ | ||
451 | } while (0) | 450 | } while (0) |
452 | #define DEINIT_S() do { \ | 451 | #define DEINIT_S() do { \ |
453 | free(group_array); \ | 452 | free(group_array); \ |
diff --git a/editors/ed.c b/editors/ed.c index c50faeefa..14540e566 100644 --- a/editors/ed.c +++ b/editors/ed.c | |||
@@ -380,7 +380,8 @@ static void addLines(int num) | |||
380 | static int readLines(const char *file, int num) | 380 | static int readLines(const char *file, int num) |
381 | { | 381 | { |
382 | int fd, cc; | 382 | int fd, cc; |
383 | int len, lineCount, charCount; | 383 | int len; |
384 | unsigned charCount; | ||
384 | char *cp; | 385 | char *cp; |
385 | 386 | ||
386 | if ((num < 1) || (num > lastNum + 1)) { | 387 | if ((num < 1) || (num > lastNum + 1)) { |
@@ -396,7 +397,6 @@ static int readLines(const char *file, int num) | |||
396 | 397 | ||
397 | bufPtr = bufBase; | 398 | bufPtr = bufBase; |
398 | bufUsed = 0; | 399 | bufUsed = 0; |
399 | lineCount = 0; | ||
400 | charCount = 0; | 400 | charCount = 0; |
401 | cc = 0; | 401 | cc = 0; |
402 | 402 | ||
@@ -415,7 +415,6 @@ static int readLines(const char *file, int num) | |||
415 | bufPtr += len; | 415 | bufPtr += len; |
416 | bufUsed -= len; | 416 | bufUsed -= len; |
417 | charCount += len; | 417 | charCount += len; |
418 | lineCount++; | ||
419 | num++; | 418 | num++; |
420 | continue; | 419 | continue; |
421 | } | 420 | } |
@@ -449,15 +448,18 @@ static int readLines(const char *file, int num) | |||
449 | close(fd); | 448 | close(fd); |
450 | return -1; | 449 | return -1; |
451 | } | 450 | } |
452 | lineCount++; | ||
453 | charCount += bufUsed; | 451 | charCount += bufUsed; |
454 | } | 452 | } |
455 | 453 | ||
456 | close(fd); | 454 | close(fd); |
457 | 455 | ||
458 | printf("%d lines%s, %d chars\n", lineCount, | 456 | /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html |
459 | (bufUsed ? " (incomplete)" : ""), charCount); | 457 | * "Read Command" |
460 | 458 | * "...the number of bytes read shall be written to standard output | |
459 | * in the following format: | ||
460 | * "%d\n", <number of bytes read> | ||
461 | */ | ||
462 | printf("%u\n", charCount); | ||
461 | return TRUE; | 463 | return TRUE; |
462 | } | 464 | } |
463 | 465 | ||
@@ -468,12 +470,12 @@ static int readLines(const char *file, int num) | |||
468 | static int writeLines(const char *file, int num1, int num2) | 470 | static int writeLines(const char *file, int num1, int num2) |
469 | { | 471 | { |
470 | LINE *lp; | 472 | LINE *lp; |
471 | int fd, lineCount, charCount; | 473 | int fd; |
474 | unsigned charCount; | ||
472 | 475 | ||
473 | if (bad_nums(num1, num2, "write")) | 476 | if (bad_nums(num1, num2, "write")) |
474 | return FALSE; | 477 | return FALSE; |
475 | 478 | ||
476 | lineCount = 0; | ||
477 | charCount = 0; | 479 | charCount = 0; |
478 | 480 | ||
479 | fd = creat(file, 0666); | 481 | fd = creat(file, 0666); |
@@ -482,9 +484,6 @@ static int writeLines(const char *file, int num1, int num2) | |||
482 | return FALSE; | 484 | return FALSE; |
483 | } | 485 | } |
484 | 486 | ||
485 | printf("\"%s\", ", file); | ||
486 | fflush_all(); | ||
487 | |||
488 | lp = findLine(num1); | 487 | lp = findLine(num1); |
489 | if (lp == NULL) { | 488 | if (lp == NULL) { |
490 | close(fd); | 489 | close(fd); |
@@ -498,7 +497,6 @@ static int writeLines(const char *file, int num1, int num2) | |||
498 | return FALSE; | 497 | return FALSE; |
499 | } | 498 | } |
500 | charCount += lp->len; | 499 | charCount += lp->len; |
501 | lineCount++; | ||
502 | lp = lp->next; | 500 | lp = lp->next; |
503 | } | 501 | } |
504 | 502 | ||
@@ -507,7 +505,13 @@ static int writeLines(const char *file, int num1, int num2) | |||
507 | return FALSE; | 505 | return FALSE; |
508 | } | 506 | } |
509 | 507 | ||
510 | printf("%d lines, %d chars\n", lineCount, charCount); | 508 | /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html |
509 | * "Write Command" | ||
510 | * "...the number of bytes written shall be written to standard output, | ||
511 | * unless the -s option was specified, in the following format: | ||
512 | * "%d\n", <number of bytes written> | ||
513 | */ | ||
514 | printf("%u\n", charCount); | ||
511 | return TRUE; | 515 | return TRUE; |
512 | } | 516 | } |
513 | 517 | ||
diff --git a/findutils/find.c b/findutils/find.c index 188865e05..87f827b1f 100644 --- a/findutils/find.c +++ b/findutils/find.c | |||
@@ -67,21 +67,53 @@ | |||
67 | //config: interpreted by other programs. | 67 | //config: interpreted by other programs. |
68 | //config: | 68 | //config: |
69 | //config:config FEATURE_FIND_MTIME | 69 | //config:config FEATURE_FIND_MTIME |
70 | //config: bool "Enable -mtime: modified time matching" | 70 | //config: bool "Enable -mtime: modification time matching" |
71 | //config: default y | 71 | //config: default y |
72 | //config: depends on FIND | 72 | //config: depends on FIND |
73 | //config: help | 73 | //config: help |
74 | //config: Allow searching based on the modification time of | 74 | //config: Allow searching based on the modification time of |
75 | //config: files, in days. | 75 | //config: files, in days. |
76 | //config: | 76 | //config: |
77 | //config:config FEATURE_FIND_ATIME | ||
78 | //config: bool "Enable -atime: access time matching" | ||
79 | //config: default y | ||
80 | //config: depends on FEATURE_FIND_MTIME | ||
81 | //config: help | ||
82 | //config: Allow searching based on the access time of | ||
83 | //config: files, in days. | ||
84 | //config: | ||
85 | //config:config FEATURE_FIND_CTIME | ||
86 | //config: bool "Enable -ctime: status change timestamp matching" | ||
87 | //config: default y | ||
88 | //config: depends on FEATURE_FIND_MTIME | ||
89 | //config: help | ||
90 | //config: Allow searching based on the status change timestamp of | ||
91 | //config: files, in days. | ||
92 | //config: | ||
77 | //config:config FEATURE_FIND_MMIN | 93 | //config:config FEATURE_FIND_MMIN |
78 | //config: bool "Enable -mmin: modified time matching by minutes" | 94 | //config: bool "Enable -mmin: modification time matching by minutes" |
79 | //config: default y | 95 | //config: default y |
80 | //config: depends on FIND | 96 | //config: depends on FIND |
81 | //config: help | 97 | //config: help |
82 | //config: Allow searching based on the modification time of | 98 | //config: Allow searching based on the modification time of |
83 | //config: files, in minutes. | 99 | //config: files, in minutes. |
84 | //config: | 100 | //config: |
101 | //config:config FEATURE_FIND_AMIN | ||
102 | //config: bool "Enable -amin: access time matching by minutes" | ||
103 | //config: default y | ||
104 | //config: depends on FEATURE_FIND_MMIN | ||
105 | //config: help | ||
106 | //config: Allow searching based on the access time of | ||
107 | //config: files, in minutes. | ||
108 | //config: | ||
109 | //config:config FEATURE_FIND_CMIN | ||
110 | //config: bool "Enable -cmin: status change timestamp matching by minutes" | ||
111 | //config: default y | ||
112 | //config: depends on FEATURE_FIND_MMIN | ||
113 | //config: help | ||
114 | //config: Allow searching based on the status change timestamp of | ||
115 | //config: files, in minutes. | ||
116 | //config: | ||
85 | //config:config FEATURE_FIND_PERM | 117 | //config:config FEATURE_FIND_PERM |
86 | //config: bool "Enable -perm: permissions matching" | 118 | //config: bool "Enable -perm: permissions matching" |
87 | //config: default y | 119 | //config: default y |
@@ -296,10 +328,22 @@ | |||
296 | //usage: "\n -mtime DAYS mtime is greater than (+N), less than (-N)," | 328 | //usage: "\n -mtime DAYS mtime is greater than (+N), less than (-N)," |
297 | //usage: "\n or exactly N days in the past" | 329 | //usage: "\n or exactly N days in the past" |
298 | //usage: ) | 330 | //usage: ) |
331 | //usage: IF_FEATURE_FIND_ATIME( | ||
332 | //usage: "\n -atime DAYS atime +N/-N/N days in the past" | ||
333 | //usage: ) | ||
334 | //usage: IF_FEATURE_FIND_CTIME( | ||
335 | //usage: "\n -ctime DAYS ctime +N/-N/N days in the past" | ||
336 | //usage: ) | ||
299 | //usage: IF_FEATURE_FIND_MMIN( | 337 | //usage: IF_FEATURE_FIND_MMIN( |
300 | //usage: "\n -mmin MINS mtime is greater than (+N), less than (-N)," | 338 | //usage: "\n -mmin MINS mtime is greater than (+N), less than (-N)," |
301 | //usage: "\n or exactly N minutes in the past" | 339 | //usage: "\n or exactly N minutes in the past" |
302 | //usage: ) | 340 | //usage: ) |
341 | //usage: IF_FEATURE_FIND_AMIN( | ||
342 | //usage: "\n -amin MINS atime +N/-N/N minutes in the past" | ||
343 | //usage: ) | ||
344 | //usage: IF_FEATURE_FIND_CMIN( | ||
345 | //usage: "\n -cmin MINS ctime +N/-N/N minutes in the past" | ||
346 | //usage: ) | ||
303 | //usage: IF_FEATURE_FIND_NEWER( | 347 | //usage: IF_FEATURE_FIND_NEWER( |
304 | //usage: "\n -newer FILE mtime is more recent than FILE's" | 348 | //usage: "\n -newer FILE mtime is more recent than FILE's" |
305 | //usage: ) | 349 | //usage: ) |
@@ -396,8 +440,8 @@ IF_FEATURE_FIND_PRINT0( ACTS(print0)) | |||
396 | IF_FEATURE_FIND_TYPE( ACTS(type, int type_mask;)) | 440 | IF_FEATURE_FIND_TYPE( ACTS(type, int type_mask;)) |
397 | IF_FEATURE_FIND_EXECUTABLE(ACTS(executable)) | 441 | IF_FEATURE_FIND_EXECUTABLE(ACTS(executable)) |
398 | IF_FEATURE_FIND_PERM( ACTS(perm, char perm_char; mode_t perm_mask;)) | 442 | IF_FEATURE_FIND_PERM( ACTS(perm, char perm_char; mode_t perm_mask;)) |
399 | IF_FEATURE_FIND_MTIME( ACTS(mtime, char mtime_char; unsigned mtime_days;)) | 443 | IF_FEATURE_FIND_MTIME( ACTS(mtime, unsigned char time_type; unsigned char mtime_char; unsigned mtime_days;)) |
400 | IF_FEATURE_FIND_MMIN( ACTS(mmin, char mmin_char; unsigned mmin_mins;)) | 444 | IF_FEATURE_FIND_MMIN( ACTS(mmin, unsigned char time_type; unsigned char mmin_char; unsigned mmin_mins;)) |
401 | IF_FEATURE_FIND_NEWER( ACTS(newer, time_t newer_mtime;)) | 445 | IF_FEATURE_FIND_NEWER( ACTS(newer, time_t newer_mtime;)) |
402 | IF_FEATURE_FIND_INUM( ACTS(inum, ino_t inode_num;)) | 446 | IF_FEATURE_FIND_INUM( ACTS(inum, ino_t inode_num;)) |
403 | IF_FEATURE_FIND_USER( ACTS(user, uid_t uid;)) | 447 | IF_FEATURE_FIND_USER( ACTS(user, uid_t uid;)) |
@@ -618,30 +662,61 @@ ACTF(perm) | |||
618 | return (statbuf->st_mode & 07777) == ap->perm_mask; | 662 | return (statbuf->st_mode & 07777) == ap->perm_mask; |
619 | } | 663 | } |
620 | #endif | 664 | #endif |
665 | |||
666 | #if 0 \ | ||
667 | || ENABLE_FEATURE_FIND_AMIN \ | ||
668 | || ENABLE_FEATURE_FIND_ATIME \ | ||
669 | || ENABLE_FEATURE_FIND_CMIN \ | ||
670 | || ENABLE_FEATURE_FIND_CTIME \ | ||
671 | || ENABLE_FEATURE_FIND_MMIN \ | ||
672 | || ENABLE_FEATURE_FIND_MTIME | ||
673 | static int time_cmp(const struct stat *statbuf, unsigned type_and_char, time_t N_from_user, unsigned unit) | ||
674 | { | ||
675 | time_t ftime, file_age; | ||
676 | |||
677 | ftime = statbuf->st_mtime; | ||
678 | # if ENABLE_FEATURE_FIND_ATIME || ENABLE_FEATURE_FIND_CTIME | ||
679 | # if ENABLE_FEATURE_FIND_ATIME | ||
680 | if ((type_and_char >> 8) == 'a') | ||
681 | ftime = statbuf->st_atime; | ||
682 | # endif | ||
683 | # if ENABLE_FEATURE_FIND_CTIME | ||
684 | if ((type_and_char >> 8) == 'c') | ||
685 | ftime = statbuf->st_ctime; | ||
686 | # endif | ||
687 | type_and_char &= 0xff; | ||
688 | # endif | ||
689 | file_age = time(NULL) - ftime; | ||
690 | N_from_user *= unit; | ||
691 | switch (type_and_char) { | ||
692 | case '+': return file_age >= N_from_user + unit; | ||
693 | case '-': return file_age < N_from_user; | ||
694 | /* just numeric time */ | ||
695 | default: return file_age >= N_from_user && file_age < N_from_user + unit; | ||
696 | } | ||
697 | } | ||
698 | #endif | ||
699 | |||
621 | #if ENABLE_FEATURE_FIND_MTIME | 700 | #if ENABLE_FEATURE_FIND_MTIME |
622 | ACTF(mtime) | 701 | ACTF(mtime) |
623 | { | 702 | { |
624 | time_t file_age = time(NULL) - statbuf->st_mtime; | 703 | return time_cmp(statbuf, |
625 | time_t mtime_secs = ap->mtime_days * 24*60*60; | 704 | # if ENABLE_FEATURE_FIND_ATIME || ENABLE_FEATURE_FIND_CTIME |
626 | if (ap->mtime_char == '+') | 705 | (ap->time_type << 8) | |
627 | return file_age >= mtime_secs + 24*60*60; | 706 | # endif |
628 | if (ap->mtime_char == '-') | 707 | ap->mtime_char, |
629 | return file_age < mtime_secs; | 708 | ap->mtime_days, 24*60*60); |
630 | /* just numeric mtime */ | ||
631 | return file_age >= mtime_secs && file_age < (mtime_secs + 24*60*60); | ||
632 | } | 709 | } |
633 | #endif | 710 | #endif |
634 | #if ENABLE_FEATURE_FIND_MMIN | 711 | #if ENABLE_FEATURE_FIND_MMIN |
635 | ACTF(mmin) | 712 | ACTF(mmin) |
636 | { | 713 | { |
637 | time_t file_age = time(NULL) - statbuf->st_mtime; | 714 | return time_cmp(statbuf, |
638 | time_t mmin_secs = ap->mmin_mins * 60; | 715 | # if ENABLE_FEATURE_FIND_ATIME || ENABLE_FEATURE_FIND_CTIME |
639 | if (ap->mmin_char == '+') | 716 | (ap->time_type << 8) | |
640 | return file_age >= mmin_secs + 60; | 717 | # endif |
641 | if (ap->mmin_char == '-') | 718 | ap->mmin_char, |
642 | return file_age < mmin_secs; | 719 | ap->mmin_mins, 60); |
643 | /* just numeric mmin */ | ||
644 | return file_age >= mmin_secs && file_age < (mmin_secs + 60); | ||
645 | } | 720 | } |
646 | #endif | 721 | #endif |
647 | #if ENABLE_FEATURE_FIND_NEWER | 722 | #if ENABLE_FEATURE_FIND_NEWER |
@@ -1043,7 +1118,11 @@ static action*** parse_params(char **argv) | |||
1043 | IF_FEATURE_FIND_TYPE( PARM_type ,) | 1118 | IF_FEATURE_FIND_TYPE( PARM_type ,) |
1044 | IF_FEATURE_FIND_PERM( PARM_perm ,) | 1119 | IF_FEATURE_FIND_PERM( PARM_perm ,) |
1045 | IF_FEATURE_FIND_MTIME( PARM_mtime ,) | 1120 | IF_FEATURE_FIND_MTIME( PARM_mtime ,) |
1121 | IF_FEATURE_FIND_ATIME( PARM_atime ,) | ||
1122 | IF_FEATURE_FIND_CTIME( PARM_ctime ,) | ||
1046 | IF_FEATURE_FIND_MMIN( PARM_mmin ,) | 1123 | IF_FEATURE_FIND_MMIN( PARM_mmin ,) |
1124 | IF_FEATURE_FIND_AMIN( PARM_amin ,) | ||
1125 | IF_FEATURE_FIND_CMIN( PARM_cmin ,) | ||
1047 | IF_FEATURE_FIND_NEWER( PARM_newer ,) | 1126 | IF_FEATURE_FIND_NEWER( PARM_newer ,) |
1048 | IF_FEATURE_FIND_INUM( PARM_inum ,) | 1127 | IF_FEATURE_FIND_INUM( PARM_inum ,) |
1049 | IF_FEATURE_FIND_USER( PARM_user ,) | 1128 | IF_FEATURE_FIND_USER( PARM_user ,) |
@@ -1087,7 +1166,11 @@ static action*** parse_params(char **argv) | |||
1087 | IF_FEATURE_FIND_TYPE( "-type\0" ) | 1166 | IF_FEATURE_FIND_TYPE( "-type\0" ) |
1088 | IF_FEATURE_FIND_PERM( "-perm\0" ) | 1167 | IF_FEATURE_FIND_PERM( "-perm\0" ) |
1089 | IF_FEATURE_FIND_MTIME( "-mtime\0" ) | 1168 | IF_FEATURE_FIND_MTIME( "-mtime\0" ) |
1169 | IF_FEATURE_FIND_ATIME( "-atime\0" ) | ||
1170 | IF_FEATURE_FIND_CTIME( "-ctime\0" ) | ||
1090 | IF_FEATURE_FIND_MMIN( "-mmin\0" ) | 1171 | IF_FEATURE_FIND_MMIN( "-mmin\0" ) |
1172 | IF_FEATURE_FIND_AMIN( "-amin\0" ) | ||
1173 | IF_FEATURE_FIND_CMIN( "-cmin\0" ) | ||
1091 | IF_FEATURE_FIND_NEWER( "-newer\0" ) | 1174 | IF_FEATURE_FIND_NEWER( "-newer\0" ) |
1092 | IF_FEATURE_FIND_INUM( "-inum\0" ) | 1175 | IF_FEATURE_FIND_INUM( "-inum\0" ) |
1093 | IF_FEATURE_FIND_USER( "-user\0" ) | 1176 | IF_FEATURE_FIND_USER( "-user\0" ) |
@@ -1373,19 +1456,39 @@ static action*** parse_params(char **argv) | |||
1373 | } | 1456 | } |
1374 | #endif | 1457 | #endif |
1375 | #if ENABLE_FEATURE_FIND_MTIME | 1458 | #if ENABLE_FEATURE_FIND_MTIME |
1376 | else if (parm == PARM_mtime) { | 1459 | else if (parm == PARM_mtime |
1460 | # if ENABLE_FEATURE_FIND_ATIME | ||
1461 | || parm == PARM_atime | ||
1462 | # endif | ||
1463 | # if ENABLE_FEATURE_FIND_CTIME | ||
1464 | || parm == PARM_ctime | ||
1465 | # endif | ||
1466 | ) { | ||
1377 | action_mtime *ap; | 1467 | action_mtime *ap; |
1378 | dbg("%d", __LINE__); | 1468 | dbg("%d", __LINE__); |
1379 | ap = ALLOC_ACTION(mtime); | 1469 | ap = ALLOC_ACTION(mtime); |
1470 | # if ENABLE_FEATURE_FIND_AMIN || ENABLE_FEATURE_FIND_CMIN | ||
1471 | ap->time_type = arg[1]; | ||
1472 | # endif | ||
1380 | ap->mtime_char = arg1[0]; | 1473 | ap->mtime_char = arg1[0]; |
1381 | ap->mtime_days = xatoul(plus_minus_num(arg1)); | 1474 | ap->mtime_days = xatoul(plus_minus_num(arg1)); |
1382 | } | 1475 | } |
1383 | #endif | 1476 | #endif |
1384 | #if ENABLE_FEATURE_FIND_MMIN | 1477 | #if ENABLE_FEATURE_FIND_MMIN |
1385 | else if (parm == PARM_mmin) { | 1478 | else if (parm == PARM_mmin |
1479 | # if ENABLE_FEATURE_FIND_AMIN | ||
1480 | || parm == PARM_amin | ||
1481 | # endif | ||
1482 | # if ENABLE_FEATURE_FIND_CMIN | ||
1483 | || parm == PARM_cmin | ||
1484 | # endif | ||
1485 | ) { | ||
1386 | action_mmin *ap; | 1486 | action_mmin *ap; |
1387 | dbg("%d", __LINE__); | 1487 | dbg("%d", __LINE__); |
1388 | ap = ALLOC_ACTION(mmin); | 1488 | ap = ALLOC_ACTION(mmin); |
1489 | # if ENABLE_FEATURE_FIND_AMIN || ENABLE_FEATURE_FIND_CMIN | ||
1490 | ap->time_type = arg[1]; | ||
1491 | # endif | ||
1389 | ap->mmin_char = arg1[0]; | 1492 | ap->mmin_char = arg1[0]; |
1390 | ap->mmin_mins = xatoul(plus_minus_num(arg1)); | 1493 | ap->mmin_mins = xatoul(plus_minus_num(arg1)); |
1391 | } | 1494 | } |
diff --git a/include/libbb.h b/include/libbb.h index 3a958b555..098619305 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -324,9 +324,13 @@ typedef unsigned long long uoff_t; | |||
324 | # endif | 324 | # endif |
325 | #else | 325 | #else |
326 | /* CONFIG_LFS is off */ | 326 | /* CONFIG_LFS is off */ |
327 | # if UINT_MAX == 0xffffffff | 327 | /* sizeof(off_t) == sizeof(long). |
328 | /* While sizeof(off_t) == sizeof(int), off_t is typedef'ed to long anyway. | 328 | * May or may not be == sizeof(int). If it is, use xatoi_positive() |
329 | * gcc will throw warnings on printf("%d", off_t). Crap... */ | 329 | * and bb_strtou() instead of xatoul_range() and bb_strtoul(). |
330 | * Even if sizeof(off_t) == sizeof(int), off_t is typedef'ed to long anyway. | ||
331 | * gcc will throw warnings on printf("%d", off_t)... Have to use %ld etc. | ||
332 | */ | ||
333 | # if UINT_MAX == ULONG_MAX | ||
330 | typedef unsigned long uoff_t; | 334 | typedef unsigned long uoff_t; |
331 | # define XATOOFF(a) xatoi_positive(a) | 335 | # define XATOOFF(a) xatoi_positive(a) |
332 | # define BB_STRTOOFF bb_strtou | 336 | # define BB_STRTOOFF bb_strtou |
@@ -384,13 +388,27 @@ struct BUG_off_t_size_is_misdetected { | |||
384 | #endif | 388 | #endif |
385 | #endif | 389 | #endif |
386 | 390 | ||
391 | /* We use a trick to have more optimized code (fewer pointer reloads | ||
392 | * and reduced binary size by a few kilobytes) like: | ||
393 | * ash.c: extern struct globals *const ash_ptr_to_globals; | ||
394 | * ash_ptr_hack.c: struct globals *ash_ptr_to_globals; | ||
395 | * This way, compiler in ash.c knows the pointer can not change. | ||
396 | * | ||
397 | * However, this may break on weird arches or toolchains. In this case, | ||
398 | * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable | ||
399 | * this optimization. | ||
400 | */ | ||
401 | #ifndef BB_GLOBAL_CONST | ||
402 | # define BB_GLOBAL_CONST const | ||
403 | #endif | ||
404 | |||
387 | #if defined(errno) | 405 | #if defined(errno) |
388 | /* If errno is a define, assume it's "define errno (*__errno_location())" | 406 | /* If errno is a define, assume it's "define errno (*__errno_location())" |
389 | * and we will cache it's result in this variable */ | 407 | * and we will cache it's result in this variable */ |
390 | extern int *const bb_errno; | 408 | extern int *BB_GLOBAL_CONST bb_errno; |
391 | #undef errno | 409 | # undef errno |
392 | #define errno (*bb_errno) | 410 | # define errno (*bb_errno) |
393 | #define bb_cached_errno_ptr 1 | 411 | # define bb_cached_errno_ptr 1 |
394 | #endif | 412 | #endif |
395 | 413 | ||
396 | #if !(ULONG_MAX > 0xffffffff) | 414 | #if !(ULONG_MAX > 0xffffffff) |
@@ -579,7 +597,7 @@ DIR *xopendir(const char *path) FAST_FUNC; | |||
579 | DIR *warn_opendir(const char *path) FAST_FUNC; | 597 | DIR *warn_opendir(const char *path) FAST_FUNC; |
580 | 598 | ||
581 | char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC; | 599 | char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC; |
582 | char *xmalloc_realpath_coreutils(const char *path) FAST_FUNC RETURNS_MALLOC; | 600 | char *xmalloc_realpath_coreutils(char *path) FAST_FUNC RETURNS_MALLOC; |
583 | char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC; | 601 | char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC; |
584 | char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC; | 602 | char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC; |
585 | /* !RETURNS_MALLOC: it's a realloc-like function */ | 603 | /* !RETURNS_MALLOC: it's a realloc-like function */ |
@@ -1297,8 +1315,10 @@ void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_ | |||
1297 | #endif | 1315 | #endif |
1298 | void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC; | 1316 | void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC; |
1299 | #if defined(__linux__) | 1317 | #if defined(__linux__) |
1318 | int re_execed_comm(void) FAST_FUNC; | ||
1300 | void set_task_comm(const char *comm) FAST_FUNC; | 1319 | void set_task_comm(const char *comm) FAST_FUNC; |
1301 | #else | 1320 | #else |
1321 | # define re_execed_comm() 0 | ||
1302 | # define set_task_comm(name) ((void)0) | 1322 | # define set_task_comm(name) ((void)0) |
1303 | #endif | 1323 | #endif |
1304 | 1324 | ||
@@ -1526,16 +1546,8 @@ int scripted_main(int argc, char** argv) MAIN_EXTERNALLY_VISIBLE; | |||
1526 | 1546 | ||
1527 | /* Applets which are useful from another applets */ | 1547 | /* Applets which are useful from another applets */ |
1528 | int bb_cat(char** argv) FAST_FUNC; | 1548 | int bb_cat(char** argv) FAST_FUNC; |
1529 | int ash_main(int argc, char** argv) | 1549 | int ash_main(int argc, char** argv) IF_SHELL_ASH(MAIN_EXTERNALLY_VISIBLE); |
1530 | #if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH | 1550 | int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE); |
1531 | MAIN_EXTERNALLY_VISIBLE | ||
1532 | #endif | ||
1533 | ; | ||
1534 | int hush_main(int argc, char** argv) | ||
1535 | #if ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH | ||
1536 | MAIN_EXTERNALLY_VISIBLE | ||
1537 | #endif | ||
1538 | ; | ||
1539 | /* If shell needs them, they exist even if not enabled as applets */ | 1551 | /* If shell needs them, they exist even if not enabled as applets */ |
1540 | int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); | 1552 | int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); |
1541 | int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); | 1553 | int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); |
@@ -2331,6 +2343,7 @@ extern const char bb_PATH_root_path[] ALIGN1; /* BB_PATH_ROOT_PATH */ | |||
2331 | extern const int const_int_0; | 2343 | extern const int const_int_0; |
2332 | //extern const int const_int_1; | 2344 | //extern const int const_int_1; |
2333 | 2345 | ||
2346 | |||
2334 | /* This struct is deliberately not defined. */ | 2347 | /* This struct is deliberately not defined. */ |
2335 | /* See docs/keep_data_small.txt */ | 2348 | /* See docs/keep_data_small.txt */ |
2336 | struct globals; | 2349 | struct globals; |
@@ -2339,6 +2352,8 @@ struct globals; | |||
2339 | * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */ | 2352 | * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */ |
2340 | extern struct globals *const ptr_to_globals; | 2353 | extern struct globals *const ptr_to_globals; |
2341 | 2354 | ||
2355 | #define barrier() asm volatile ("":::"memory") | ||
2356 | |||
2342 | #if defined(__clang_major__) && __clang_major__ >= 9 | 2357 | #if defined(__clang_major__) && __clang_major__ >= 9 |
2343 | /* Clang/llvm drops assignment to "constant" storage. Silently. | 2358 | /* Clang/llvm drops assignment to "constant" storage. Silently. |
2344 | * Needs serious convincing to not eliminate the store. | 2359 | * Needs serious convincing to not eliminate the store. |
@@ -2346,30 +2361,38 @@ extern struct globals *const ptr_to_globals; | |||
2346 | static ALWAYS_INLINE void* not_const_pp(const void *p) | 2361 | static ALWAYS_INLINE void* not_const_pp(const void *p) |
2347 | { | 2362 | { |
2348 | void *pp; | 2363 | void *pp; |
2349 | __asm__ __volatile__( | 2364 | asm volatile ( |
2350 | "# forget that p points to const" | 2365 | "# forget that p points to const" |
2351 | : /*outputs*/ "=r" (pp) | 2366 | : /*outputs*/ "=r" (pp) |
2352 | : /*inputs*/ "0" (p) | 2367 | : /*inputs*/ "0" (p) |
2353 | ); | 2368 | ); |
2354 | return pp; | 2369 | return pp; |
2355 | } | 2370 | } |
2371 | # define ASSIGN_CONST_PTR(pptr, v) do { \ | ||
2372 | *(void**)not_const_pp(pptr) = (void*)(v); \ | ||
2373 | barrier(); \ | ||
2374 | } while (0) | ||
2375 | /* XZALLOC_CONST_PTR() is an out-of-line function to prevent | ||
2376 | * clang from reading pointer before it is assigned. | ||
2377 | */ | ||
2378 | void XZALLOC_CONST_PTR(const void *pptr, size_t size) FAST_FUNC; | ||
2356 | #else | 2379 | #else |
2357 | static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; } | 2380 | # define ASSIGN_CONST_PTR(pptr, v) do { \ |
2358 | #endif | 2381 | *(void**)(pptr) = (void*)(v); \ |
2359 | 2382 | /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \ | |
2360 | /* At least gcc 3.4.6 on mipsel system needs optimization barrier */ | ||
2361 | #define barrier() __asm__ __volatile__("":::"memory") | ||
2362 | #define SET_PTR_TO_GLOBALS(x) do { \ | ||
2363 | (*(struct globals**)not_const_pp(&ptr_to_globals)) = (void*)(x); \ | ||
2364 | barrier(); \ | 2383 | barrier(); \ |
2365 | } while (0) | 2384 | } while (0) |
2385 | # define XZALLOC_CONST_PTR(pptr, size) ASSIGN_CONST_PTR(pptr, xzalloc(size)) | ||
2386 | #endif | ||
2366 | 2387 | ||
2388 | #define SET_PTR_TO_GLOBALS(x) ASSIGN_CONST_PTR(&ptr_to_globals, x) | ||
2367 | #define FREE_PTR_TO_GLOBALS() do { \ | 2389 | #define FREE_PTR_TO_GLOBALS() do { \ |
2368 | if (ENABLE_FEATURE_CLEAN_UP) { \ | 2390 | if (ENABLE_FEATURE_CLEAN_UP) { \ |
2369 | free(ptr_to_globals); \ | 2391 | free(ptr_to_globals); \ |
2370 | } \ | 2392 | } \ |
2371 | } while (0) | 2393 | } while (0) |
2372 | 2394 | ||
2395 | |||
2373 | /* You can change LIBBB_DEFAULT_LOGIN_SHELL, but don't use it, | 2396 | /* You can change LIBBB_DEFAULT_LOGIN_SHELL, but don't use it, |
2374 | * use bb_default_login_shell and following defines. | 2397 | * use bb_default_login_shell and following defines. |
2375 | * If you change LIBBB_DEFAULT_LOGIN_SHELL, | 2398 | * If you change LIBBB_DEFAULT_LOGIN_SHELL, |
diff --git a/libbb/Config.src b/libbb/Config.src index 58c5fad50..24b31fad9 100644 --- a/libbb/Config.src +++ b/libbb/Config.src | |||
@@ -61,32 +61,73 @@ config SHA3_SMALL | |||
61 | 64-bit x86: +270 bytes of code, 45% faster | 61 | 64-bit x86: +270 bytes of code, 45% faster |
62 | 32-bit x86: +450 bytes of code, 75% faster | 62 | 32-bit x86: +450 bytes of code, 75% faster |
63 | 63 | ||
64 | config FEATURE_FAST_TOP | 64 | config FEATURE_NON_POSIX_CP |
65 | bool "Faster /proc scanning code (+100 bytes)" | 65 | bool "Non-POSIX, but safer, copying to special nodes" |
66 | default n # all "fast or small" options default to small | 66 | default y |
67 | help | 67 | help |
68 | This option makes top and ps ~20% faster (or 20% less CPU hungry), | 68 | With this option, "cp file symlink" will delete symlink |
69 | but code size is slightly bigger. | 69 | and create a regular file. This does not conform to POSIX, |
70 | but prevents a symlink attack. | ||
71 | Similarly, "cp file device" will not send file's data | ||
72 | to the device. (To do that, use "cat file >device") | ||
70 | 73 | ||
71 | config FEATURE_ETC_NETWORKS | 74 | config FEATURE_VERBOSE_CP_MESSAGE |
72 | bool "Support /etc/networks" | 75 | bool "Give more precise messages when copy fails (cp, mv etc)" |
73 | default n | 76 | default n |
74 | help | 77 | help |
75 | Enable support for network names in /etc/networks. This is | 78 | Error messages with this feature enabled: |
76 | a rarely used feature which allows you to use names | ||
77 | instead of IP/mask pairs in route command. | ||
78 | 79 | ||
79 | config FEATURE_ETC_SERVICES | 80 | $ cp file /does_not_exist/file |
80 | bool "Consult /etc/services even for well-known ports" | 81 | cp: cannot create '/does_not_exist/file': Path does not exist |
81 | default n | 82 | $ cp file /vmlinuz/file |
83 | cp: cannot stat '/vmlinuz/file': Path has non-directory component | ||
84 | |||
85 | If this feature is not enabled, they will be, respectively: | ||
86 | |||
87 | cp: cannot create '/does_not_exist/file': No such file or directory | ||
88 | cp: cannot stat '/vmlinuz/file': Not a directory | ||
89 | |||
90 | This will cost you ~60 bytes. | ||
91 | |||
92 | config FEATURE_USE_SENDFILE | ||
93 | bool "Use sendfile system call" | ||
94 | default y | ||
95 | help | ||
96 | When enabled, busybox will use the kernel sendfile() function | ||
97 | instead of read/write loops to copy data between file descriptors | ||
98 | (for example, cp command does this a lot). | ||
99 | If sendfile() doesn't work, copying code falls back to read/write | ||
100 | loop. sendfile() was originally implemented for faster I/O | ||
101 | from files to sockets, but since Linux 2.6.33 it was extended | ||
102 | to work for many more file types. | ||
103 | |||
104 | config FEATURE_COPYBUF_KB | ||
105 | int "Copy buffer size, in kilobytes" | ||
106 | range 1 1024 | ||
107 | default 4 | ||
108 | help | ||
109 | Size of buffer used by cp, mv, install, wget etc. | ||
110 | Buffers which are 4 kb or less will be allocated on stack. | ||
111 | Bigger buffers will be allocated with mmap, with fallback to 4 kb | ||
112 | stack buffer if mmap fails. | ||
113 | |||
114 | config MONOTONIC_SYSCALL | ||
115 | bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" | ||
116 | default y | ||
117 | help | ||
118 | Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring | ||
119 | time intervals (time, ping, traceroute etc need this). | ||
120 | Probably requires Linux 2.6+. If not selected, gettimeofday | ||
121 | will be used instead (which gives wrong results if date/time | ||
122 | is reset). | ||
123 | |||
124 | config IOCTL_HEX2STR_ERROR | ||
125 | bool "Use ioctl names rather than hex values in error messages" | ||
126 | default y | ||
82 | help | 127 | help |
83 | Look up e.g. "telnet" and "http" in /etc/services file | 128 | Use ioctl names rather than hex values in error messages |
84 | instead of assuming ports 23 and 80. | 129 | (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this |
85 | This is almost never necessary (everybody uses standard ports), | 130 | saves about 1400 bytes. |
86 | and it makes sense to avoid reading this file. | ||
87 | If you disable this option, in the cases where port is explicitly | ||
88 | specified as a service name (e.g. "telnet HOST PORTNAME"), | ||
89 | it will still be looked up in /etc/services. | ||
90 | 131 | ||
91 | config FEATURE_EDITING | 132 | config FEATURE_EDITING |
92 | bool "Command line editing" | 133 | bool "Command line editing" |
@@ -302,107 +343,3 @@ config UNICODE_PRESERVE_BROKEN | |||
302 | For example, this means that entering 'l', 's', ' ', 0xff, [Enter] | 343 | For example, this means that entering 'l', 's', ' ', 0xff, [Enter] |
303 | at shell prompt will list file named 0xff (single char name | 344 | at shell prompt will list file named 0xff (single char name |
304 | with char value 255), not file named '?'. | 345 | with char value 255), not file named '?'. |
305 | |||
306 | config FEATURE_NON_POSIX_CP | ||
307 | bool "Non-POSIX, but safer, copying to special nodes" | ||
308 | default y | ||
309 | help | ||
310 | With this option, "cp file symlink" will delete symlink | ||
311 | and create a regular file. This does not conform to POSIX, | ||
312 | but prevents a symlink attack. | ||
313 | Similarly, "cp file device" will not send file's data | ||
314 | to the device. (To do that, use "cat file >device") | ||
315 | |||
316 | config FEATURE_VERBOSE_CP_MESSAGE | ||
317 | bool "Give more precise messages when copy fails (cp, mv etc)" | ||
318 | default n | ||
319 | help | ||
320 | Error messages with this feature enabled: | ||
321 | |||
322 | $ cp file /does_not_exist/file | ||
323 | cp: cannot create '/does_not_exist/file': Path does not exist | ||
324 | $ cp file /vmlinuz/file | ||
325 | cp: cannot stat '/vmlinuz/file': Path has non-directory component | ||
326 | |||
327 | If this feature is not enabled, they will be, respectively: | ||
328 | |||
329 | cp: cannot create '/does_not_exist/file': No such file or directory | ||
330 | cp: cannot stat '/vmlinuz/file': Not a directory | ||
331 | |||
332 | This will cost you ~60 bytes. | ||
333 | |||
334 | config FEATURE_USE_SENDFILE | ||
335 | bool "Use sendfile system call" | ||
336 | default y | ||
337 | help | ||
338 | When enabled, busybox will use the kernel sendfile() function | ||
339 | instead of read/write loops to copy data between file descriptors | ||
340 | (for example, cp command does this a lot). | ||
341 | If sendfile() doesn't work, copying code falls back to read/write | ||
342 | loop. sendfile() was originally implemented for faster I/O | ||
343 | from files to sockets, but since Linux 2.6.33 it was extended | ||
344 | to work for many more file types. | ||
345 | |||
346 | config FEATURE_COPYBUF_KB | ||
347 | int "Copy buffer size, in kilobytes" | ||
348 | range 1 1024 | ||
349 | default 4 | ||
350 | help | ||
351 | Size of buffer used by cp, mv, install, wget etc. | ||
352 | Buffers which are 4 kb or less will be allocated on stack. | ||
353 | Bigger buffers will be allocated with mmap, with fallback to 4 kb | ||
354 | stack buffer if mmap fails. | ||
355 | |||
356 | config FEATURE_SKIP_ROOTFS | ||
357 | bool "Skip rootfs in mount table" | ||
358 | default y | ||
359 | help | ||
360 | Ignore rootfs entry in mount table. | ||
361 | |||
362 | In Linux, kernel has a special filesystem, rootfs, which is initially | ||
363 | mounted on /. It contains initramfs data, if kernel is configured | ||
364 | to have one. Usually, another file system is mounted over / early | ||
365 | in boot process, and therefore most tools which manipulate | ||
366 | mount table, such as df, will skip rootfs entry. | ||
367 | |||
368 | However, some systems do not mount anything on /. | ||
369 | If you need to configure busybox for one of these systems, | ||
370 | you may find it useful to turn this option off to make df show | ||
371 | initramfs statistics. | ||
372 | |||
373 | Otherwise, choose Y. | ||
374 | |||
375 | config MONOTONIC_SYSCALL | ||
376 | bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" | ||
377 | default y | ||
378 | help | ||
379 | Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring | ||
380 | time intervals (time, ping, traceroute etc need this). | ||
381 | Probably requires Linux 2.6+. If not selected, gettimeofday | ||
382 | will be used instead (which gives wrong results if date/time | ||
383 | is reset). | ||
384 | |||
385 | config IOCTL_HEX2STR_ERROR | ||
386 | bool "Use ioctl names rather than hex values in error messages" | ||
387 | default y | ||
388 | help | ||
389 | Use ioctl names rather than hex values in error messages | ||
390 | (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this | ||
391 | saves about 1400 bytes. | ||
392 | |||
393 | config FEATURE_HWIB | ||
394 | bool "Support infiniband HW" | ||
395 | default y | ||
396 | help | ||
397 | Support for printing infiniband addresses in network applets. | ||
398 | |||
399 | config FEATURE_TIMEZONE | ||
400 | bool "Allow timezone in dates" | ||
401 | default y | ||
402 | depends on DESKTOP | ||
403 | help | ||
404 | Permit the use of timezones when parsing user-provided data | ||
405 | strings, e.g. '1996-04-09 12:45:00 -0500'. | ||
406 | |||
407 | This requires support for the '%z' extension to strptime() which | ||
408 | may not be available in all implementations. | ||
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 102e360af..60df3476f 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -21,6 +21,7 @@ lib-y += chomp.o | |||
21 | lib-y += compare_string_array.o | 21 | lib-y += compare_string_array.o |
22 | lib-y += concat_path_file.o | 22 | lib-y += concat_path_file.o |
23 | lib-y += concat_subpath_file.o | 23 | lib-y += concat_subpath_file.o |
24 | lib-y += const_hack.o | ||
24 | lib-y += copy_file.o | 25 | lib-y += copy_file.o |
25 | lib-y += copyfd.o | 26 | lib-y += copyfd.o |
26 | lib-y += crc32.o | 27 | lib-y += crc32.o |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index e1f8bf432..6c0be4a83 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -262,8 +262,7 @@ void lbb_prepare(const char *applet | |||
262 | IF_FEATURE_INDIVIDUAL(, char **argv)) | 262 | IF_FEATURE_INDIVIDUAL(, char **argv)) |
263 | { | 263 | { |
264 | #ifdef bb_cached_errno_ptr | 264 | #ifdef bb_cached_errno_ptr |
265 | (*(int **)not_const_pp(&bb_errno)) = get_perrno(); | 265 | ASSIGN_CONST_PTR(&bb_errno, get_perrno()); |
266 | barrier(); | ||
267 | #endif | 266 | #endif |
268 | applet_name = applet; | 267 | applet_name = applet; |
269 | 268 | ||
@@ -767,9 +766,9 @@ int scripted_main(int argc UNUSED_PARAM, char **argv) | |||
767 | int script = find_script_by_name(applet_name); | 766 | int script = find_script_by_name(applet_name); |
768 | if (script >= 0) | 767 | if (script >= 0) |
769 | # if ENABLE_SHELL_ASH | 768 | # if ENABLE_SHELL_ASH |
770 | exit(ash_main(-script - 1, argv)); | 769 | return ash_main(-script - 1, argv); |
771 | # elif ENABLE_SHELL_HUSH | 770 | # elif ENABLE_SHELL_HUSH |
772 | exit(hush_main(-script - 1, argv)); | 771 | return hush_main(-script - 1, argv); |
773 | # else | 772 | # else |
774 | return 1; | 773 | return 1; |
775 | # endif | 774 | # endif |
@@ -1161,10 +1160,10 @@ int scripted_main(int argc UNUSED_PARAM, char **argv) | |||
1161 | { | 1160 | { |
1162 | # if ENABLE_SHELL_ASH | 1161 | # if ENABLE_SHELL_ASH |
1163 | int script = 0; | 1162 | int script = 0; |
1164 | exit(ash_main(-script - 1, argv)); | 1163 | return ash_main(-script - 1, argv); |
1165 | # elif ENABLE_SHELL_HUSH | 1164 | # elif ENABLE_SHELL_HUSH |
1166 | int script = 0; | 1165 | int script = 0; |
1167 | exit(hush_main(-script - 1, argv)); | 1166 | return hush_main(-script - 1, argv); |
1168 | # else | 1167 | # else |
1169 | return 1; | 1168 | return 1; |
1170 | # endif | 1169 | # endif |
@@ -1282,7 +1281,7 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
1282 | 1281 | ||
1283 | full_write2_str(bb_basename(argv[0])); | 1282 | full_write2_str(bb_basename(argv[0])); |
1284 | full_write2_str(": no applets enabled\n"); | 1283 | full_write2_str(": no applets enabled\n"); |
1285 | exit(127); | 1284 | return 127; |
1286 | 1285 | ||
1287 | #else | 1286 | #else |
1288 | 1287 | ||
@@ -1314,8 +1313,14 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
1314 | || ENABLE_FEATURE_PREFER_APPLETS | 1313 | || ENABLE_FEATURE_PREFER_APPLETS |
1315 | || !BB_MMU | 1314 | || !BB_MMU |
1316 | ) { | 1315 | ) { |
1317 | if (NUM_APPLETS > 1) | 1316 | if (NUM_APPLETS > 1) { |
1318 | set_task_comm(applet_name); | 1317 | /* Careful, do not trash comm of "SCRIPT.sh" - |
1318 | * the case when started from e.g. #!/bin/ash script. | ||
1319 | * (not limited to shells - #!/bin/awk scripts also exist) | ||
1320 | */ | ||
1321 | if (re_execed_comm()) | ||
1322 | set_task_comm(applet_name); | ||
1323 | } | ||
1319 | } | 1324 | } |
1320 | 1325 | ||
1321 | parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ | 1326 | parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ |
diff --git a/libbb/const_hack.c b/libbb/const_hack.c new file mode 100644 index 000000000..9575e6d67 --- /dev/null +++ b/libbb/const_hack.c | |||
@@ -0,0 +1,16 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Trick to assign a const ptr with barrier for clang | ||
4 | * | ||
5 | * Copyright (C) 2021 by YU Jincheng <shana@zju.edu.cn> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
8 | */ | ||
9 | #include "libbb.h" | ||
10 | |||
11 | #if defined(__clang_major__) && __clang_major__ >= 9 | ||
12 | void FAST_FUNC XZALLOC_CONST_PTR(const void *pptr, size_t size) | ||
13 | { | ||
14 | ASSIGN_CONST_PTR(pptr, xzalloc(size)); | ||
15 | } | ||
16 | #endif | ||
diff --git a/libbb/dump.c b/libbb/dump.c index ffae04786..d24057325 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -568,7 +568,7 @@ static void conv_u(PR *pr, unsigned char *p) | |||
568 | } | 568 | } |
569 | } | 569 | } |
570 | 570 | ||
571 | static void display(priv_dumper_t* dumper) | 571 | static NOINLINE void display(priv_dumper_t* dumper) |
572 | { | 572 | { |
573 | unsigned char *bp; | 573 | unsigned char *bp; |
574 | unsigned char savech = '\0'; | 574 | unsigned char savech = '\0'; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 7c46fa5db..8abc87976 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -135,10 +135,6 @@ enum { | |||
135 | : 0x7ff0 | 135 | : 0x7ff0 |
136 | }; | 136 | }; |
137 | 137 | ||
138 | #if ENABLE_USERNAME_OR_HOMEDIR | ||
139 | static const char null_str[] ALIGN1 = ""; | ||
140 | #endif | ||
141 | |||
142 | /* We try to minimize both static and stack usage. */ | 138 | /* We try to minimize both static and stack usage. */ |
143 | struct lineedit_statics { | 139 | struct lineedit_statics { |
144 | line_input_t *state; | 140 | line_input_t *state; |
@@ -161,12 +157,13 @@ struct lineedit_statics { | |||
161 | 157 | ||
162 | #if ENABLE_USERNAME_OR_HOMEDIR | 158 | #if ENABLE_USERNAME_OR_HOMEDIR |
163 | char *user_buf; | 159 | char *user_buf; |
164 | char *home_pwd_buf; /* = (char*)null_str; */ | 160 | char *home_pwd_buf; |
161 | smallint got_user_strings; | ||
165 | #endif | 162 | #endif |
166 | 163 | ||
167 | #if ENABLE_FEATURE_TAB_COMPLETION | 164 | #if ENABLE_FEATURE_TAB_COMPLETION |
168 | char **matches; | ||
169 | unsigned num_matches; | 165 | unsigned num_matches; |
166 | char **matches; | ||
170 | #endif | 167 | #endif |
171 | 168 | ||
172 | #if ENABLE_FEATURE_EDITING_WINCH | 169 | #if ENABLE_FEATURE_EDITING_WINCH |
@@ -192,7 +189,7 @@ struct lineedit_statics { | |||
192 | }; | 189 | }; |
193 | 190 | ||
194 | /* See lineedit_ptr_hack.c */ | 191 | /* See lineedit_ptr_hack.c */ |
195 | extern struct lineedit_statics *const lineedit_ptr_to_statics; | 192 | extern struct lineedit_statics *BB_GLOBAL_CONST lineedit_ptr_to_statics; |
196 | 193 | ||
197 | #define S (*lineedit_ptr_to_statics) | 194 | #define S (*lineedit_ptr_to_statics) |
198 | #define state (S.state ) | 195 | #define state (S.state ) |
@@ -207,15 +204,15 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics; | |||
207 | #define prompt_last_line (S.prompt_last_line) | 204 | #define prompt_last_line (S.prompt_last_line) |
208 | #define user_buf (S.user_buf ) | 205 | #define user_buf (S.user_buf ) |
209 | #define home_pwd_buf (S.home_pwd_buf ) | 206 | #define home_pwd_buf (S.home_pwd_buf ) |
210 | #define matches (S.matches ) | 207 | #define got_user_strings (S.got_user_strings) |
211 | #define num_matches (S.num_matches ) | 208 | #define num_matches (S.num_matches ) |
209 | #define matches (S.matches ) | ||
212 | #define delptr (S.delptr ) | 210 | #define delptr (S.delptr ) |
213 | #define newdelflag (S.newdelflag ) | 211 | #define newdelflag (S.newdelflag ) |
214 | #define delbuf (S.delbuf ) | 212 | #define delbuf (S.delbuf ) |
215 | 213 | ||
216 | #define INIT_S() do { \ | 214 | #define INIT_S() do { \ |
217 | (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ | 215 | XZALLOC_CONST_PTR(&lineedit_ptr_to_statics, sizeof(S)); \ |
218 | barrier(); \ | ||
219 | } while (0) | 216 | } while (0) |
220 | 217 | ||
221 | static void deinit_S(void) | 218 | static void deinit_S(void) |
@@ -227,14 +224,47 @@ static void deinit_S(void) | |||
227 | #endif | 224 | #endif |
228 | #if ENABLE_USERNAME_OR_HOMEDIR | 225 | #if ENABLE_USERNAME_OR_HOMEDIR |
229 | free(user_buf); | 226 | free(user_buf); |
230 | if (home_pwd_buf != null_str) | 227 | free(home_pwd_buf); |
231 | free(home_pwd_buf); | ||
232 | #endif | 228 | #endif |
233 | free(lineedit_ptr_to_statics); | 229 | free(lineedit_ptr_to_statics); |
234 | } | 230 | } |
235 | #define DEINIT_S() deinit_S() | 231 | #define DEINIT_S() deinit_S() |
236 | 232 | ||
237 | 233 | ||
234 | #if ENABLE_USERNAME_OR_HOMEDIR | ||
235 | /* Call getpwuid() only if necessary. | ||
236 | * E.g. if PS1=':', no user database reading is needed to generate prompt. | ||
237 | * (Unfortunately, default PS1='\w \$' needs it, \w abbreviates homedir | ||
238 | * as ~/... - for that it needs to *know* the homedir...) | ||
239 | */ | ||
240 | static void get_user_strings(void) | ||
241 | { | ||
242 | struct passwd *entry; | ||
243 | |||
244 | got_user_strings = 1; | ||
245 | entry = getpwuid(geteuid()); | ||
246 | if (entry) { | ||
247 | user_buf = xstrdup(entry->pw_name); | ||
248 | home_pwd_buf = xstrdup(entry->pw_dir); | ||
249 | } | ||
250 | } | ||
251 | |||
252 | static const char *get_username_str(void) | ||
253 | { | ||
254 | if (!got_user_strings) | ||
255 | get_user_strings(); | ||
256 | return user_buf ? user_buf : ""; | ||
257 | /* btw, bash uses "I have no name!" string if uid has no entry */ | ||
258 | } | ||
259 | |||
260 | static NOINLINE const char *get_homedir_or_NULL(void) | ||
261 | { | ||
262 | if (!got_user_strings) | ||
263 | get_user_strings(); | ||
264 | return home_pwd_buf; | ||
265 | } | ||
266 | #endif | ||
267 | |||
238 | #if ENABLE_UNICODE_SUPPORT | 268 | #if ENABLE_UNICODE_SUPPORT |
239 | static size_t load_string(const char *src) | 269 | static size_t load_string(const char *src) |
240 | { | 270 | { |
@@ -748,11 +778,11 @@ static char *username_path_completion(char *ud) | |||
748 | struct passwd *entry; | 778 | struct passwd *entry; |
749 | #endif | 779 | #endif |
750 | char *tilde_name = ud; | 780 | char *tilde_name = ud; |
751 | char *home = NULL; | 781 | const char *home = NULL; |
752 | 782 | ||
753 | ud++; /* skip ~ */ | 783 | ud++; /* skip ~ */ |
754 | if (*ud == '/') { /* "~/..." */ | 784 | if (*ud == '/') { /* "~/..." */ |
755 | home = home_pwd_buf; | 785 | home = get_homedir_or_NULL(); |
756 | # if !ENABLE_PLATFORM_MINGW32 | 786 | # if !ENABLE_PLATFORM_MINGW32 |
757 | } else { | 787 | } else { |
758 | /* "~user/..." */ | 788 | /* "~user/..." */ |
@@ -1881,7 +1911,7 @@ vi_back_motion(void) | |||
1881 | input_backward(1); | 1911 | input_backward(1); |
1882 | } | 1912 | } |
1883 | } | 1913 | } |
1884 | #endif | 1914 | #endif /* ENABLE_FEATURE_EDITING_VI */ |
1885 | 1915 | ||
1886 | /* Modelled after bash 4.0 behavior of Ctrl-<arrow> */ | 1916 | /* Modelled after bash 4.0 behavior of Ctrl-<arrow> */ |
1887 | static void ctrl_left(void) | 1917 | static void ctrl_left(void) |
@@ -1982,7 +2012,7 @@ static void ask_terminal(void) | |||
1982 | } | 2012 | } |
1983 | } | 2013 | } |
1984 | #else | 2014 | #else |
1985 | #define ask_terminal() ((void)0) | 2015 | # define ask_terminal() ((void)0) |
1986 | #endif | 2016 | #endif |
1987 | 2017 | ||
1988 | /* Note about multi-line PS1 (e.g. "\n\w \u@\h\n> ") and prompt redrawing: | 2018 | /* Note about multi-line PS1 (e.g. "\n\w \u@\h\n> ") and prompt redrawing: |
@@ -2091,7 +2121,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2091 | 2121 | ||
2092 | switch (c) { | 2122 | switch (c) { |
2093 | case 'u': | 2123 | case 'u': |
2094 | pbuf = user_buf ? user_buf : (char*)""; | 2124 | pbuf = (char*)get_username_str(); |
2095 | break; | 2125 | break; |
2096 | case 'H': | 2126 | case 'H': |
2097 | case 'h': | 2127 | case 'h': |
@@ -2113,14 +2143,15 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2113 | case 'w': /* current dir */ | 2143 | case 'w': /* current dir */ |
2114 | case 'W': /* basename of cur dir */ | 2144 | case 'W': /* basename of cur dir */ |
2115 | if (!cwd_buf) { | 2145 | if (!cwd_buf) { |
2146 | const char *home; | ||
2116 | cwd_buf = xrealloc_getcwd_or_warn(NULL); | 2147 | cwd_buf = xrealloc_getcwd_or_warn(NULL); |
2117 | if (!cwd_buf) | 2148 | if (!cwd_buf) |
2118 | cwd_buf = (char *)bb_msg_unknown; | 2149 | cwd_buf = (char *)bb_msg_unknown; |
2119 | else if (home_pwd_buf[0]) { | 2150 | else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { |
2120 | char *after_home_user; | 2151 | char *after_home_user; |
2121 | 2152 | ||
2122 | /* /home/user[/something] -> ~[/something] */ | 2153 | /* /home/user[/something] -> ~[/something] */ |
2123 | after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf); | 2154 | after_home_user = is_prefixed_with(cwd_buf, home); |
2124 | if (after_home_user | 2155 | if (after_home_user |
2125 | && (*after_home_user == '/' || *after_home_user == '\0') | 2156 | && (*after_home_user == '/' || *after_home_user == '\0') |
2126 | ) { | 2157 | ) { |
@@ -2176,7 +2207,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2176 | if (c == '\n') | 2207 | if (c == '\n') |
2177 | cmdedit_prmt_len = 0; | 2208 | cmdedit_prmt_len = 0; |
2178 | else if (flg_not_length != ']') { | 2209 | else if (flg_not_length != ']') { |
2179 | #if ENABLE_UNICODE_SUPPORT | 2210 | # if ENABLE_UNICODE_SUPPORT |
2180 | if (n == 1) { | 2211 | if (n == 1) { |
2181 | /* Only count single-byte characters and the first of multi-byte characters */ | 2212 | /* Only count single-byte characters and the first of multi-byte characters */ |
2182 | if ((unsigned char)*pbuf < 0x80 /* single byte character */ | 2213 | if ((unsigned char)*pbuf < 0x80 /* single byte character */ |
@@ -2187,9 +2218,9 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2187 | } else { | 2218 | } else { |
2188 | cmdedit_prmt_len += unicode_strwidth(pbuf); | 2219 | cmdedit_prmt_len += unicode_strwidth(pbuf); |
2189 | } | 2220 | } |
2190 | #else | 2221 | # else |
2191 | cmdedit_prmt_len += n; | 2222 | cmdedit_prmt_len += n; |
2192 | #endif | 2223 | # endif |
2193 | } | 2224 | } |
2194 | } | 2225 | } |
2195 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); | 2226 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); |
@@ -2416,7 +2447,7 @@ static int32_t reverse_i_search(int timeout) | |||
2416 | } | 2447 | } |
2417 | 2448 | ||
2418 | /* Append this char */ | 2449 | /* Append this char */ |
2419 | #if ENABLE_UNICODE_SUPPORT | 2450 | # if ENABLE_UNICODE_SUPPORT |
2420 | if (unicode_status == UNICODE_ON) { | 2451 | if (unicode_status == UNICODE_ON) { |
2421 | mbstate_t mbstate = { 0 }; | 2452 | mbstate_t mbstate = { 0 }; |
2422 | char buf[MB_CUR_MAX + 1]; | 2453 | char buf[MB_CUR_MAX + 1]; |
@@ -2427,7 +2458,7 @@ static int32_t reverse_i_search(int timeout) | |||
2427 | strcpy(match_buf + match_buf_len, buf); | 2458 | strcpy(match_buf + match_buf_len, buf); |
2428 | } | 2459 | } |
2429 | } else | 2460 | } else |
2430 | #endif | 2461 | # endif |
2431 | if (match_buf_len < sizeof(match_buf) - 1) { | 2462 | if (match_buf_len < sizeof(match_buf) - 1) { |
2432 | match_buf[match_buf_len] = ic; | 2463 | match_buf[match_buf_len] = ic; |
2433 | match_buf[match_buf_len + 1] = '\0'; | 2464 | match_buf[match_buf_len + 1] = '\0'; |
@@ -2479,7 +2510,7 @@ static int32_t reverse_i_search(int timeout) | |||
2479 | 2510 | ||
2480 | return ic; | 2511 | return ic; |
2481 | } | 2512 | } |
2482 | #endif | 2513 | #endif /* ENABLE_FEATURE_REVERSE_SEARCH */ |
2483 | 2514 | ||
2484 | #if ENABLE_FEATURE_EDITING_WINCH | 2515 | #if ENABLE_FEATURE_EDITING_WINCH |
2485 | static void sigaction2(int sig, struct sigaction *act) | 2516 | static void sigaction2(int sig, struct sigaction *act) |
@@ -2521,7 +2552,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2521 | //command_len = 0; - done by INIT_S() | 2552 | //command_len = 0; - done by INIT_S() |
2522 | //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ | 2553 | //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ |
2523 | cmdedit_termw = 80; | 2554 | cmdedit_termw = 80; |
2524 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) | ||
2525 | IF_FEATURE_EDITING_VI(delptr = delbuf;) | 2555 | IF_FEATURE_EDITING_VI(delptr = delbuf;) |
2526 | 2556 | ||
2527 | #if !ENABLE_PLATFORM_MINGW32 | 2557 | #if !ENABLE_PLATFORM_MINGW32 |
@@ -2589,18 +2619,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2589 | tcsetattr_stdin_TCSANOW(&new_settings); | 2619 | tcsetattr_stdin_TCSANOW(&new_settings); |
2590 | #endif | 2620 | #endif |
2591 | 2621 | ||
2592 | #if ENABLE_USERNAME_OR_HOMEDIR | ||
2593 | { | ||
2594 | struct passwd *entry; | ||
2595 | |||
2596 | entry = getpwuid(geteuid()); | ||
2597 | if (entry) { | ||
2598 | user_buf = xstrdup(entry->pw_name); | ||
2599 | home_pwd_buf = xstrdup(entry->pw_dir); | ||
2600 | } | ||
2601 | } | ||
2602 | #endif | ||
2603 | |||
2604 | #if 0 | 2622 | #if 0 |
2605 | for (i = 0; i <= state->max_history; i++) | 2623 | for (i = 0; i <= state->max_history; i++) |
2606 | bb_error_msg("history[%d]:'%s'", i, state->history[i]); | 2624 | bb_error_msg("history[%d]:'%s'", i, state->history[i]); |
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 885c19f1a..151739ae2 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -28,6 +28,22 @@ | |||
28 | # ifndef PR_GET_NAME | 28 | # ifndef PR_GET_NAME |
29 | # define PR_GET_NAME 16 | 29 | # define PR_GET_NAME 16 |
30 | # endif | 30 | # endif |
31 | # if ENABLE_FEATURE_SH_STANDALONE || ENABLE_FEATURE_PREFER_APPLETS || !BB_MMU | ||
32 | int FAST_FUNC re_execed_comm(void) | ||
33 | { | ||
34 | const char *e, *expected_comm; | ||
35 | char comm[16]; | ||
36 | |||
37 | BUILD_BUG_ON(CONFIG_BUSYBOX_EXEC_PATH[0] != '/'); | ||
38 | e = CONFIG_BUSYBOX_EXEC_PATH; | ||
39 | /* Hopefully (strrchr(e) - e) evaluates to constant at compile time: */ | ||
40 | expected_comm = bb_busybox_exec_path + (strrchr(e, '/') - e) + 1; | ||
41 | |||
42 | prctl(PR_GET_NAME, (long)comm, 0, 0, 0); | ||
43 | //bb_error_msg("comm:'%.*s' expected:'%s'", 16, comm, expected_comm); | ||
44 | return strcmp(comm, expected_comm) == 0; | ||
45 | } | ||
46 | # endif | ||
31 | void FAST_FUNC set_task_comm(const char *comm) | 47 | void FAST_FUNC set_task_comm(const char *comm) |
32 | { | 48 | { |
33 | /* okay if too long (truncates) */ | 49 | /* okay if too long (truncates) */ |
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index 31680810b..024ee9047 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c | |||
@@ -130,7 +130,7 @@ char* FAST_FUNC xmalloc_realpath(const char *path) | |||
130 | #endif | 130 | #endif |
131 | } | 131 | } |
132 | 132 | ||
133 | char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) | 133 | char* FAST_FUNC xmalloc_realpath_coreutils(char *path) |
134 | { | 134 | { |
135 | char *buf; | 135 | char *buf; |
136 | 136 | ||
@@ -144,32 +144,19 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) | |||
144 | * (the directory must exist). | 144 | * (the directory must exist). |
145 | */ | 145 | */ |
146 | if (!buf && errno == ENOENT) { | 146 | if (!buf && errno == ENOENT) { |
147 | char *last_slash = strrchr(path, '/'); | 147 | char *target, c, *last_slash; |
148 | if (last_slash) { | 148 | size_t i; |
149 | *last_slash++ = '\0'; | 149 | |
150 | buf = xmalloc_realpath(path); | 150 | target = xmalloc_readlink(path); |
151 | if (buf) { | 151 | if (target) { |
152 | unsigned len = strlen(buf); | 152 | /* |
153 | buf = xrealloc(buf, len + strlen(last_slash) + 2); | 153 | * $ ln -s /bin/qwe symlink # note: /bin is a link to /usr/bin |
154 | buf[len++] = '/'; | 154 | * $ readlink -f symlink |
155 | strcpy(buf + len, last_slash); | 155 | * /usr/bin/qwe |
156 | } | 156 | * $ realpath symlink |
157 | } else { | 157 | * /usr/bin/qwe |
158 | char *target = xmalloc_readlink(path); | 158 | */ |
159 | if (target) { | 159 | if (target[0] != '/') { |
160 | char *cwd; | ||
161 | if (target[0] == '/') { | ||
162 | /* | ||
163 | * $ ln -s /bin/qwe symlink # note: /bin is a link to /usr/bin | ||
164 | * $ readlink -f symlink | ||
165 | * /usr/bin/qwe/target_does_not_exist | ||
166 | * $ realpath symlink | ||
167 | * /usr/bin/qwe/target_does_not_exist | ||
168 | */ | ||
169 | buf = xmalloc_realpath_coreutils(target); | ||
170 | free(target); | ||
171 | return buf; | ||
172 | } | ||
173 | /* | 160 | /* |
174 | * $ ln -s target_does_not_exist symlink | 161 | * $ ln -s target_does_not_exist symlink |
175 | * $ readlink -f symlink | 162 | * $ readlink -f symlink |
@@ -177,13 +164,41 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) | |||
177 | * $ realpath symlink | 164 | * $ realpath symlink |
178 | * /CURDIR/target_does_not_exist | 165 | * /CURDIR/target_does_not_exist |
179 | */ | 166 | */ |
180 | cwd = xrealloc_getcwd_or_warn(NULL); | 167 | char *cwd = xrealloc_getcwd_or_warn(NULL); |
181 | buf = concat_path_file(cwd, target); | 168 | char *tmp = concat_path_file(cwd, target); |
182 | free(cwd); | 169 | free(cwd); |
183 | free(target); | 170 | free(target); |
184 | return buf; | 171 | target = tmp; |
172 | } | ||
173 | buf = xmalloc_realpath_coreutils(target); | ||
174 | free(target); | ||
175 | return buf; | ||
176 | } | ||
177 | |||
178 | /* ignore leading and trailing slashes */ | ||
179 | while (path[0] == '/' && path[1] == '/') | ||
180 | ++path; | ||
181 | i = strlen(path) - 1; | ||
182 | while (i > 0 && path[i] == '/') | ||
183 | i--; | ||
184 | c = path[i + 1]; | ||
185 | path[i + 1] = '\0'; | ||
186 | |||
187 | last_slash = strrchr(path, '/'); | ||
188 | if (last_slash == path) | ||
189 | buf = xstrdup(path); | ||
190 | else if (last_slash) { | ||
191 | *last_slash = '\0'; | ||
192 | buf = xmalloc_realpath(path); | ||
193 | *last_slash++ = '/'; | ||
194 | if (buf) { | ||
195 | unsigned len = strlen(buf); | ||
196 | buf = xrealloc(buf, len + strlen(last_slash) + 2); | ||
197 | buf[len++] = '/'; | ||
198 | strcpy(buf + len, last_slash); | ||
185 | } | 199 | } |
186 | } | 200 | } |
201 | path[i + 1] = c; | ||
187 | } | 202 | } |
188 | 203 | ||
189 | return buf; | 204 | return buf; |
diff --git a/mailutils/Config.src b/mailutils/Config.src index 6d47163e4..b3a3e506d 100644 --- a/mailutils/Config.src +++ b/mailutils/Config.src | |||
@@ -1,7 +1,5 @@ | |||
1 | menu "Mail Utilities" | 1 | menu "Mail Utilities" |
2 | 2 | ||
3 | INSERT | ||
4 | |||
5 | config FEATURE_MIME_CHARSET | 3 | config FEATURE_MIME_CHARSET |
6 | string "Default charset" | 4 | string "Default charset" |
7 | default "us-ascii" | 5 | default "us-ascii" |
@@ -9,4 +7,6 @@ config FEATURE_MIME_CHARSET | |||
9 | help | 7 | help |
10 | Default charset of the message. | 8 | Default charset of the message. |
11 | 9 | ||
10 | INSERT | ||
11 | |||
12 | endmenu | 12 | endmenu |
diff --git a/miscutils/bc.c b/miscutils/bc.c index f931be5cc..e3f7573c9 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -2261,7 +2261,7 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size | |||
2261 | } | 2261 | } |
2262 | #define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS) | 2262 | #define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS) |
2263 | 2263 | ||
2264 | static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) | 2264 | static NOINLINE BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) |
2265 | { | 2265 | { |
2266 | BcStatus s; | 2266 | BcStatus s; |
2267 | BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; | 2267 | BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; |
diff --git a/miscutils/less.c b/miscutils/less.c index a5ce14c91..063c4d378 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -1904,7 +1904,7 @@ int less_main(int argc, char **argv) | |||
1904 | getopt32(argv, "EMmN~IF" | 1904 | getopt32(argv, "EMmN~IF" |
1905 | IF_FEATURE_LESS_TRUNCATE("S") | 1905 | IF_FEATURE_LESS_TRUNCATE("S") |
1906 | IF_FEATURE_LESS_RAW("R") | 1906 | IF_FEATURE_LESS_RAW("R") |
1907 | /*ignored:*/"s" | 1907 | /*ignored:*/"sX" |
1908 | ); | 1908 | ); |
1909 | argv += optind; | 1909 | argv += optind; |
1910 | num_files = argc - optind; | 1910 | num_files = argc - optind; |
diff --git a/networking/Config.src b/networking/Config.src index 04d644bc9..0942645c3 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -46,6 +46,32 @@ config VERBOSE_RESOLUTION_ERRORS | |||
46 | "can't resolve 'hostname.com'" and want to know more. | 46 | "can't resolve 'hostname.com'" and want to know more. |
47 | This may increase size of your executable a bit. | 47 | This may increase size of your executable a bit. |
48 | 48 | ||
49 | config FEATURE_ETC_NETWORKS | ||
50 | bool "Support /etc/networks" | ||
51 | default n | ||
52 | help | ||
53 | Enable support for network names in /etc/networks. This is | ||
54 | a rarely used feature which allows you to use names | ||
55 | instead of IP/mask pairs in route command. | ||
56 | |||
57 | config FEATURE_ETC_SERVICES | ||
58 | bool "Consult /etc/services even for well-known ports" | ||
59 | default n | ||
60 | help | ||
61 | Look up e.g. "telnet" and "http" in /etc/services file | ||
62 | instead of assuming ports 23 and 80. | ||
63 | This is almost never necessary (everybody uses standard ports), | ||
64 | and it makes sense to avoid reading this file. | ||
65 | If you disable this option, in the cases where port is explicitly | ||
66 | specified as a service name (e.g. "telnet HOST PORTNAME"), | ||
67 | it will still be looked up in /etc/services. | ||
68 | |||
69 | config FEATURE_HWIB | ||
70 | bool "Support infiniband HW" | ||
71 | default y | ||
72 | help | ||
73 | Support for printing infiniband addresses in network applets. | ||
74 | |||
49 | config FEATURE_TLS_SHA1 | 75 | config FEATURE_TLS_SHA1 |
50 | bool "In TLS code, support ciphers which use deprecated SHA1" | 76 | bool "In TLS code, support ciphers which use deprecated SHA1" |
51 | depends on TLS | 77 | depends on TLS |
diff --git a/networking/brctl.c b/networking/brctl.c index c83aac6e0..956bd91f3 100644 --- a/networking/brctl.c +++ b/networking/brctl.c | |||
@@ -318,7 +318,7 @@ static void printf_xstrtou(const char *fmt) | |||
318 | printf(fmt, xstrtou(filedata, 0)); | 318 | printf(fmt, xstrtou(filedata, 0)); |
319 | } | 319 | } |
320 | 320 | ||
321 | static void show_bridge_port(const char *name) | 321 | static NOINLINE void show_bridge_port(const char *name) |
322 | { | 322 | { |
323 | char pathbuf[IFNAMSIZ + sizeof("/brport/forward_delay_timer") + 8]; | 323 | char pathbuf[IFNAMSIZ + sizeof("/brport/forward_delay_timer") + 8]; |
324 | char *sfx; | 324 | char *sfx; |
diff --git a/networking/httpd.c b/networking/httpd.c index 71e3a723f..6cc189272 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -281,7 +281,7 @@ | |||
281 | //usage: IF_NOT_PLATFORM_MINGW32( | 281 | //usage: IF_NOT_PLATFORM_MINGW32( |
282 | //usage: "\n -i Inetd mode" | 282 | //usage: "\n -i Inetd mode" |
283 | //usage: ) | 283 | //usage: ) |
284 | //usage: "\n -f Don't daemonize" | 284 | //usage: "\n -f Run in foreground" |
285 | //usage: "\n -v[v] Verbose" | 285 | //usage: "\n -v[v] Verbose" |
286 | //usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:"STR(CONFIG_FEATURE_HTTPD_PORT_DEFAULT)")" | 286 | //usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:"STR(CONFIG_FEATURE_HTTPD_PORT_DEFAULT)")" |
287 | //usage: IF_FEATURE_HTTPD_SETUID( | 287 | //usage: IF_FEATURE_HTTPD_SETUID( |
@@ -1918,14 +1918,17 @@ static NOINLINE void send_file_and_exit(const char *url, int what) | |||
1918 | send_headers(HTTP_OK); | 1918 | send_headers(HTTP_OK); |
1919 | #if ENABLE_FEATURE_USE_SENDFILE | 1919 | #if ENABLE_FEATURE_USE_SENDFILE |
1920 | { | 1920 | { |
1921 | off_t offset = (range_start < 0) ? 0 : range_start; | 1921 | off_t offset; |
1922 | if (range_start < 0) | ||
1923 | range_start = 0; | ||
1924 | offset = range_start; | ||
1922 | while (1) { | 1925 | while (1) { |
1923 | /* sz is rounded down to 64k */ | 1926 | /* sz is rounded down to 64k */ |
1924 | ssize_t sz = MAXINT(ssize_t) - 0xffff; | 1927 | ssize_t sz = MAXINT(ssize_t) - 0xffff; |
1925 | IF_FEATURE_HTTPD_RANGES(if (sz > range_len) sz = range_len;) | 1928 | IF_FEATURE_HTTPD_RANGES(if (sz > range_len) sz = range_len;) |
1926 | count = sendfile(STDOUT_FILENO, fd, &offset, sz); | 1929 | count = sendfile(STDOUT_FILENO, fd, &offset, sz); |
1927 | if (count < 0) { | 1930 | if (count < 0) { |
1928 | if (offset == range_start) | 1931 | if (offset == range_start) /* was it the very 1st sendfile? */ |
1929 | break; /* fall back to read/write loop */ | 1932 | break; /* fall back to read/write loop */ |
1930 | goto fin; | 1933 | goto fin; |
1931 | } | 1934 | } |
diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 18dcaff96..c4b6b9584 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c | |||
@@ -20,7 +20,7 @@ | |||
20 | //usage: "[OPTIONS]" | 20 | //usage: "[OPTIONS]" |
21 | //usage:#define ifplugd_full_usage "\n\n" | 21 | //usage:#define ifplugd_full_usage "\n\n" |
22 | //usage: "Network interface plug detection daemon\n" | 22 | //usage: "Network interface plug detection daemon\n" |
23 | //usage: "\n -n Don't daemonize" | 23 | //usage: "\n -n Run in foreground" |
24 | //usage: "\n -s Don't log to syslog" | 24 | //usage: "\n -s Don't log to syslog" |
25 | //usage: "\n -i IFACE Interface" | 25 | //usage: "\n -i IFACE Interface" |
26 | //usage: "\n -f/-F Treat link detection error as link down/link up" | 26 | //usage: "\n -f/-F Treat link detection error as link down/link up" |
diff --git a/networking/ip.c b/networking/ip.c index 85b1ba080..7c3208699 100644 --- a/networking/ip.c +++ b/networking/ip.c | |||
@@ -152,7 +152,7 @@ | |||
152 | //usage:#define iplink_trivial_usage | 152 | //usage:#define iplink_trivial_usage |
153 | //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" | 153 | //usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" |
154 | //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" | 154 | //usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" |
155 | //usage: " [master IFACE | nomaster]" | 155 | //usage: " [master IFACE | nomaster] [netns PID]" |
156 | // * short help shows only "set" command, long help continues (with just one "\n") | 156 | // * short help shows only "set" command, long help continues (with just one "\n") |
157 | // * and shows all other commands: | 157 | // * and shows all other commands: |
158 | //usage:#define iplink_full_usage "\n" | 158 | //usage:#define iplink_full_usage "\n" |
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index 1a1064bdc..68d199044 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c | |||
@@ -153,6 +153,30 @@ static void set_master(char *dev, int master) | |||
153 | } | 153 | } |
154 | 154 | ||
155 | /* Exits on error */ | 155 | /* Exits on error */ |
156 | static void set_netns(char *dev, int netns) | ||
157 | { | ||
158 | struct rtnl_handle rth; | ||
159 | struct { | ||
160 | struct nlmsghdr n; | ||
161 | struct ifinfomsg i; | ||
162 | char buf[1024]; | ||
163 | } req; | ||
164 | |||
165 | memset(&req, 0, sizeof(req)); | ||
166 | req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); | ||
167 | req.n.nlmsg_flags = NLM_F_REQUEST; | ||
168 | req.n.nlmsg_type = RTM_NEWLINK; | ||
169 | req.i.ifi_family = preferred_family; | ||
170 | |||
171 | xrtnl_open(&rth); | ||
172 | req.i.ifi_index = xll_name_to_index(dev); | ||
173 | //printf("netns %i for %i\n", netns, req.i.ifi_index); | ||
174 | addattr_l(&req.n, sizeof(req), IFLA_NET_NS_PID, &netns, 4); | ||
175 | if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) | ||
176 | xfunc_die(); | ||
177 | } | ||
178 | |||
179 | /* Exits on error */ | ||
156 | static int get_address(char *dev, int *htype) | 180 | static int get_address(char *dev, int *htype) |
157 | { | 181 | { |
158 | struct ifreq ifr; | 182 | struct ifreq ifr; |
@@ -226,6 +250,7 @@ static int do_set(char **argv) | |||
226 | int qlen = -1; | 250 | int qlen = -1; |
227 | int mtu = -1; | 251 | int mtu = -1; |
228 | int master = -1; | 252 | int master = -1; |
253 | int netns = -1; | ||
229 | char *newaddr = NULL; | 254 | char *newaddr = NULL; |
230 | char *newbrd = NULL; | 255 | char *newbrd = NULL; |
231 | struct ifreq ifr0, ifr1; | 256 | struct ifreq ifr0, ifr1; |
@@ -234,11 +259,11 @@ static int do_set(char **argv) | |||
234 | /* If you add stuff here, update iplink_full_usage */ | 259 | /* If you add stuff here, update iplink_full_usage */ |
235 | static const char keywords[] ALIGN1 = | 260 | static const char keywords[] ALIGN1 = |
236 | "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" | 261 | "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" |
237 | "arp\0""promisc\0""address\0" | 262 | "arp\0""promisc\0""address\0""netns\0" |
238 | "master\0""nomaster\0" | 263 | "master\0""nomaster\0" |
239 | "dev\0" /* must be last */; | 264 | "dev\0" /* must be last */; |
240 | enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, | 265 | enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, |
241 | ARG_arp, ARG_promisc, ARG_addr, | 266 | ARG_arp, ARG_promisc, ARG_addr, ARG_netns, |
242 | ARG_master, ARG_nomaster, | 267 | ARG_master, ARG_nomaster, |
243 | ARG_dev }; | 268 | ARG_dev }; |
244 | enum { PARM_on = 0, PARM_off }; | 269 | enum { PARM_on = 0, PARM_off }; |
@@ -276,6 +301,9 @@ static int do_set(char **argv) | |||
276 | master = xll_name_to_index(*argv); | 301 | master = xll_name_to_index(*argv); |
277 | } else if (key == ARG_nomaster) { | 302 | } else if (key == ARG_nomaster) { |
278 | master = 0; | 303 | master = 0; |
304 | } else if (key == ARG_netns) { | ||
305 | NEXT_ARG(); | ||
306 | netns = get_unsigned(*argv, "netns"); | ||
279 | } else if (key >= ARG_dev) { | 307 | } else if (key >= ARG_dev) { |
280 | /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ | 308 | /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ |
281 | if (key == ARG_dev) { | 309 | if (key == ARG_dev) { |
@@ -463,6 +491,9 @@ static int do_set(char **argv) | |||
463 | if (master != -1) { | 491 | if (master != -1) { |
464 | set_master(dev, master); | 492 | set_master(dev, master); |
465 | } | 493 | } |
494 | if (netns != -1) { | ||
495 | set_netns(dev, netns); | ||
496 | } | ||
466 | if (mask) | 497 | if (mask) |
467 | do_chflags(dev, flags, mask); | 498 | do_chflags(dev, flags, mask); |
468 | return 0; | 499 | return 0; |
diff --git a/networking/nslookup.c b/networking/nslookup.c index de7b5c0e7..6da97baf4 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c | |||
@@ -335,7 +335,7 @@ enum { | |||
335 | OPT_debug = (1 << 0), | 335 | OPT_debug = (1 << 0), |
336 | }; | 336 | }; |
337 | 337 | ||
338 | static int parse_reply(const unsigned char *msg, size_t len) | 338 | static NOINLINE int parse_reply(const unsigned char *msg, size_t len) |
339 | { | 339 | { |
340 | HEADER *header; | 340 | HEADER *header; |
341 | 341 | ||
diff --git a/networking/ntpd.c b/networking/ntpd.c index 6bf6c4e07..204e1d7c2 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -78,7 +78,7 @@ | |||
78 | //usage:#define ntpd_full_usage "\n\n" | 78 | //usage:#define ntpd_full_usage "\n\n" |
79 | //usage: "NTP client/server\n" | 79 | //usage: "NTP client/server\n" |
80 | //usage: "\n -d[d] Verbose" | 80 | //usage: "\n -d[d] Verbose" |
81 | //usage: "\n -n Do not daemonize" | 81 | //usage: "\n -n Run in foreground" |
82 | //usage: "\n -q Quit after clock is set" | 82 | //usage: "\n -q Quit after clock is set" |
83 | //usage: "\n -N Run at high priority" | 83 | //usage: "\n -N Run at high priority" |
84 | //usage: "\n -w Do not set time (only query peers), implies -n" | 84 | //usage: "\n -w Do not set time (only query peers), implies -n" |
@@ -1152,7 +1152,7 @@ fit(peer_t *p, double rd) | |||
1152 | // return 0; | 1152 | // return 0; |
1153 | return 1; | 1153 | return 1; |
1154 | } | 1154 | } |
1155 | static peer_t* | 1155 | static NOINLINE peer_t* |
1156 | select_and_cluster(void) | 1156 | select_and_cluster(void) |
1157 | { | 1157 | { |
1158 | peer_t *p; | 1158 | peer_t *p; |
diff --git a/networking/tls.c b/networking/tls.c index a1b12f9ed..36f83212b 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -22,47 +22,23 @@ | |||
22 | 22 | ||
23 | #include "tls.h" | 23 | #include "tls.h" |
24 | 24 | ||
25 | // Usually enabled. You can disable some of them to force only | ||
26 | // specific ciphers to be advertized to server. | ||
27 | // (this would not exclude code to handle disabled ciphers, no code size win) | ||
28 | #define ALLOW_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 1 | ||
29 | #define ALLOW_ECDHE_RSA_WITH_AES_128_CBC_SHA256 1 | ||
30 | #define ALLOW_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 1 | ||
31 | #define ALLOW_ECDHE_RSA_WITH_AES_128_GCM_SHA256 1 | ||
32 | #define ALLOW_RSA_WITH_AES_128_CBC_SHA256 1 | ||
33 | #define ALLOW_RSA_WITH_AES_256_CBC_SHA256 1 | ||
34 | #define ALLOW_RSA_WITH_AES_128_GCM_SHA256 1 | ||
35 | #define ALLOW_CURVE_P256 1 | ||
36 | #define ALLOW_CURVE_X25519 1 | ||
37 | |||
38 | // For testing (does everything except encrypting). | ||
25 | // works against "openssl s_server -cipher NULL" | 39 | // works against "openssl s_server -cipher NULL" |
26 | // and against wolfssl-3.9.10-stable/examples/server/server.c: | 40 | // and against wolfssl-3.9.10-stable/examples/server/server.c: |
27 | #define ALLOW_RSA_NULL_SHA256 0 // for testing (does everything except encrypting) | 41 | #define ALLOW_RSA_NULL_SHA256 0 |
28 | |||
29 | //Tested against kernel.org: | ||
30 | //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box | ||
31 | //#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE | ||
32 | //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE | ||
33 | //^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck, server refuses it) | ||
34 | //#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE | ||
35 | //#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE | ||
36 | //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // ok, recvs SERVER_KEY_EXCHANGE | ||
37 | //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | ||
38 | //#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 | ||
39 | //#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE | ||
40 | //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 | ||
41 | //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE | ||
42 | //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE | ||
43 | //#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE | ||
44 | |||
45 | // works against wolfssl-3.9.10-stable/examples/server/server.c | ||
46 | // works for kernel.org | ||
47 | // does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page) | ||
48 | // getting alert 40 "handshake failure" at once | ||
49 | // with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher | ||
50 | // fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES256-SHA256 | ||
51 | // fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES256-GCM-SHA384 | ||
52 | // fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-SHA256 | ||
53 | // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-GCM-SHA256 | ||
54 | // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-SHA | ||
55 | // (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) | ||
56 | //#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 //0x003D | ||
57 | // Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" | ||
58 | //#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA //0x002F | ||
59 | |||
60 | // bug #11456: | ||
61 | // ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305 | ||
62 | //#define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //0xC02F | ||
63 | // host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009) | ||
64 | //#define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA //0xC009 | ||
65 | |||
66 | 42 | ||
67 | #define TLS_DEBUG 0 | 43 | #define TLS_DEBUG 0 |
68 | #define TLS_DEBUG_HASH 0 | 44 | #define TLS_DEBUG_HASH 0 |
@@ -1488,9 +1464,20 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un | |||
1488 | 1464 | ||
1489 | static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | 1465 | static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) |
1490 | { | 1466 | { |
1491 | #define NUM_CIPHERS (7 + 6 * ENABLE_FEATURE_TLS_SHA1 + ALLOW_RSA_NULL_SHA256) | 1467 | #define NUM_CIPHERS (0 \ |
1468 | + 4 * ENABLE_FEATURE_TLS_SHA1 \ | ||
1469 | + ALLOW_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 \ | ||
1470 | + ALLOW_ECDHE_RSA_WITH_AES_128_CBC_SHA256 \ | ||
1471 | + ALLOW_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 \ | ||
1472 | + ALLOW_ECDHE_RSA_WITH_AES_128_GCM_SHA256 \ | ||
1473 | + 2 * ENABLE_FEATURE_TLS_SHA1 \ | ||
1474 | + ALLOW_RSA_WITH_AES_128_CBC_SHA256 \ | ||
1475 | + ALLOW_RSA_WITH_AES_256_CBC_SHA256 \ | ||
1476 | + ALLOW_RSA_WITH_AES_128_GCM_SHA256 \ | ||
1477 | + ALLOW_RSA_NULL_SHA256 \ | ||
1478 | ) | ||
1492 | static const uint8_t ciphers[] = { | 1479 | static const uint8_t ciphers[] = { |
1493 | 0x00,2 + NUM_CIPHERS*2, //len16_be | 1480 | 0x00,2 * (1 + NUM_CIPHERS), //len16_be |
1494 | 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV | 1481 | 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV |
1495 | /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ | 1482 | /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ |
1496 | #if ENABLE_FEATURE_TLS_SHA1 | 1483 | #if ENABLE_FEATURE_TLS_SHA1 |
@@ -1501,14 +1488,22 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
1501 | // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA | 1488 | // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA |
1502 | // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA | 1489 | // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA |
1503 | #endif | 1490 | #endif |
1491 | #if ALLOW_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 | ||
1504 | 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ | 1492 | 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ |
1493 | #endif | ||
1505 | // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet | 1494 | // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet |
1495 | #if ALLOW_ECDHE_RSA_WITH_AES_128_CBC_SHA256 | ||
1506 | 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 | 1496 | 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 |
1497 | #endif | ||
1507 | // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet | 1498 | // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet |
1499 | #if ALLOW_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 | ||
1508 | 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ | 1500 | 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ |
1501 | #endif | ||
1509 | // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" | 1502 | // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" |
1510 | //TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF? | 1503 | //TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF? |
1504 | #if ALLOW_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | ||
1511 | 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 | 1505 | 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 |
1506 | #endif | ||
1512 | // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" | 1507 | // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" |
1513 | //possibly these too: | 1508 | //possibly these too: |
1514 | #if ENABLE_FEATURE_TLS_SHA1 | 1509 | #if ENABLE_FEATURE_TLS_SHA1 |
@@ -1521,9 +1516,15 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
1521 | 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA | 1516 | 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA |
1522 | 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA | 1517 | 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA |
1523 | #endif | 1518 | #endif |
1519 | #if ALLOW_RSA_WITH_AES_128_CBC_SHA256 | ||
1524 | 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 | 1520 | 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 |
1521 | #endif | ||
1522 | #if ALLOW_RSA_WITH_AES_256_CBC_SHA256 | ||
1525 | 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 | 1523 | 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 |
1524 | #endif | ||
1525 | #if ALLOW_RSA_WITH_AES_128_GCM_SHA256 | ||
1526 | 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 | 1526 | 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 |
1527 | #endif | ||
1527 | // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" | 1528 | // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" |
1528 | #if ALLOW_RSA_NULL_SHA256 | 1529 | #if ALLOW_RSA_NULL_SHA256 |
1529 | 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 | 1530 | 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 |
@@ -1532,12 +1533,16 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
1532 | }; | 1533 | }; |
1533 | static const uint8_t supported_groups[] = { | 1534 | static const uint8_t supported_groups[] = { |
1534 | 0x00,0x0a, //extension_type: "supported_groups" | 1535 | 0x00,0x0a, //extension_type: "supported_groups" |
1535 | 0x00,0x06, //ext len | 1536 | 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len |
1536 | 0x00,0x04, //list len | 1537 | 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len |
1537 | 0x00,0x17, //curve_secp256r1 (aka P256) | 1538 | #if ALLOW_CURVE_P256 |
1539 | 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1) | ||
1540 | #endif | ||
1538 | //0x00,0x18, //curve_secp384r1 | 1541 | //0x00,0x18, //curve_secp384r1 |
1539 | //0x00,0x19, //curve_secp521r1 | 1542 | //0x00,0x19, //curve_secp521r1 |
1543 | #if ALLOW_CURVE_X25519 | ||
1540 | 0x00,0x1d, //curve_x25519 (RFC 7748) | 1544 | 0x00,0x1d, //curve_x25519 (RFC 7748) |
1545 | #endif | ||
1541 | //0x00,0x1e, //curve_x448 (RFC 7748) | 1546 | //0x00,0x1e, //curve_x448 (RFC 7748) |
1542 | }; | 1547 | }; |
1543 | //static const uint8_t signature_algorithms[] = { | 1548 | //static const uint8_t signature_algorithms[] = { |
@@ -1555,7 +1560,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
1555 | uint8_t session_id_len; | 1560 | uint8_t session_id_len; |
1556 | /* uint8_t session_id[]; */ | 1561 | /* uint8_t session_id[]; */ |
1557 | uint8_t cipherid_len16_hi, cipherid_len16_lo; | 1562 | uint8_t cipherid_len16_hi, cipherid_len16_lo; |
1558 | uint8_t cipherid[2 + NUM_CIPHERS*2]; /* actually variable */ | 1563 | uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ |
1559 | uint8_t comprtypes_len; | 1564 | uint8_t comprtypes_len; |
1560 | uint8_t comprtypes[1]; /* actually variable */ | 1565 | uint8_t comprtypes[1]; /* actually variable */ |
1561 | /* Extensions (SNI shown): | 1566 | /* Extensions (SNI shown): |
@@ -1603,7 +1608,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
1603 | memset(record->rand32, 0x11, sizeof(record->rand32)); | 1608 | memset(record->rand32, 0x11, sizeof(record->rand32)); |
1604 | /* record->session_id_len = 0; - already is */ | 1609 | /* record->session_id_len = 0; - already is */ |
1605 | 1610 | ||
1606 | BUILD_BUG_ON(sizeof(ciphers) != 2 + 2 + NUM_CIPHERS*2 + 2); | 1611 | BUILD_BUG_ON(sizeof(ciphers) != 2 * (1 + 1 + NUM_CIPHERS + 1)); |
1607 | memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers)); | 1612 | memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers)); |
1608 | 1613 | ||
1609 | ptr = (void*)(record + 1); | 1614 | ptr = (void*)(record + 1); |
@@ -1700,42 +1705,33 @@ static void get_server_hello(tls_state_t *tls) | |||
1700 | 1705 | ||
1701 | /* Set up encryption params based on selected cipher */ | 1706 | /* Set up encryption params based on selected cipher */ |
1702 | #if 0 | 1707 | #if 0 |
1703 | #if ENABLE_FEATURE_TLS_SHA1 | ||
1704 | 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ | 1708 | 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ |
1705 | 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ | 1709 | 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ |
1706 | 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA | 1710 | 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA |
1707 | 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl) | 1711 | 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl) |
1708 | // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA | 1712 | // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA |
1709 | // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA | 1713 | // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA |
1710 | #endif | ||
1711 | 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ | 1714 | 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ |
1712 | // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet | 1715 | // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet |
1713 | 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 | 1716 | 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 |
1714 | // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet | 1717 | // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet |
1715 | 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ | 1718 | 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ |
1716 | // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" | 1719 | // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" |
1717 | //TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF? | ||
1718 | 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 | 1720 | 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 |
1719 | // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" | 1721 | // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" |
1720 | //possibly these too: | 1722 | //possibly these too: |
1721 | #if ENABLE_FEATURE_TLS_SHA1 | ||
1722 | // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA | 1723 | // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA |
1723 | // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA | 1724 | // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA |
1724 | #endif | ||
1725 | // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 | 1725 | // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 |
1726 | // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet | 1726 | // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet |
1727 | #if ENABLE_FEATURE_TLS_SHA1 | ||
1728 | 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA | 1727 | 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA |
1729 | 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA | 1728 | 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA |
1730 | #endif | ||
1731 | 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 | 1729 | 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 |
1732 | 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 | 1730 | 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 |
1733 | 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 | 1731 | 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 |
1734 | // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" | 1732 | // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" |
1735 | #if ALLOW_RSA_NULL_SHA256 | ||
1736 | 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 | 1733 | 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 |
1737 | #endif | 1734 | #endif |
1738 | #endif | ||
1739 | cipherid1 = cipherid[1]; | 1735 | cipherid1 = cipherid[1]; |
1740 | tls->cipher_id = 0x100 * cipherid[0] + cipherid1; | 1736 | tls->cipher_id = 0x100 * cipherid[0] + cipherid1; |
1741 | tls->key_size = AES256_KEYSIZE; | 1737 | tls->key_size = AES256_KEYSIZE; |
@@ -1944,7 +1940,7 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1944 | if (!(tls->flags & NEED_EC_KEY)) { | 1940 | if (!(tls->flags & NEED_EC_KEY)) { |
1945 | /* RSA */ | 1941 | /* RSA */ |
1946 | if (!(tls->flags & GOT_CERT_RSA_KEY_ALG)) | 1942 | if (!(tls->flags & GOT_CERT_RSA_KEY_ALG)) |
1947 | bb_simple_error_msg("server cert is not RSA"); | 1943 | bb_simple_error_msg_and_die("server cert is not RSA"); |
1948 | 1944 | ||
1949 | tls_get_random(premaster, RSA_PREMASTER_SIZE); | 1945 | tls_get_random(premaster, RSA_PREMASTER_SIZE); |
1950 | if (TLS_DEBUG_FIXED_SECRETS) | 1946 | if (TLS_DEBUG_FIXED_SECRETS) |
@@ -2330,6 +2326,47 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) | |||
2330 | const int INBUF_STEP = 4 * 1024; | 2326 | const int INBUF_STEP = 4 * 1024; |
2331 | struct pollfd pfds[2]; | 2327 | struct pollfd pfds[2]; |
2332 | 2328 | ||
2329 | #if 0 | ||
2330 | // Debug aid for comparing P256 implementations. | ||
2331 | // Enable this, set SP_DEBUG and FIXED_SECRET to 1, | ||
2332 | // and add | ||
2333 | // tls_run_copy_loop(NULL, 0); | ||
2334 | // e.g. at the very beginning of wget_main() | ||
2335 | // | ||
2336 | { | ||
2337 | uint8_t ecc_pub_key32[2 * 32]; | ||
2338 | uint8_t pubkey2x32[2 * 32]; | ||
2339 | uint8_t premaster32[32]; | ||
2340 | |||
2341 | //Fixed input key: | ||
2342 | // memset(ecc_pub_key32, 0xee, sizeof(ecc_pub_key32)); | ||
2343 | //Fixed 000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||
2344 | // memset(ecc_pub_key32, 0x00, sizeof(ecc_pub_key32)); | ||
2345 | // ecc_pub_key32[18] = 0xab; | ||
2346 | //Random key: | ||
2347 | // tls_get_random(ecc_pub_key32, sizeof(ecc_pub_key32)); | ||
2348 | //Biased random (almost all zeros or almost all ones): | ||
2349 | srand(time(NULL) ^ getpid()); | ||
2350 | if (rand() & 1) | ||
2351 | memset(ecc_pub_key32, 0x00, sizeof(ecc_pub_key32)); | ||
2352 | else | ||
2353 | memset(ecc_pub_key32, 0xff, sizeof(ecc_pub_key32)); | ||
2354 | ecc_pub_key32[rand() & 0x3f] = rand(); | ||
2355 | |||
2356 | xmove_fd(xopen("p256.OLD", O_WRONLY | O_CREAT | O_TRUNC), 2); | ||
2357 | curve_P256_compute_pubkey_and_premaster( | ||
2358 | pubkey2x32, premaster32, | ||
2359 | /*point:*/ ecc_pub_key32 | ||
2360 | ); | ||
2361 | xmove_fd(xopen("p256.NEW", O_WRONLY | O_CREAT | O_TRUNC), 2); | ||
2362 | curve_P256_compute_pubkey_and_premaster_NEW( | ||
2363 | pubkey2x32, premaster32, | ||
2364 | /*point:*/ ecc_pub_key32 | ||
2365 | ); | ||
2366 | exit(1); | ||
2367 | } | ||
2368 | #endif | ||
2369 | |||
2333 | pfds[0].fd = STDIN_FILENO; | 2370 | pfds[0].fd = STDIN_FILENO; |
2334 | pfds[0].events = POLLIN; | 2371 | pfds[0].events = POLLIN; |
2335 | pfds[1].fd = tls->ifd; | 2372 | pfds[1].fd = tls->ifd; |
diff --git a/networking/tls.h b/networking/tls.h index 215e92b02..0173b87b2 100644 --- a/networking/tls.h +++ b/networking/tls.h | |||
@@ -101,7 +101,6 @@ void xorbuf_aligned_AES_BLOCK_SIZE(void* buf, const void* mask) FAST_FUNC; | |||
101 | 101 | ||
102 | 102 | ||
103 | #include "tls_pstm.h" | 103 | #include "tls_pstm.h" |
104 | #include "tls_symmetric.h" | ||
105 | #include "tls_aes.h" | 104 | #include "tls_aes.h" |
106 | #include "tls_aesgcm.h" | 105 | #include "tls_aesgcm.h" |
107 | #include "tls_rsa.h" | 106 | #include "tls_rsa.h" |
@@ -117,3 +116,7 @@ void curve_x25519_compute_pubkey_and_premaster( | |||
117 | void curve_P256_compute_pubkey_and_premaster( | 116 | void curve_P256_compute_pubkey_and_premaster( |
118 | uint8_t *pubkey2x32, uint8_t *premaster32, | 117 | uint8_t *pubkey2x32, uint8_t *premaster32, |
119 | const uint8_t *peerkey2x32) FAST_FUNC; | 118 | const uint8_t *peerkey2x32) FAST_FUNC; |
119 | |||
120 | void curve_P256_compute_pubkey_and_premaster_NEW( | ||
121 | uint8_t *pubkey2x32, uint8_t *premaster32, | ||
122 | const uint8_t *peerkey2x32) FAST_FUNC; | ||
diff --git a/networking/tls_fe.c b/networking/tls_fe.c index ecb410281..3a0a6776f 100644 --- a/networking/tls_fe.c +++ b/networking/tls_fe.c | |||
@@ -63,16 +63,22 @@ static void fprime_select(byte *dst, const byte *zero, const byte *one, byte con | |||
63 | } | 63 | } |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | #if 0 /* constant-time */ | ||
66 | static void fe_select(byte *dst, | 67 | static void fe_select(byte *dst, |
67 | const byte *zero, const byte *one, | 68 | const byte *src, |
68 | byte condition) | 69 | byte condition) |
69 | { | 70 | { |
70 | const byte mask = -condition; | 71 | const byte mask = -condition; |
71 | int i; | 72 | int i; |
72 | 73 | ||
73 | for (i = 0; i < F25519_SIZE; i++) | 74 | for (i = 0; i < F25519_SIZE; i++) |
74 | dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); | 75 | dst[i] = dst[i] ^ (mask & (src[i] ^ dst[i])); |
75 | } | 76 | } |
77 | #else | ||
78 | # define fe_select(dst, src, condition) do { \ | ||
79 | if (condition) lm_copy(dst, src); \ | ||
80 | } while (0) | ||
81 | #endif | ||
76 | 82 | ||
77 | #if 0 //UNUSED | 83 | #if 0 //UNUSED |
78 | static void raw_add(byte *x, const byte *p) | 84 | static void raw_add(byte *x, const byte *p) |
@@ -225,7 +231,7 @@ static void fe_normalize(byte *x) | |||
225 | minusp[31] = (byte)c; | 231 | minusp[31] = (byte)c; |
226 | 232 | ||
227 | /* Load x-p if no underflow */ | 233 | /* Load x-p if no underflow */ |
228 | fe_select(x, minusp, x, (c >> 15) & 1); | 234 | fe_select(x, minusp, !(c & (1<<15))); |
229 | } | 235 | } |
230 | 236 | ||
231 | static void lm_add(byte* r, const byte* a, const byte* b) | 237 | static void lm_add(byte* r, const byte* a, const byte* b) |
@@ -548,26 +554,32 @@ static void curve25519(byte *result, const byte *e, const byte *q) | |||
548 | { | 554 | { |
549 | int i; | 555 | int i; |
550 | 556 | ||
551 | struct { | 557 | struct Z { |
552 | /* for bbox's special case of q == NULL meaning "use basepoint" */ | 558 | /* for bbox's special case of q == NULL meaning "use basepoint" */ |
553 | /*static const*/ uint8_t basepoint9[CURVE25519_KEYSIZE]; // = {9}; | 559 | /*static const*/ uint8_t basepoint9[CURVE25519_KEYSIZE]; // = {9}; |
554 | 560 | ||
555 | /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */ | 561 | /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */ |
556 | /*static const*/ byte f25519_one[F25519_SIZE]; // = {1}; | 562 | /*static const*/ byte f25519_one[F25519_SIZE]; // = {1}; |
557 | 563 | ||
558 | /* Current point: P_m */ | ||
559 | byte xm[F25519_SIZE]; | ||
560 | byte zm[F25519_SIZE]; // = {1}; | ||
561 | /* Predecessor: P_(m-1) */ | 564 | /* Predecessor: P_(m-1) */ |
562 | byte xm1[F25519_SIZE]; // = {1}; | 565 | byte xm1[F25519_SIZE]; // = {1}; |
563 | byte zm1[F25519_SIZE]; // = {0}; | 566 | byte zm1[F25519_SIZE]; // = {0}; |
567 | /* Current point: P_m */ | ||
568 | byte xm[F25519_SIZE]; | ||
569 | byte zm[F25519_SIZE]; // = {1}; | ||
570 | /* Temporaries */ | ||
571 | byte xms[F25519_SIZE]; | ||
572 | byte zms[F25519_SIZE]; | ||
564 | } z; | 573 | } z; |
574 | uint8_t *XM1 = (uint8_t*)&z + offsetof(struct Z,xm1); // gcc 11.0.0 workaround | ||
565 | #define basepoint9 z.basepoint9 | 575 | #define basepoint9 z.basepoint9 |
566 | #define f25519_one z.f25519_one | 576 | #define f25519_one z.f25519_one |
567 | #define xm z.xm | ||
568 | #define zm z.zm | ||
569 | #define xm1 z.xm1 | 577 | #define xm1 z.xm1 |
570 | #define zm1 z.zm1 | 578 | #define zm1 z.zm1 |
579 | #define xm z.xm | ||
580 | #define zm z.zm | ||
581 | #define xms z.xms | ||
582 | #define zms z.zms | ||
571 | memset(&z, 0, sizeof(z)); | 583 | memset(&z, 0, sizeof(z)); |
572 | f25519_one[0] = 1; | 584 | f25519_one[0] = 1; |
573 | zm[0] = 1; | 585 | zm[0] = 1; |
@@ -583,8 +595,8 @@ static void curve25519(byte *result, const byte *e, const byte *q) | |||
583 | 595 | ||
584 | for (i = 253; i >= 0; i--) { | 596 | for (i = 253; i >= 0; i--) { |
585 | const int bit = (e[i >> 3] >> (i & 7)) & 1; | 597 | const int bit = (e[i >> 3] >> (i & 7)) & 1; |
586 | byte xms[F25519_SIZE]; | 598 | // byte xms[F25519_SIZE]; |
587 | byte zms[F25519_SIZE]; | 599 | // byte zms[F25519_SIZE]; |
588 | 600 | ||
589 | /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */ | 601 | /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */ |
590 | xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1); | 602 | xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1); |
@@ -597,10 +609,22 @@ static void curve25519(byte *result, const byte *e, const byte *q) | |||
597 | * bit = 1 --> (P_(2m+1), P_(2m)) | 609 | * bit = 1 --> (P_(2m+1), P_(2m)) |
598 | * bit = 0 --> (P_(2m), P_(2m-1)) | 610 | * bit = 0 --> (P_(2m), P_(2m-1)) |
599 | */ | 611 | */ |
600 | fe_select(xm1, xm1, xm, bit); | 612 | #if 0 |
601 | fe_select(zm1, zm1, zm, bit); | 613 | fe_select(xm1, xm, bit); |
602 | fe_select(xm, xm, xms, bit); | 614 | fe_select(zm1, zm, bit); |
603 | fe_select(zm, zm, zms, bit); | 615 | fe_select(xm, xms, bit); |
616 | fe_select(zm, zms, bit); | ||
617 | #else | ||
618 | // same as above in about 50 bytes smaller code, but | ||
619 | // requires that in-memory order is exactly xm1,zm1,xm,zm,xms,zms | ||
620 | if (bit) { | ||
621 | //memcpy(xm1, xm, 4 * F25519_SIZE); | ||
622 | //^^^ gcc 11.0.0 warns of overlapping memcpy | ||
623 | //memmove(xm1, xm, 4 * F25519_SIZE); | ||
624 | //^^^ gcc 11.0.0 warns of out-of-bounds access to xm1[] | ||
625 | memmove(XM1, XM1 + 2 * F25519_SIZE, 4 * F25519_SIZE); | ||
626 | } | ||
627 | #endif | ||
604 | } | 628 | } |
605 | 629 | ||
606 | /* Freeze out of projective coordinates */ | 630 | /* Freeze out of projective coordinates */ |
diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h index bc7a0119a..56c6bb879 100644 --- a/networking/tls_pstm.h +++ b/networking/tls_pstm.h | |||
@@ -283,4 +283,3 @@ extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b, | |||
283 | typedef int32 pstm_int; | 283 | typedef int32 pstm_int; |
284 | #endif /* !DISABLE_PSTM */ | 284 | #endif /* !DISABLE_PSTM */ |
285 | #endif /* _h_PSTMATH */ | 285 | #endif /* _h_PSTMATH */ |
286 | |||
diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c index 5a84852a5..4d4ecdd74 100644 --- a/networking/tls_sp_c32.c +++ b/networking/tls_sp_c32.c | |||
@@ -9,6 +9,8 @@ | |||
9 | #define FIXED_SECRET 0 | 9 | #define FIXED_SECRET 0 |
10 | #define FIXED_PEER_PUBKEY 0 | 10 | #define FIXED_PEER_PUBKEY 0 |
11 | 11 | ||
12 | #define ALLOW_ASM 1 | ||
13 | |||
12 | #if SP_DEBUG | 14 | #if SP_DEBUG |
13 | # define dbg(...) fprintf(stderr, __VA_ARGS__) | 15 | # define dbg(...) fprintf(stderr, __VA_ARGS__) |
14 | static void dump_hex(const char *fmt, const void *vp, int len) | 16 | static void dump_hex(const char *fmt, const void *vp, int len) |
@@ -24,127 +26,98 @@ static void dump_hex(const char *fmt, const void *vp, int len) | |||
24 | # define dump_hex(...) ((void)0) | 26 | # define dump_hex(...) ((void)0) |
25 | #endif | 27 | #endif |
26 | 28 | ||
27 | #undef DIGIT_BIT | 29 | typedef uint32_t sp_digit; |
28 | #define DIGIT_BIT 32 | 30 | typedef int32_t signed_sp_digit; |
29 | typedef int32_t sp_digit; | ||
30 | 31 | ||
31 | /* The code below is taken from parts of | 32 | /* The code below is taken from parts of |
32 | * wolfssl-3.15.3/wolfcrypt/src/sp_c32.c | 33 | * wolfssl-3.15.3/wolfcrypt/src/sp_c32.c |
33 | * and heavily modified. | 34 | * and heavily modified. |
34 | * Header comment is kept intact: | ||
35 | */ | 35 | */ |
36 | 36 | ||
37 | /* sp.c | ||
38 | * | ||
39 | * Copyright (C) 2006-2018 wolfSSL Inc. | ||
40 | * | ||
41 | * This file is part of wolfSSL. | ||
42 | * | ||
43 | * wolfSSL is free software; you can redistribute it and/or modify | ||
44 | * it under the terms of the GNU General Public License as published by | ||
45 | * the Free Software Foundation; either version 2 of the License, or | ||
46 | * (at your option) any later version. | ||
47 | * | ||
48 | * wolfSSL is distributed in the hope that it will be useful, | ||
49 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
50 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
51 | * GNU General Public License for more details. | ||
52 | * | ||
53 | * You should have received a copy of the GNU General Public License | ||
54 | * along with this program; if not, write to the Free Software | ||
55 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA | ||
56 | */ | ||
57 | |||
58 | /* Implementation by Sean Parkinson. */ | ||
59 | |||
60 | typedef struct sp_point { | 37 | typedef struct sp_point { |
61 | sp_digit x[2 * 10]; | 38 | sp_digit x[2 * 8]; |
62 | sp_digit y[2 * 10]; | 39 | sp_digit y[2 * 8]; |
63 | sp_digit z[2 * 10]; | 40 | sp_digit z[2 * 8]; |
64 | int infinity; | 41 | int infinity; |
65 | } sp_point; | 42 | } sp_point; |
66 | 43 | ||
67 | /* The modulus (prime) of the curve P256. */ | 44 | /* The modulus (prime) of the curve P256. */ |
68 | static const sp_digit p256_mod[10] = { | 45 | static const sp_digit p256_mod[8] = { |
69 | 0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000, | 46 | 0xffffffff,0xffffffff,0xffffffff,0x00000000, |
70 | 0x0000000,0x0000000,0x0000400,0x3ff0000,0x03fffff, | 47 | 0x00000000,0x00000000,0x00000001,0xffffffff, |
71 | }; | 48 | }; |
72 | 49 | ||
73 | #define p256_mp_mod ((sp_digit)0x000001) | 50 | #define p256_mp_mod ((sp_digit)0x000001) |
74 | 51 | ||
75 | /* Write r as big endian to byte aray. | 52 | /* Normalize the values in each word to 32 bits - NOP */ |
53 | #define sp_256_norm_8(a) ((void)0) | ||
54 | |||
55 | /* Write r as big endian to byte array. | ||
76 | * Fixed length number of bytes written: 32 | 56 | * Fixed length number of bytes written: 32 |
77 | * | 57 | * |
78 | * r A single precision integer. | 58 | * r A single precision integer. |
79 | * a Byte array. | 59 | * a Byte array. |
80 | */ | 60 | */ |
81 | static void sp_256_to_bin(sp_digit* r, uint8_t* a) | 61 | static void sp_256_to_bin_8(const sp_digit* r, uint8_t* a) |
82 | { | 62 | { |
83 | int i, j, s = 0, b; | 63 | int i; |
84 | 64 | ||
85 | for (i = 0; i < 9; i++) { | 65 | sp_256_norm_8(r); |
86 | r[i+1] += r[i] >> 26; | 66 | |
87 | r[i] &= 0x3ffffff; | 67 | r += 8; |
88 | } | 68 | for (i = 0; i < 8; i++) { |
89 | j = 256 / 8 - 1; | 69 | r--; |
90 | a[j] = 0; | 70 | move_to_unaligned32(a, SWAP_BE32(*r)); |
91 | for (i = 0; i < 10 && j >= 0; i++) { | 71 | a += 4; |
92 | b = 0; | ||
93 | a[j--] |= r[i] << s; b += 8 - s; | ||
94 | if (j < 0) | ||
95 | break; | ||
96 | while (b < 26) { | ||
97 | a[j--] = r[i] >> b; b += 8; | ||
98 | if (j < 0) | ||
99 | break; | ||
100 | } | ||
101 | s = 8 - (b - 26); | ||
102 | if (j >= 0) | ||
103 | a[j] = 0; | ||
104 | if (s != 0) | ||
105 | j++; | ||
106 | } | 72 | } |
107 | } | 73 | } |
108 | 74 | ||
109 | /* Read big endian unsigned byte aray into r. | 75 | /* Read big endian unsigned byte array into r. |
110 | * | 76 | * |
111 | * r A single precision integer. | 77 | * r A single precision integer. |
112 | * a Byte array. | 78 | * a Byte array. |
113 | * n Number of bytes in array to read. | 79 | * n Number of bytes in array to read. |
114 | */ | 80 | */ |
115 | static void sp_256_from_bin(sp_digit* r, int max, const uint8_t* a, int n) | 81 | static void sp_256_from_bin_8(sp_digit* r, const uint8_t* a) |
116 | { | 82 | { |
117 | int i, j = 0, s = 0; | 83 | int i; |
118 | 84 | ||
119 | r[0] = 0; | 85 | r += 8; |
120 | for (i = n-1; i >= 0; i--) { | 86 | for (i = 0; i < 8; i++) { |
121 | r[j] |= ((sp_digit)a[i]) << s; | 87 | sp_digit v; |
122 | if (s >= 18) { | 88 | move_from_unaligned32(v, a); |
123 | r[j] &= 0x3ffffff; | 89 | *--r = SWAP_BE32(v); |
124 | s = 26 - s; | 90 | a += 4; |
125 | if (j + 1 >= max) | ||
126 | break; | ||
127 | r[++j] = a[i] >> s; | ||
128 | s = 8 - s; | ||
129 | } | ||
130 | else | ||
131 | s += 8; | ||
132 | } | 91 | } |
92 | } | ||
133 | 93 | ||
134 | for (j++; j < max; j++) | 94 | #if SP_DEBUG |
135 | r[j] = 0; | 95 | static void dump_256(const char *fmt, const sp_digit* r) |
96 | { | ||
97 | uint8_t b32[32]; | ||
98 | sp_256_to_bin_8(r, b32); | ||
99 | dump_hex(fmt, b32, 32); | ||
100 | } | ||
101 | static void dump_512(const char *fmt, const sp_digit* r) | ||
102 | { | ||
103 | uint8_t b64[64]; | ||
104 | sp_256_to_bin_8(r, b64 + 32); | ||
105 | sp_256_to_bin_8(r+8, b64); | ||
106 | dump_hex(fmt, b64, 64); | ||
136 | } | 107 | } |
108 | #else | ||
109 | # define dump_256(...) ((void)0) | ||
110 | # define dump_512(...) ((void)0) | ||
111 | #endif | ||
137 | 112 | ||
138 | /* Convert a point of big-endian 32-byte x,y pair to type sp_point. */ | 113 | /* Convert a point of big-endian 32-byte x,y pair to type sp_point. */ |
139 | static void sp_256_point_from_bin2x32(sp_point* p, const uint8_t *bin2x32) | 114 | static void sp_256_point_from_bin2x32(sp_point* p, const uint8_t *bin2x32) |
140 | { | 115 | { |
141 | memset(p, 0, sizeof(*p)); | 116 | memset(p, 0, sizeof(*p)); |
142 | /*p->infinity = 0;*/ | 117 | /*p->infinity = 0;*/ |
143 | sp_256_from_bin(p->x, 2 * 10, bin2x32, 32); | 118 | sp_256_from_bin_8(p->x, bin2x32); |
144 | sp_256_from_bin(p->y, 2 * 10, bin2x32 + 32, 32); | 119 | sp_256_from_bin_8(p->y, bin2x32 + 32); |
145 | //static const uint8_t one[1] = { 1 }; | 120 | p->z[0] = 1; /* p->z = 1 */ |
146 | //sp_256_from_bin(p->z, 2 * 10, one, 1); | ||
147 | p->z[0] = 1; | ||
148 | } | 121 | } |
149 | 122 | ||
150 | /* Compare a with b. | 123 | /* Compare a with b. |
@@ -152,201 +125,650 @@ static void sp_256_point_from_bin2x32(sp_point* p, const uint8_t *bin2x32) | |||
152 | * return -ve, 0 or +ve if a is less than, equal to or greater than b | 125 | * return -ve, 0 or +ve if a is less than, equal to or greater than b |
153 | * respectively. | 126 | * respectively. |
154 | */ | 127 | */ |
155 | static sp_digit sp_256_cmp_10(const sp_digit* a, const sp_digit* b) | 128 | static signed_sp_digit sp_256_cmp_8(const sp_digit* a, const sp_digit* b) |
156 | { | 129 | { |
157 | sp_digit r; | ||
158 | int i; | 130 | int i; |
159 | for (i = 9; i >= 0; i--) { | 131 | for (i = 7; i >= 0; i--) { |
160 | r = a[i] - b[i]; | 132 | /* signed_sp_digit r = a[i] - b[i]; |
161 | if (r != 0) | 133 | * if (r != 0) |
162 | break; | 134 | * return r; |
135 | * does not work: think about a[i]=0, b[i]=0xffffffff | ||
136 | */ | ||
137 | if (a[i] == b[i]) | ||
138 | continue; | ||
139 | return (a[i] > b[i]) * 2 - 1; | ||
163 | } | 140 | } |
164 | return r; | 141 | return 0; |
165 | } | 142 | } |
166 | 143 | ||
167 | /* Compare two numbers to determine if they are equal. | 144 | /* Compare two numbers to determine if they are equal. |
168 | * | 145 | * |
169 | * return 1 when equal and 0 otherwise. | 146 | * return 1 when equal and 0 otherwise. |
170 | */ | 147 | */ |
171 | static int sp_256_cmp_equal_10(const sp_digit* a, const sp_digit* b) | 148 | static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) |
172 | { | 149 | { |
173 | return sp_256_cmp_10(a, b) == 0; | 150 | return sp_256_cmp_8(a, b) == 0; |
174 | } | 151 | } |
175 | 152 | ||
176 | /* Normalize the values in each word to 26 bits. */ | 153 | /* Add b to a into r. (r = a + b). Return !0 on overflow */ |
177 | static void sp_256_norm_10(sp_digit* a) | 154 | static int sp_256_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b) |
178 | { | 155 | { |
156 | #if ALLOW_ASM && defined(__GNUC__) && defined(__i386__) | ||
157 | sp_digit reg; | ||
158 | asm volatile ( | ||
159 | "\n movl (%0), %3" | ||
160 | "\n addl (%1), %3" | ||
161 | "\n movl %3, (%2)" | ||
162 | "\n" | ||
163 | "\n movl 1*4(%0), %3" | ||
164 | "\n adcl 1*4(%1), %3" | ||
165 | "\n movl %3, 1*4(%2)" | ||
166 | "\n" | ||
167 | "\n movl 2*4(%0), %3" | ||
168 | "\n adcl 2*4(%1), %3" | ||
169 | "\n movl %3, 2*4(%2)" | ||
170 | "\n" | ||
171 | "\n movl 3*4(%0), %3" | ||
172 | "\n adcl 3*4(%1), %3" | ||
173 | "\n movl %3, 3*4(%2)" | ||
174 | "\n" | ||
175 | "\n movl 4*4(%0), %3" | ||
176 | "\n adcl 4*4(%1), %3" | ||
177 | "\n movl %3, 4*4(%2)" | ||
178 | "\n" | ||
179 | "\n movl 5*4(%0), %3" | ||
180 | "\n adcl 5*4(%1), %3" | ||
181 | "\n movl %3, 5*4(%2)" | ||
182 | "\n" | ||
183 | "\n movl 6*4(%0), %3" | ||
184 | "\n adcl 6*4(%1), %3" | ||
185 | "\n movl %3, 6*4(%2)" | ||
186 | "\n" | ||
187 | "\n movl 7*4(%0), %3" | ||
188 | "\n adcl 7*4(%1), %3" | ||
189 | "\n movl %3, 7*4(%2)" | ||
190 | "\n" | ||
191 | "\n sbbl %3, %3" | ||
192 | "\n" | ||
193 | : "=r" (a), "=r" (b), "=r" (r), "=r" (reg) | ||
194 | : "0" (a), "1" (b), "2" (r) | ||
195 | : "memory" | ||
196 | ); | ||
197 | return reg; | ||
198 | #elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__) | ||
199 | /* x86_64 has no alignment restrictions, and is little-endian, | ||
200 | * so 64-bit and 32-bit representations are identical */ | ||
201 | uint64_t reg; | ||
202 | asm volatile ( | ||
203 | "\n movq (%0), %3" | ||
204 | "\n addq (%1), %3" | ||
205 | "\n movq %3, (%2)" | ||
206 | "\n" | ||
207 | "\n movq 1*8(%0), %3" | ||
208 | "\n adcq 1*8(%1), %3" | ||
209 | "\n movq %3, 1*8(%2)" | ||
210 | "\n" | ||
211 | "\n movq 2*8(%0), %3" | ||
212 | "\n adcq 2*8(%1), %3" | ||
213 | "\n movq %3, 2*8(%2)" | ||
214 | "\n" | ||
215 | "\n movq 3*8(%0), %3" | ||
216 | "\n adcq 3*8(%1), %3" | ||
217 | "\n movq %3, 3*8(%2)" | ||
218 | "\n" | ||
219 | "\n sbbq %3, %3" | ||
220 | "\n" | ||
221 | : "=r" (a), "=r" (b), "=r" (r), "=r" (reg) | ||
222 | : "0" (a), "1" (b), "2" (r) | ||
223 | : "memory" | ||
224 | ); | ||
225 | return reg; | ||
226 | #else | ||
179 | int i; | 227 | int i; |
180 | for (i = 0; i < 9; i++) { | 228 | sp_digit carry; |
181 | a[i+1] += a[i] >> 26; | 229 | |
182 | a[i] &= 0x3ffffff; | 230 | carry = 0; |
231 | for (i = 0; i < 8; i++) { | ||
232 | sp_digit w, v; | ||
233 | w = b[i] + carry; | ||
234 | v = a[i]; | ||
235 | if (w != 0) { | ||
236 | v = a[i] + w; | ||
237 | carry = (v < a[i]); | ||
238 | /* hope compiler detects above as "carry flag set" */ | ||
239 | } | ||
240 | /* else: b + carry == 0, two cases: | ||
241 | * b:ffffffff, carry:1 | ||
242 | * b:00000000, carry:0 | ||
243 | * in either case, r[i] = a[i] and carry remains unchanged | ||
244 | */ | ||
245 | r[i] = v; | ||
183 | } | 246 | } |
247 | return carry; | ||
248 | #endif | ||
184 | } | 249 | } |
185 | 250 | ||
186 | /* Add b to a into r. (r = a + b) */ | 251 | /* Sub b from a into r. (r = a - b). Return !0 on underflow */ |
187 | static void sp_256_add_10(sp_digit* r, const sp_digit* a, const sp_digit* b) | 252 | static int sp_256_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b) |
188 | { | 253 | { |
254 | #if ALLOW_ASM && defined(__GNUC__) && defined(__i386__) | ||
255 | sp_digit reg; | ||
256 | asm volatile ( | ||
257 | "\n movl (%0), %3" | ||
258 | "\n subl (%1), %3" | ||
259 | "\n movl %3, (%2)" | ||
260 | "\n" | ||
261 | "\n movl 1*4(%0), %3" | ||
262 | "\n sbbl 1*4(%1), %3" | ||
263 | "\n movl %3, 1*4(%2)" | ||
264 | "\n" | ||
265 | "\n movl 2*4(%0), %3" | ||
266 | "\n sbbl 2*4(%1), %3" | ||
267 | "\n movl %3, 2*4(%2)" | ||
268 | "\n" | ||
269 | "\n movl 3*4(%0), %3" | ||
270 | "\n sbbl 3*4(%1), %3" | ||
271 | "\n movl %3, 3*4(%2)" | ||
272 | "\n" | ||
273 | "\n movl 4*4(%0), %3" | ||
274 | "\n sbbl 4*4(%1), %3" | ||
275 | "\n movl %3, 4*4(%2)" | ||
276 | "\n" | ||
277 | "\n movl 5*4(%0), %3" | ||
278 | "\n sbbl 5*4(%1), %3" | ||
279 | "\n movl %3, 5*4(%2)" | ||
280 | "\n" | ||
281 | "\n movl 6*4(%0), %3" | ||
282 | "\n sbbl 6*4(%1), %3" | ||
283 | "\n movl %3, 6*4(%2)" | ||
284 | "\n" | ||
285 | "\n movl 7*4(%0), %3" | ||
286 | "\n sbbl 7*4(%1), %3" | ||
287 | "\n movl %3, 7*4(%2)" | ||
288 | "\n" | ||
289 | "\n sbbl %3, %3" | ||
290 | "\n" | ||
291 | : "=r" (a), "=r" (b), "=r" (r), "=r" (reg) | ||
292 | : "0" (a), "1" (b), "2" (r) | ||
293 | : "memory" | ||
294 | ); | ||
295 | return reg; | ||
296 | #elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__) | ||
297 | /* x86_64 has no alignment restrictions, and is little-endian, | ||
298 | * so 64-bit and 32-bit representations are identical */ | ||
299 | uint64_t reg; | ||
300 | asm volatile ( | ||
301 | "\n movq (%0), %3" | ||
302 | "\n subq (%1), %3" | ||
303 | "\n movq %3, (%2)" | ||
304 | "\n" | ||
305 | "\n movq 1*8(%0), %3" | ||
306 | "\n sbbq 1*8(%1), %3" | ||
307 | "\n movq %3, 1*8(%2)" | ||
308 | "\n" | ||
309 | "\n movq 2*8(%0), %3" | ||
310 | "\n sbbq 2*8(%1), %3" | ||
311 | "\n movq %3, 2*8(%2)" | ||
312 | "\n" | ||
313 | "\n movq 3*8(%0), %3" | ||
314 | "\n sbbq 3*8(%1), %3" | ||
315 | "\n movq %3, 3*8(%2)" | ||
316 | "\n" | ||
317 | "\n sbbq %3, %3" | ||
318 | "\n" | ||
319 | : "=r" (a), "=r" (b), "=r" (r), "=r" (reg) | ||
320 | : "0" (a), "1" (b), "2" (r) | ||
321 | : "memory" | ||
322 | ); | ||
323 | return reg; | ||
324 | #else | ||
189 | int i; | 325 | int i; |
190 | for (i = 0; i < 10; i++) | 326 | sp_digit borrow; |
191 | r[i] = a[i] + b[i]; | 327 | |
328 | borrow = 0; | ||
329 | for (i = 0; i < 8; i++) { | ||
330 | sp_digit w, v; | ||
331 | w = b[i] + borrow; | ||
332 | v = a[i]; | ||
333 | if (w != 0) { | ||
334 | v = a[i] - w; | ||
335 | borrow = (v > a[i]); | ||
336 | /* hope compiler detects above as "carry flag set" */ | ||
337 | } | ||
338 | /* else: b + borrow == 0, two cases: | ||
339 | * b:ffffffff, borrow:1 | ||
340 | * b:00000000, borrow:0 | ||
341 | * in either case, r[i] = a[i] and borrow remains unchanged | ||
342 | */ | ||
343 | r[i] = v; | ||
344 | } | ||
345 | return borrow; | ||
346 | #endif | ||
192 | } | 347 | } |
193 | 348 | ||
194 | /* Sub b from a into r. (r = a - b) */ | 349 | /* Sub p256_mod from r. (r = r - p256_mod). */ |
195 | static void sp_256_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b) | 350 | #if ALLOW_ASM && defined(__GNUC__) && defined(__i386__) |
351 | static void sp_256_sub_8_p256_mod(sp_digit* r) | ||
196 | { | 352 | { |
197 | int i; | 353 | //p256_mod[7..0] = ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff |
198 | for (i = 0; i < 10; i++) | 354 | asm volatile ( |
199 | r[i] = a[i] - b[i]; | 355 | "\n subl $0xffffffff, (%0)" |
356 | "\n sbbl $0xffffffff, 1*4(%0)" | ||
357 | "\n sbbl $0xffffffff, 2*4(%0)" | ||
358 | "\n sbbl $0, 3*4(%0)" | ||
359 | "\n sbbl $0, 4*4(%0)" | ||
360 | "\n sbbl $0, 5*4(%0)" | ||
361 | "\n sbbl $1, 6*4(%0)" | ||
362 | "\n sbbl $0xffffffff, 7*4(%0)" | ||
363 | "\n" | ||
364 | : "=r" (r) | ||
365 | : "0" (r) | ||
366 | : "memory" | ||
367 | ); | ||
200 | } | 368 | } |
201 | 369 | #elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__) | |
202 | /* Shift number left one bit. Bottom bit is lost. */ | 370 | static void sp_256_sub_8_p256_mod(sp_digit* r) |
203 | static void sp_256_rshift1_10(sp_digit* r, sp_digit* a) | ||
204 | { | 371 | { |
205 | int i; | 372 | uint64_t reg; |
206 | for (i = 0; i < 9; i++) | 373 | uint64_t ooff; |
207 | r[i] = ((a[i] >> 1) | (a[i + 1] << 25)) & 0x3ffffff; | 374 | //p256_mod[3..0] = ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff |
208 | r[9] = a[9] >> 1; | 375 | asm volatile ( |
376 | "\n addq $1, (%0)" // adding 1 is the same as subtracting ffffffffffffffff | ||
377 | "\n cmc" // only carry bit needs inverting | ||
378 | "\n" | ||
379 | "\n sbbq %1, 1*8(%0)" // %1 holds 00000000ffffffff | ||
380 | "\n" | ||
381 | "\n sbbq $0, 2*8(%0)" | ||
382 | "\n" | ||
383 | "\n movq 3*8(%0), %2" | ||
384 | "\n sbbq $0, %2" // adding 00000000ffffffff (in %1) | ||
385 | "\n addq %1, %2" // is the same as subtracting ffffffff00000001 | ||
386 | "\n movq %2, 3*8(%0)" | ||
387 | "\n" | ||
388 | : "=r" (r), "=r" (ooff), "=r" (reg) | ||
389 | : "0" (r), "1" (0x00000000ffffffff) | ||
390 | : "memory" | ||
391 | ); | ||
209 | } | 392 | } |
210 | 393 | #else | |
211 | /* Mul a by scalar b and add into r. (r += a * b) */ | 394 | static void sp_256_sub_8_p256_mod(sp_digit* r) |
212 | static void sp_256_mul_add_10(sp_digit* r, const sp_digit* a, sp_digit b) | ||
213 | { | 395 | { |
214 | int64_t tb = b; | 396 | sp_256_sub_8(r, r, p256_mod); |
215 | int64_t t = 0; | ||
216 | int i; | ||
217 | |||
218 | for (i = 0; i < 10; i++) { | ||
219 | t += (tb * a[i]) + r[i]; | ||
220 | r[i] = t & 0x3ffffff; | ||
221 | t >>= 26; | ||
222 | } | ||
223 | r[10] += t; | ||
224 | } | 397 | } |
398 | #endif | ||
225 | 399 | ||
226 | /* Multiply a and b into r. (r = a * b) */ | 400 | /* Multiply a and b into r. (r = a * b) */ |
227 | static void sp_256_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b) | 401 | static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) |
228 | { | 402 | { |
403 | #if ALLOW_ASM && defined(__GNUC__) && defined(__i386__) | ||
404 | sp_digit rr[15]; /* in case r coincides with a or b */ | ||
405 | int k; | ||
406 | uint32_t accl; | ||
407 | uint32_t acch; | ||
408 | |||
409 | acch = accl = 0; | ||
410 | for (k = 0; k < 15; k++) { | ||
411 | int i, j; | ||
412 | uint32_t acc_hi; | ||
413 | i = k - 7; | ||
414 | if (i < 0) | ||
415 | i = 0; | ||
416 | j = k - i; | ||
417 | acc_hi = 0; | ||
418 | do { | ||
419 | //////////////////////// | ||
420 | // uint64_t m = ((uint64_t)a[i]) * b[j]; | ||
421 | // acc_hi:acch:accl += m; | ||
422 | asm volatile ( | ||
423 | // a[i] is already loaded in %%eax | ||
424 | "\n mull %7" | ||
425 | "\n addl %%eax, %0" | ||
426 | "\n adcl %%edx, %1" | ||
427 | "\n adcl $0, %2" | ||
428 | : "=rm" (accl), "=rm" (acch), "=rm" (acc_hi) | ||
429 | : "0" (accl), "1" (acch), "2" (acc_hi), "a" (a[i]), "m" (b[j]) | ||
430 | : "cc", "dx" | ||
431 | ); | ||
432 | //////////////////////// | ||
433 | j--; | ||
434 | i++; | ||
435 | } while (i != 8 && i <= k); | ||
436 | rr[k] = accl; | ||
437 | accl = acch; | ||
438 | acch = acc_hi; | ||
439 | } | ||
440 | r[15] = accl; | ||
441 | memcpy(r, rr, sizeof(rr)); | ||
442 | #elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__) | ||
443 | /* x86_64 has no alignment restrictions, and is little-endian, | ||
444 | * so 64-bit and 32-bit representations are identical */ | ||
445 | const uint64_t* aa = (const void*)a; | ||
446 | const uint64_t* bb = (const void*)b; | ||
447 | uint64_t rr[8]; | ||
448 | int k; | ||
449 | uint64_t accl; | ||
450 | uint64_t acch; | ||
451 | |||
452 | acch = accl = 0; | ||
453 | for (k = 0; k < 7; k++) { | ||
454 | int i, j; | ||
455 | uint64_t acc_hi; | ||
456 | i = k - 3; | ||
457 | if (i < 0) | ||
458 | i = 0; | ||
459 | j = k - i; | ||
460 | acc_hi = 0; | ||
461 | do { | ||
462 | //////////////////////// | ||
463 | // uint128_t m = ((uint128_t)a[i]) * b[j]; | ||
464 | // acc_hi:acch:accl += m; | ||
465 | asm volatile ( | ||
466 | // aa[i] is already loaded in %%rax | ||
467 | "\n mulq %7" | ||
468 | "\n addq %%rax, %0" | ||
469 | "\n adcq %%rdx, %1" | ||
470 | "\n adcq $0, %2" | ||
471 | : "=rm" (accl), "=rm" (acch), "=rm" (acc_hi) | ||
472 | : "0" (accl), "1" (acch), "2" (acc_hi), "a" (aa[i]), "m" (bb[j]) | ||
473 | : "cc", "dx" | ||
474 | ); | ||
475 | //////////////////////// | ||
476 | j--; | ||
477 | i++; | ||
478 | } while (i != 4 && i <= k); | ||
479 | rr[k] = accl; | ||
480 | accl = acch; | ||
481 | acch = acc_hi; | ||
482 | } | ||
483 | rr[7] = accl; | ||
484 | memcpy(r, rr, sizeof(rr)); | ||
485 | #elif 0 | ||
486 | //TODO: arm assembly (untested) | ||
487 | sp_digit tmp[16]; | ||
488 | |||
489 | asm volatile ( | ||
490 | "\n mov r5, #0" | ||
491 | "\n mov r6, #0" | ||
492 | "\n mov r7, #0" | ||
493 | "\n mov r8, #0" | ||
494 | "\n 1:" | ||
495 | "\n subs r3, r5, #28" | ||
496 | "\n movcc r3, #0" | ||
497 | "\n sub r4, r5, r3" | ||
498 | "\n 2:" | ||
499 | "\n ldr r14, [%[a], r3]" | ||
500 | "\n ldr r12, [%[b], r4]" | ||
501 | "\n umull r9, r10, r14, r12" | ||
502 | "\n adds r6, r6, r9" | ||
503 | "\n adcs r7, r7, r10" | ||
504 | "\n adc r8, r8, #0" | ||
505 | "\n add r3, r3, #4" | ||
506 | "\n sub r4, r4, #4" | ||
507 | "\n cmp r3, #32" | ||
508 | "\n beq 3f" | ||
509 | "\n cmp r3, r5" | ||
510 | "\n ble 2b" | ||
511 | "\n 3:" | ||
512 | "\n str r6, [%[r], r5]" | ||
513 | "\n mov r6, r7" | ||
514 | "\n mov r7, r8" | ||
515 | "\n mov r8, #0" | ||
516 | "\n add r5, r5, #4" | ||
517 | "\n cmp r5, #56" | ||
518 | "\n ble 1b" | ||
519 | "\n str r6, [%[r], r5]" | ||
520 | : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) | ||
521 | : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" | ||
522 | ); | ||
523 | memcpy(r, tmp, sizeof(tmp)); | ||
524 | #else | ||
525 | sp_digit rr[15]; /* in case r coincides with a or b */ | ||
229 | int i, j, k; | 526 | int i, j, k; |
230 | int64_t c; | 527 | uint64_t acc; |
231 | 528 | ||
232 | c = ((int64_t)a[9]) * b[9]; | 529 | acc = 0; |
233 | r[19] = (sp_digit)(c >> 26); | 530 | for (k = 0; k < 15; k++) { |
234 | c = (c & 0x3ffffff) << 26; | 531 | uint32_t acc_hi; |
235 | for (k = 17; k >= 0; k--) { | 532 | i = k - 7; |
236 | for (i = 9; i >= 0; i--) { | 533 | if (i < 0) |
237 | j = k - i; | 534 | i = 0; |
238 | if (j >= 10) | 535 | j = k - i; |
239 | break; | 536 | acc_hi = 0; |
240 | if (j < 0) | 537 | do { |
241 | continue; | 538 | uint64_t m = ((uint64_t)a[i]) * b[j]; |
242 | c += ((int64_t)a[i]) * b[j]; | 539 | acc += m; |
243 | } | 540 | if (acc < m) |
244 | r[k + 2] += c >> 52; | 541 | acc_hi++; |
245 | r[k + 1] = (c >> 26) & 0x3ffffff; | 542 | j--; |
246 | c = (c & 0x3ffffff) << 26; | 543 | i++; |
544 | } while (i != 8 && i <= k); | ||
545 | rr[k] = acc; | ||
546 | acc = (acc >> 32) | ((uint64_t)acc_hi << 32); | ||
247 | } | 547 | } |
248 | r[0] = (sp_digit)(c >> 26); | 548 | r[15] = acc; |
549 | memcpy(r, rr, sizeof(rr)); | ||
550 | #endif | ||
249 | } | 551 | } |
250 | 552 | ||
251 | /* Square a and put result in r. (r = a * a) */ | 553 | /* Shift number right one bit. Bottom bit is lost. */ |
252 | static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) | 554 | static void sp_256_rshift1_8(sp_digit* r, sp_digit* a, sp_digit carry) |
253 | { | 555 | { |
254 | int i, j, k; | 556 | int i; |
255 | int64_t c; | 557 | |
256 | 558 | carry = (!!carry << 31); | |
257 | c = ((int64_t)a[9]) * a[9]; | 559 | for (i = 7; i >= 0; i--) { |
258 | r[19] = (sp_digit)(c >> 26); | 560 | sp_digit c = a[i] << 31; |
259 | c = (c & 0x3ffffff) << 26; | 561 | r[i] = (a[i] >> 1) | carry; |
260 | for (k = 17; k >= 0; k--) { | 562 | carry = c; |
261 | for (i = 9; i >= 0; i--) { | ||
262 | j = k - i; | ||
263 | if (j >= 10 || i <= j) | ||
264 | break; | ||
265 | if (j < 0) | ||
266 | continue; | ||
267 | c += ((int64_t)a[i]) * a[j] * 2; | ||
268 | } | ||
269 | if (i == j) | ||
270 | c += ((int64_t)a[i]) * a[i]; | ||
271 | r[k + 2] += c >> 52; | ||
272 | r[k + 1] = (c >> 26) & 0x3ffffff; | ||
273 | c = (c & 0x3ffffff) << 26; | ||
274 | } | 563 | } |
275 | r[0] = (sp_digit)(c >> 26); | ||
276 | } | 564 | } |
277 | 565 | ||
278 | /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) */ | 566 | /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) */ |
279 | static void sp_256_div2_10(sp_digit* r, const sp_digit* a, const sp_digit* m) | 567 | static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_digit* m) |
280 | { | 568 | { |
569 | int carry = 0; | ||
281 | if (a[0] & 1) | 570 | if (a[0] & 1) |
282 | sp_256_add_10(r, a, m); | 571 | carry = sp_256_add_8(r, a, m); |
283 | sp_256_norm_10(r); | 572 | sp_256_norm_8(r); |
284 | sp_256_rshift1_10(r, r); | 573 | sp_256_rshift1_8(r, r, carry); |
285 | } | 574 | } |
286 | 575 | ||
287 | /* Add two Montgomery form numbers (r = a + b % m) */ | 576 | /* Add two Montgomery form numbers (r = a + b % m) */ |
288 | static void sp_256_mont_add_10(sp_digit* r, const sp_digit* a, const sp_digit* b, | 577 | static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b |
289 | const sp_digit* m) | 578 | /*, const sp_digit* m*/) |
290 | { | 579 | { |
291 | sp_256_add_10(r, a, b); | 580 | // const sp_digit* m = p256_mod; |
292 | sp_256_norm_10(r); | 581 | |
293 | if ((r[9] >> 22) > 0) | 582 | int carry = sp_256_add_8(r, a, b); |
294 | sp_256_sub_10(r, r, m); | 583 | sp_256_norm_8(r); |
295 | sp_256_norm_10(r); | 584 | if (carry) { |
585 | sp_256_sub_8_p256_mod(r); | ||
586 | sp_256_norm_8(r); | ||
587 | } | ||
296 | } | 588 | } |
297 | 589 | ||
298 | /* Subtract two Montgomery form numbers (r = a - b % m) */ | 590 | /* Subtract two Montgomery form numbers (r = a - b % m) */ |
299 | static void sp_256_mont_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b, | 591 | static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b |
300 | const sp_digit* m) | 592 | /*, const sp_digit* m*/) |
301 | { | 593 | { |
302 | sp_256_sub_10(r, a, b); | 594 | const sp_digit* m = p256_mod; |
303 | if (r[9] >> 22) | 595 | |
304 | sp_256_add_10(r, r, m); | 596 | int borrow; |
305 | sp_256_norm_10(r); | 597 | borrow = sp_256_sub_8(r, a, b); |
598 | sp_256_norm_8(r); | ||
599 | if (borrow) { | ||
600 | sp_256_add_8(r, r, m); | ||
601 | sp_256_norm_8(r); | ||
602 | } | ||
306 | } | 603 | } |
307 | 604 | ||
308 | /* Double a Montgomery form number (r = a + a % m) */ | 605 | /* Double a Montgomery form number (r = a + a % m) */ |
309 | static void sp_256_mont_dbl_10(sp_digit* r, const sp_digit* a, const sp_digit* m) | 606 | static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a /*, const sp_digit* m*/) |
310 | { | 607 | { |
311 | sp_256_add_10(r, a, a); | 608 | // const sp_digit* m = p256_mod; |
312 | sp_256_norm_10(r); | 609 | |
313 | if ((r[9] >> 22) > 0) | 610 | int carry = sp_256_add_8(r, a, a); |
314 | sp_256_sub_10(r, r, m); | 611 | sp_256_norm_8(r); |
315 | sp_256_norm_10(r); | 612 | if (carry) |
613 | sp_256_sub_8_p256_mod(r); | ||
614 | sp_256_norm_8(r); | ||
316 | } | 615 | } |
317 | 616 | ||
318 | /* Triple a Montgomery form number (r = a + a + a % m) */ | 617 | /* Triple a Montgomery form number (r = a + a + a % m) */ |
319 | static void sp_256_mont_tpl_10(sp_digit* r, const sp_digit* a, const sp_digit* m) | 618 | static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a /*, const sp_digit* m*/) |
320 | { | 619 | { |
321 | sp_256_add_10(r, a, a); | 620 | // const sp_digit* m = p256_mod; |
322 | sp_256_norm_10(r); | 621 | |
323 | if ((r[9] >> 22) > 0) | 622 | int carry = sp_256_add_8(r, a, a); |
324 | sp_256_sub_10(r, r, m); | 623 | sp_256_norm_8(r); |
325 | sp_256_norm_10(r); | 624 | if (carry) { |
326 | sp_256_add_10(r, r, a); | 625 | sp_256_sub_8_p256_mod(r); |
327 | sp_256_norm_10(r); | 626 | sp_256_norm_8(r); |
328 | if ((r[9] >> 22) > 0) | 627 | } |
329 | sp_256_sub_10(r, r, m); | 628 | carry = sp_256_add_8(r, r, a); |
330 | sp_256_norm_10(r); | 629 | sp_256_norm_8(r); |
630 | if (carry) { | ||
631 | sp_256_sub_8_p256_mod(r); | ||
632 | sp_256_norm_8(r); | ||
633 | } | ||
331 | } | 634 | } |
332 | 635 | ||
333 | /* Shift the result in the high 256 bits down to the bottom. */ | 636 | /* Shift the result in the high 256 bits down to the bottom. */ |
334 | static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a) | 637 | static void sp_256_mont_shift_8(sp_digit* r, const sp_digit* a) |
335 | { | 638 | { |
336 | int i; | 639 | int i; |
337 | sp_digit n, s; | 640 | |
338 | 641 | for (i = 0; i < 8; i++) { | |
339 | s = a[10]; | 642 | r[i] = a[i+8]; |
340 | n = a[9] >> 22; | 643 | r[i+8] = 0; |
341 | for (i = 0; i < 9; i++) { | ||
342 | n += (s & 0x3ffffff) << 4; | ||
343 | r[i] = n & 0x3ffffff; | ||
344 | n >>= 26; | ||
345 | s = a[11 + i] + (s >> 26); | ||
346 | } | 644 | } |
347 | n += s << 4; | 645 | } |
348 | r[9] = n; | 646 | |
349 | memset(&r[10], 0, sizeof(*r) * 10); | 647 | /* Mul a by scalar b and add into r. (r += a * b) */ |
648 | static int sp_256_mul_add_8(sp_digit* r /*, const sp_digit* a, sp_digit b*/) | ||
649 | { | ||
650 | // const sp_digit* a = p256_mod; | ||
651 | //a[7..0] = ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff | ||
652 | sp_digit b = r[0]; | ||
653 | |||
654 | uint64_t t; | ||
655 | |||
656 | // t = 0; | ||
657 | // for (i = 0; i < 8; i++) { | ||
658 | // uint32_t t_hi; | ||
659 | // uint64_t m = ((uint64_t)b * a[i]) + r[i]; | ||
660 | // t += m; | ||
661 | // t_hi = (t < m); | ||
662 | // r[i] = (sp_digit)t; | ||
663 | // t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
664 | // } | ||
665 | // r[8] += (sp_digit)t; | ||
666 | |||
667 | // Unroll, then optimize the above loop: | ||
668 | //uint32_t t_hi; | ||
669 | uint64_t m; | ||
670 | uint32_t t32; | ||
671 | |||
672 | //m = ((uint64_t)b * a[0]) + r[0]; | ||
673 | // Since b is r[0] and a[0] is ffffffff, the above optimizes to: | ||
674 | // m = r[0] * ffffffff + r[0] = (r[0] * 100000000 - r[0]) + r[0] = r[0] << 32; | ||
675 | //t += m; | ||
676 | // t = r[0] << 32 = b << 32; | ||
677 | //t_hi = (t < m); | ||
678 | // t_hi = 0; | ||
679 | //r[0] = (sp_digit)t; | ||
680 | r[0] = 0; | ||
681 | //t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
682 | // t = b; | ||
683 | |||
684 | //m = ((uint64_t)b * a[1]) + r[1]; | ||
685 | // Since a[1] is ffffffff, the above optimizes to: | ||
686 | // m = b * ffffffff + r[1] = (b * 100000000 - b) + r[1] = (b << 32) - b + r[1]; | ||
687 | //t += m; | ||
688 | // t = b + (b << 32) - b + r[1] = (b << 32) + r[1]; | ||
689 | //t_hi = (t < m); | ||
690 | // t_hi = 0; | ||
691 | //r[1] = (sp_digit)t; | ||
692 | // r[1] = r[1]; | ||
693 | //t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
694 | // t = b; | ||
695 | |||
696 | //m = ((uint64_t)b * a[2]) + r[2]; | ||
697 | // Since a[2] is ffffffff, the above optimizes to: | ||
698 | // m = b * ffffffff + r[2] = (b * 100000000 - b) + r[2] = (b << 32) - b + r[2]; | ||
699 | //t += m; | ||
700 | // t = b + (b << 32) - b + r[2] = (b << 32) + r[2] | ||
701 | //t_hi = (t < m); | ||
702 | // t_hi = 0; | ||
703 | //r[2] = (sp_digit)t; | ||
704 | // r[2] = r[2]; | ||
705 | //t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
706 | // t = b; | ||
707 | |||
708 | //m = ((uint64_t)b * a[3]) + r[3]; | ||
709 | // Since a[3] is 00000000, the above optimizes to: | ||
710 | // m = b * 0 + r[3] = r[3]; | ||
711 | //t += m; | ||
712 | // t = b + r[3]; | ||
713 | //t_hi = (t < m); | ||
714 | // t_hi = 0; | ||
715 | //r[3] = (sp_digit)t; | ||
716 | r[3] = r[3] + b; | ||
717 | //t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
718 | t32 = (r[3] < b); // 0 or 1 | ||
719 | |||
720 | //m = ((uint64_t)b * a[4]) + r[4]; | ||
721 | // Since a[4] is 00000000, the above optimizes to: | ||
722 | // m = b * 0 + r[4] = r[4]; | ||
723 | //t += m; | ||
724 | // t = t32 + r[4]; | ||
725 | //t_hi = (t < m); | ||
726 | // t_hi = 0; | ||
727 | //r[4] = (sp_digit)t; | ||
728 | //t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
729 | if (t32 != 0) { | ||
730 | r[4]++; | ||
731 | t32 = (r[4] == 0); // 0 or 1 | ||
732 | |||
733 | //m = ((uint64_t)b * a[5]) + r[5]; | ||
734 | // Since a[5] is 00000000, the above optimizes to: | ||
735 | // m = b * 0 + r[5] = r[5]; | ||
736 | //t += m; | ||
737 | // t = t32 + r[5]; (t32 is 0 or 1) | ||
738 | //t_hi = (t < m); | ||
739 | // t_hi = 0; | ||
740 | //r[5] = (sp_digit)t; | ||
741 | //t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
742 | if (t32 != 0) { | ||
743 | r[5]++; | ||
744 | t32 = (r[5] == 0); // 0 or 1 | ||
745 | } | ||
746 | } | ||
747 | |||
748 | //m = ((uint64_t)b * a[6]) + r[6]; | ||
749 | // Since a[6] is 00000001, the above optimizes to: | ||
750 | // m = (uint64_t)b + r[6]; // 33 bits at most | ||
751 | //t += m; | ||
752 | t = t32 + (uint64_t)b + r[6]; | ||
753 | //t_hi = (t < m); | ||
754 | // t_hi = 0; | ||
755 | r[6] = (sp_digit)t; | ||
756 | //t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
757 | t = (t >> 32); | ||
758 | |||
759 | //m = ((uint64_t)b * a[7]) + r[7]; | ||
760 | // Since a[7] is ffffffff, the above optimizes to: | ||
761 | // m = b * ffffffff + r[7] = (b * 100000000 - b) + r[7] | ||
762 | m = ((uint64_t)b << 32) - b + r[7]; | ||
763 | t += m; | ||
764 | //t_hi = (t < m); | ||
765 | // t_hi in fact is always 0 here (256bit * 32bit can't have more than 32 bits of overflow) | ||
766 | r[7] = (sp_digit)t; | ||
767 | //t = (t >> 32) | ((uint64_t)t_hi << 32); | ||
768 | t = (t >> 32); | ||
769 | |||
770 | r[8] += (sp_digit)t; | ||
771 | return (r[8] < (sp_digit)t); /* 1 if addition overflowed */ | ||
350 | } | 772 | } |
351 | 773 | ||
352 | /* Reduce the number back to 256 bits using Montgomery reduction. | 774 | /* Reduce the number back to 256 bits using Montgomery reduction. |
@@ -355,39 +777,159 @@ static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a) | |||
355 | * m The single precision number representing the modulus. | 777 | * m The single precision number representing the modulus. |
356 | * mp The digit representing the negative inverse of m mod 2^n. | 778 | * mp The digit representing the negative inverse of m mod 2^n. |
357 | */ | 779 | */ |
358 | static void sp_256_mont_reduce_10(sp_digit* a, const sp_digit* m, sp_digit mp) | 780 | static void sp_256_mont_reduce_8(sp_digit* a/*, const sp_digit* m, sp_digit mp*/) |
359 | { | 781 | { |
782 | // const sp_digit* m = p256_mod; | ||
783 | sp_digit mp = p256_mp_mod; | ||
784 | |||
360 | int i; | 785 | int i; |
361 | sp_digit mu; | 786 | // sp_digit mu; |
362 | 787 | ||
363 | if (mp != 1) { | 788 | if (mp != 1) { |
364 | for (i = 0; i < 9; i++) { | 789 | sp_digit word16th = 0; |
365 | mu = (a[i] * mp) & 0x3ffffff; | 790 | for (i = 0; i < 8; i++) { |
366 | sp_256_mul_add_10(a+i, m, mu); | 791 | // mu = (sp_digit)(a[i] * mp); |
367 | a[i+1] += a[i] >> 26; | 792 | if (sp_256_mul_add_8(a+i /*, m, mu*/)) { |
793 | int j = i + 8; | ||
794 | inc_next_word0: | ||
795 | if (++j > 15) { /* a[16] array has no more words? */ | ||
796 | word16th++; | ||
797 | continue; | ||
798 | } | ||
799 | if (++a[j] == 0) /* did this overflow too? */ | ||
800 | goto inc_next_word0; | ||
801 | } | ||
368 | } | 802 | } |
369 | mu = (a[i] * mp) & 0x3fffffl; | 803 | sp_256_mont_shift_8(a, a); |
370 | sp_256_mul_add_10(a+i, m, mu); | 804 | if (word16th != 0) |
371 | a[i+1] += a[i] >> 26; | 805 | sp_256_sub_8_p256_mod(a); |
372 | a[i] &= 0x3ffffff; | 806 | sp_256_norm_8(a); |
373 | } | 807 | } |
374 | else { | 808 | else { /* Same code for explicit mp == 1 (which is always the case for P256) */ |
375 | for (i = 0; i < 9; i++) { | 809 | sp_digit word16th = 0; |
376 | mu = a[i] & 0x3ffffff; | 810 | for (i = 0; i < 8; i++) { |
377 | sp_256_mul_add_10(a+i, p256_mod, mu); | 811 | /*mu = a[i];*/ |
378 | a[i+1] += a[i] >> 26; | 812 | if (sp_256_mul_add_8(a+i /*, m, mu*/)) { |
813 | int j = i + 8; | ||
814 | inc_next_word: | ||
815 | if (++j > 15) { /* a[16] array has no more words? */ | ||
816 | word16th++; | ||
817 | continue; | ||
818 | } | ||
819 | if (++a[j] == 0) /* did this overflow too? */ | ||
820 | goto inc_next_word; | ||
821 | } | ||
379 | } | 822 | } |
380 | mu = a[i] & 0x3fffffl; | 823 | sp_256_mont_shift_8(a, a); |
381 | sp_256_mul_add_10(a+i, p256_mod, mu); | 824 | if (word16th != 0) |
382 | a[i+1] += a[i] >> 26; | 825 | sp_256_sub_8_p256_mod(a); |
383 | a[i] &= 0x3ffffff; | 826 | sp_256_norm_8(a); |
384 | } | 827 | } |
385 | |||
386 | sp_256_mont_shift_10(a, a); | ||
387 | if ((a[9] >> 22) > 0) | ||
388 | sp_256_sub_10(a, a, m); | ||
389 | sp_256_norm_10(a); | ||
390 | } | 828 | } |
829 | #if 0 | ||
830 | //TODO: arm32 asm (also adapt for x86?) | ||
831 | static void sp_256_mont_reduce_8(sp_digit* a, sp_digit* m, sp_digit mp) | ||
832 | { | ||
833 | sp_digit ca = 0; | ||
834 | |||
835 | asm volatile ( | ||
836 | # i = 0 | ||
837 | mov r12, #0 | ||
838 | ldr r10, [%[a], #0] | ||
839 | ldr r14, [%[a], #4] | ||
840 | 1: | ||
841 | # mu = a[i] * mp | ||
842 | mul r8, %[mp], r10 | ||
843 | # a[i+0] += m[0] * mu | ||
844 | ldr r7, [%[m], #0] | ||
845 | ldr r9, [%[a], #0] | ||
846 | umull r6, r7, r8, r7 | ||
847 | adds r10, r10, r6 | ||
848 | adc r5, r7, #0 | ||
849 | # a[i+1] += m[1] * mu | ||
850 | ldr r7, [%[m], #4] | ||
851 | ldr r9, [%[a], #4] | ||
852 | umull r6, r7, r8, r7 | ||
853 | adds r10, r14, r6 | ||
854 | adc r4, r7, #0 | ||
855 | adds r10, r10, r5 | ||
856 | adc r4, r4, #0 | ||
857 | # a[i+2] += m[2] * mu | ||
858 | ldr r7, [%[m], #8] | ||
859 | ldr r14, [%[a], #8] | ||
860 | umull r6, r7, r8, r7 | ||
861 | adds r14, r14, r6 | ||
862 | adc r5, r7, #0 | ||
863 | adds r14, r14, r4 | ||
864 | adc r5, r5, #0 | ||
865 | # a[i+3] += m[3] * mu | ||
866 | ldr r7, [%[m], #12] | ||
867 | ldr r9, [%[a], #12] | ||
868 | umull r6, r7, r8, r7 | ||
869 | adds r9, r9, r6 | ||
870 | adc r4, r7, #0 | ||
871 | adds r9, r9, r5 | ||
872 | str r9, [%[a], #12] | ||
873 | adc r4, r4, #0 | ||
874 | # a[i+4] += m[4] * mu | ||
875 | ldr r7, [%[m], #16] | ||
876 | ldr r9, [%[a], #16] | ||
877 | umull r6, r7, r8, r7 | ||
878 | adds r9, r9, r6 | ||
879 | adc r5, r7, #0 | ||
880 | adds r9, r9, r4 | ||
881 | str r9, [%[a], #16] | ||
882 | adc r5, r5, #0 | ||
883 | # a[i+5] += m[5] * mu | ||
884 | ldr r7, [%[m], #20] | ||
885 | ldr r9, [%[a], #20] | ||
886 | umull r6, r7, r8, r7 | ||
887 | adds r9, r9, r6 | ||
888 | adc r4, r7, #0 | ||
889 | adds r9, r9, r5 | ||
890 | str r9, [%[a], #20] | ||
891 | adc r4, r4, #0 | ||
892 | # a[i+6] += m[6] * mu | ||
893 | ldr r7, [%[m], #24] | ||
894 | ldr r9, [%[a], #24] | ||
895 | umull r6, r7, r8, r7 | ||
896 | adds r9, r9, r6 | ||
897 | adc r5, r7, #0 | ||
898 | adds r9, r9, r4 | ||
899 | str r9, [%[a], #24] | ||
900 | adc r5, r5, #0 | ||
901 | # a[i+7] += m[7] * mu | ||
902 | ldr r7, [%[m], #28] | ||
903 | ldr r9, [%[a], #28] | ||
904 | umull r6, r7, r8, r7 | ||
905 | adds r5, r5, r6 | ||
906 | adcs r7, r7, %[ca] | ||
907 | mov %[ca], #0 | ||
908 | adc %[ca], %[ca], %[ca] | ||
909 | adds r9, r9, r5 | ||
910 | str r9, [%[a], #28] | ||
911 | ldr r9, [%[a], #32] | ||
912 | adcs r9, r9, r7 | ||
913 | str r9, [%[a], #32] | ||
914 | adc %[ca], %[ca], #0 | ||
915 | # i += 1 | ||
916 | add %[a], %[a], #4 | ||
917 | add r12, r12, #4 | ||
918 | cmp r12, #32 | ||
919 | blt 1b | ||
920 | |||
921 | str r10, [%[a], #0] | ||
922 | str r14, [%[a], #4] | ||
923 | : [ca] "+r" (ca), [a] "+r" (a) | ||
924 | : [m] "r" (m), [mp] "r" (mp) | ||
925 | : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" | ||
926 | ); | ||
927 | |||
928 | memcpy(a, a + 8, 32); | ||
929 | if (ca) | ||
930 | a -= m; | ||
931 | } | ||
932 | #endif | ||
391 | 933 | ||
392 | /* Multiply two Montogmery form numbers mod the modulus (prime). | 934 | /* Multiply two Montogmery form numbers mod the modulus (prime). |
393 | * (r = a * b mod m) | 935 | * (r = a * b mod m) |
@@ -398,11 +940,13 @@ static void sp_256_mont_reduce_10(sp_digit* a, const sp_digit* m, sp_digit mp) | |||
398 | * m Modulus (prime). | 940 | * m Modulus (prime). |
399 | * mp Montogmery mulitplier. | 941 | * mp Montogmery mulitplier. |
400 | */ | 942 | */ |
401 | static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b, | 943 | static void sp_256_mont_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b |
402 | const sp_digit* m, sp_digit mp) | 944 | /*, const sp_digit* m, sp_digit mp*/) |
403 | { | 945 | { |
404 | sp_256_mul_10(r, a, b); | 946 | //const sp_digit* m = p256_mod; |
405 | sp_256_mont_reduce_10(r, m, mp); | 947 | //sp_digit mp = p256_mp_mod; |
948 | sp_256_mul_8(r, a, b); | ||
949 | sp_256_mont_reduce_8(r /*, m, mp*/); | ||
406 | } | 950 | } |
407 | 951 | ||
408 | /* Square the Montgomery form number. (r = a * a mod m) | 952 | /* Square the Montgomery form number. (r = a * a mod m) |
@@ -412,11 +956,12 @@ static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b | |||
412 | * m Modulus (prime). | 956 | * m Modulus (prime). |
413 | * mp Montogmery mulitplier. | 957 | * mp Montogmery mulitplier. |
414 | */ | 958 | */ |
415 | static void sp_256_mont_sqr_10(sp_digit* r, const sp_digit* a, const sp_digit* m, | 959 | static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a |
416 | sp_digit mp) | 960 | /*, const sp_digit* m, sp_digit mp*/) |
417 | { | 961 | { |
418 | sp_256_sqr_10(r, a); | 962 | //const sp_digit* m = p256_mod; |
419 | sp_256_mont_reduce_10(r, m, mp); | 963 | //sp_digit mp = p256_mp_mod; |
964 | sp_256_mont_mul_8(r, a, a /*, m, mp*/); | ||
420 | } | 965 | } |
421 | 966 | ||
422 | /* Invert the number, in Montgomery form, modulo the modulus (prime) of the | 967 | /* Invert the number, in Montgomery form, modulo the modulus (prime) of the |
@@ -437,19 +982,19 @@ static const uint32_t p256_mod_2[8] = { | |||
437 | //543210987654321098765432109876543210987654321098765432109876543210...09876543210...09876543210 | 982 | //543210987654321098765432109876543210987654321098765432109876543210...09876543210...09876543210 |
438 | //111111111111111111111111111111110000000000000000000000000000000100...00000111111...11111111101 | 983 | //111111111111111111111111111111110000000000000000000000000000000100...00000111111...11111111101 |
439 | #endif | 984 | #endif |
440 | static void sp_256_mont_inv_10(sp_digit* r, sp_digit* a) | 985 | static void sp_256_mont_inv_8(sp_digit* r, sp_digit* a) |
441 | { | 986 | { |
442 | sp_digit t[2*10]; //can be just [10]? | 987 | sp_digit t[2*8]; //can be just [8]? |
443 | int i; | 988 | int i; |
444 | 989 | ||
445 | memcpy(t, a, sizeof(sp_digit) * 10); | 990 | memcpy(t, a, sizeof(sp_digit) * 8); |
446 | for (i = 254; i >= 0; i--) { | 991 | for (i = 254; i >= 0; i--) { |
447 | sp_256_mont_sqr_10(t, t, p256_mod, p256_mp_mod); | 992 | sp_256_mont_sqr_8(t, t /*, p256_mod, p256_mp_mod*/); |
448 | /*if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32)))*/ | 993 | /*if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32)))*/ |
449 | if (i >= 224 || i == 192 || (i <= 95 && i != 1)) | 994 | if (i >= 224 || i == 192 || (i <= 95 && i != 1)) |
450 | sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod); | 995 | sp_256_mont_mul_8(t, t, a /*, p256_mod, p256_mp_mod*/); |
451 | } | 996 | } |
452 | memcpy(r, t, sizeof(sp_digit) * 10); | 997 | memcpy(r, t, sizeof(sp_digit) * 8); |
453 | } | 998 | } |
454 | 999 | ||
455 | /* Multiply a number by Montogmery normalizer mod modulus (prime). | 1000 | /* Multiply a number by Montogmery normalizer mod modulus (prime). |
@@ -457,93 +1002,29 @@ static void sp_256_mont_inv_10(sp_digit* r, sp_digit* a) | |||
457 | * r The resulting Montgomery form number. | 1002 | * r The resulting Montgomery form number. |
458 | * a The number to convert. | 1003 | * a The number to convert. |
459 | */ | 1004 | */ |
460 | static void sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a) | 1005 | static void sp_256_mod_mul_norm_8(sp_digit* r, const sp_digit* a) |
461 | { | 1006 | { |
462 | int64_t t[8]; | 1007 | int64_t t[8]; |
463 | int64_t o; | 1008 | int32_t o; |
464 | uint32_t a32; | ||
465 | 1009 | ||
1010 | #define A(n) ((uint64_t)a[n]) | ||
466 | /* 1 1 0 -1 -1 -1 -1 0 */ | 1011 | /* 1 1 0 -1 -1 -1 -1 0 */ |
1012 | t[0] = 0 + A(0) + A(1) - A(3) - A(4) - A(5) - A(6); | ||
467 | /* 0 1 1 0 -1 -1 -1 -1 */ | 1013 | /* 0 1 1 0 -1 -1 -1 -1 */ |
1014 | t[1] = 0 + A(1) + A(2) - A(4) - A(5) - A(6) - A(7); | ||
468 | /* 0 0 1 1 0 -1 -1 -1 */ | 1015 | /* 0 0 1 1 0 -1 -1 -1 */ |
1016 | t[2] = 0 + A(2) + A(3) - A(5) - A(6) - A(7); | ||
469 | /* -1 -1 0 2 2 1 0 -1 */ | 1017 | /* -1 -1 0 2 2 1 0 -1 */ |
1018 | t[3] = 0 - A(0) - A(1) + 2 * A(3) + 2 * A(4) + A(5) - A(7); | ||
470 | /* 0 -1 -1 0 2 2 1 0 */ | 1019 | /* 0 -1 -1 0 2 2 1 0 */ |
1020 | t[4] = 0 - A(1) - A(2) + 2 * A(4) + 2 * A(5) + A(6); | ||
471 | /* 0 0 -1 -1 0 2 2 1 */ | 1021 | /* 0 0 -1 -1 0 2 2 1 */ |
1022 | t[5] = 0 - A(2) - A(3) + 2 * A(5) + 2 * A(6) + A(7); | ||
472 | /* -1 -1 0 0 0 1 3 2 */ | 1023 | /* -1 -1 0 0 0 1 3 2 */ |
1024 | t[6] = 0 - A(0) - A(1) + A(5) + 3 * A(6) + 2 * A(7); | ||
473 | /* 1 0 -1 -1 -1 -1 0 3 */ | 1025 | /* 1 0 -1 -1 -1 -1 0 3 */ |
474 | // t[] should be calculated from "a" (converted from 26-bit to 32-bit vector a32[8]) | 1026 | t[7] = 0 + A(0) - A(2) - A(3) - A(4) - A(5) + 3 * A(7); |
475 | // according to the above matrix: | 1027 | #undef A |
476 | //t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6] ; | ||
477 | //t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7] ; | ||
478 | //t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7] ; | ||
479 | //t[3] = 0 - a32[0] - a32[1] + 2*a32[3] + 2*a32[4] + a32[5] - a32[7] ; | ||
480 | //t[4] = 0 - a32[1] - a32[2] + 2*a32[4] + 2*a32[5] + a32[6] ; | ||
481 | //t[5] = 0 - a32[2] - a32[3] + 2*a32[5] + 2*a32[6] + a32[7] ; | ||
482 | //t[6] = 0 - a32[0] - a32[1] + a32[5] + 3*a32[6] + 2*a32[7]; | ||
483 | //t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3*a32[7]; | ||
484 | // We can do it "piecemeal" after each a32[i] is known, no need to store entire a32[8] vector: | ||
485 | |||
486 | #define A32 (int64_t)a32 | ||
487 | a32 = a[0] | (a[1] << 26); | ||
488 | t[0] = 0 + A32; | ||
489 | t[3] = 0 - A32; | ||
490 | t[6] = 0 - A32; | ||
491 | t[7] = 0 + A32; | ||
492 | |||
493 | a32 = (a[1] >> 6) | (a[2] << 20); | ||
494 | t[0] += A32 ; | ||
495 | t[1] = 0 + A32; | ||
496 | t[3] -= A32 ; | ||
497 | t[4] = 0 - A32; | ||
498 | t[6] -= A32 ; | ||
499 | |||
500 | a32 = (a[2] >> 12) | (a[3] << 14); | ||
501 | t[1] += A32 ; | ||
502 | t[2] = 0 + A32; | ||
503 | t[4] -= A32 ; | ||
504 | t[5] = 0 - A32; | ||
505 | t[7] -= A32 ; | ||
506 | |||
507 | a32 = (a[3] >> 18) | (a[4] << 8); | ||
508 | t[0] -= A32 ; | ||
509 | t[2] += A32 ; | ||
510 | t[3] += 2*A32; | ||
511 | t[5] -= A32 ; | ||
512 | t[7] -= A32 ; | ||
513 | |||
514 | a32 = (a[4] >> 24) | (a[5] << 2) | (a[6] << 28); | ||
515 | t[0] -= A32 ; | ||
516 | t[1] -= A32 ; | ||
517 | t[3] += 2*A32; | ||
518 | t[4] += 2*A32; | ||
519 | t[7] -= A32 ; | ||
520 | |||
521 | a32 = (a[6] >> 4) | (a[7] << 22); | ||
522 | t[0] -= A32 ; | ||
523 | t[1] -= A32 ; | ||
524 | t[2] -= A32 ; | ||
525 | t[3] += A32 ; | ||
526 | t[4] += 2*A32; | ||
527 | t[5] += 2*A32; | ||
528 | t[6] += A32 ; | ||
529 | t[7] -= A32 ; | ||
530 | |||
531 | a32 = (a[7] >> 10) | (a[8] << 16); | ||
532 | t[0] -= A32 ; | ||
533 | t[1] -= A32 ; | ||
534 | t[2] -= A32 ; | ||
535 | t[4] += A32 ; | ||
536 | t[5] += 2*A32; | ||
537 | t[6] += 3*A32; | ||
538 | |||
539 | a32 = (a[8] >> 16) | (a[9] << 10); | ||
540 | t[1] -= A32 ; | ||
541 | t[2] -= A32 ; | ||
542 | t[3] -= A32 ; | ||
543 | t[5] += A32 ; | ||
544 | t[6] += 2*A32; | ||
545 | t[7] += 3*A32; | ||
546 | #undef A32 | ||
547 | 1028 | ||
548 | t[1] += t[0] >> 32; t[0] &= 0xffffffff; | 1029 | t[1] += t[0] >> 32; t[0] &= 0xffffffff; |
549 | t[2] += t[1] >> 32; t[1] &= 0xffffffff; | 1030 | t[2] += t[1] >> 32; t[1] &= 0xffffffff; |
@@ -552,29 +1033,27 @@ static void sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a) | |||
552 | t[5] += t[4] >> 32; t[4] &= 0xffffffff; | 1033 | t[5] += t[4] >> 32; t[4] &= 0xffffffff; |
553 | t[6] += t[5] >> 32; t[5] &= 0xffffffff; | 1034 | t[6] += t[5] >> 32; t[5] &= 0xffffffff; |
554 | t[7] += t[6] >> 32; t[6] &= 0xffffffff; | 1035 | t[7] += t[6] >> 32; t[6] &= 0xffffffff; |
555 | o = t[7] >> 32; t[7] &= 0xffffffff; | 1036 | o = t[7] >> 32; //t[7] &= 0xffffffff; |
556 | t[0] += o; | 1037 | t[0] += o; |
557 | t[3] -= o; | 1038 | t[3] -= o; |
558 | t[6] -= o; | 1039 | t[6] -= o; |
559 | t[7] += o; | 1040 | t[7] += o; |
560 | t[1] += t[0] >> 32; //t[0] &= 0xffffffff; | 1041 | r[0] = (sp_digit)t[0]; |
561 | t[2] += t[1] >> 32; //t[1] &= 0xffffffff; | 1042 | t[1] += t[0] >> 32; |
562 | t[3] += t[2] >> 32; //t[2] &= 0xffffffff; | 1043 | r[1] = (sp_digit)t[1]; |
563 | t[4] += t[3] >> 32; //t[3] &= 0xffffffff; | 1044 | t[2] += t[1] >> 32; |
564 | t[5] += t[4] >> 32; //t[4] &= 0xffffffff; | 1045 | r[2] = (sp_digit)t[2]; |
565 | t[6] += t[5] >> 32; //t[5] &= 0xffffffff; | 1046 | t[3] += t[2] >> 32; |
566 | t[7] += t[6] >> 32; //t[6] &= 0xffffffff; - (uint32_t)t[i] casts below accomplish masking | 1047 | r[3] = (sp_digit)t[3]; |
567 | 1048 | t[4] += t[3] >> 32; | |
568 | r[0] = 0x3ffffff & ((sp_digit)((uint32_t)t[0])); | 1049 | r[4] = (sp_digit)t[4]; |
569 | r[1] = 0x3ffffff & ((sp_digit)((uint32_t)t[0] >> 26) | ((sp_digit)t[1] << 6)); | 1050 | t[5] += t[4] >> 32; |
570 | r[2] = 0x3ffffff & ((sp_digit)((uint32_t)t[1] >> 20) | ((sp_digit)t[2] << 12)); | 1051 | r[5] = (sp_digit)t[5]; |
571 | r[3] = 0x3ffffff & ((sp_digit)((uint32_t)t[2] >> 14) | ((sp_digit)t[3] << 18)); | 1052 | t[6] += t[5] >> 32; |
572 | r[4] = 0x3ffffff & ((sp_digit)((uint32_t)t[3] >> 8) | ((sp_digit)t[4] << 24)); | 1053 | r[6] = (sp_digit)t[6]; |
573 | r[5] = 0x3ffffff & ((sp_digit)((uint32_t)t[4] >> 2)); | 1054 | // t[7] += t[6] >> 32; |
574 | r[6] = 0x3ffffff & ((sp_digit)((uint32_t)t[4] >> 28) | ((sp_digit)t[5] << 4)); | 1055 | // r[7] = (sp_digit)t[7]; |
575 | r[7] = 0x3ffffff & ((sp_digit)((uint32_t)t[5] >> 22) | ((sp_digit)t[6] << 10)); | 1056 | r[7] = (sp_digit)t[7] + (sp_digit)(t[6] >> 32); |
576 | r[8] = 0x3ffffff & ((sp_digit)((uint32_t)t[6] >> 16) | ((sp_digit)t[7] << 16)); | ||
577 | r[9] = ((sp_digit)((uint32_t)t[7] >> 10)); | ||
578 | } | 1057 | } |
579 | 1058 | ||
580 | /* Map the Montgomery form projective co-ordinate point to an affine point. | 1059 | /* Map the Montgomery form projective co-ordinate point to an affine point. |
@@ -582,33 +1061,33 @@ static void sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a) | |||
582 | * r Resulting affine co-ordinate point. | 1061 | * r Resulting affine co-ordinate point. |
583 | * p Montgomery form projective co-ordinate point. | 1062 | * p Montgomery form projective co-ordinate point. |
584 | */ | 1063 | */ |
585 | static void sp_256_map_10(sp_point* r, sp_point* p) | 1064 | static void sp_256_map_8(sp_point* r, sp_point* p) |
586 | { | 1065 | { |
587 | sp_digit t1[2*10]; | 1066 | sp_digit t1[2*8]; |
588 | sp_digit t2[2*10]; | 1067 | sp_digit t2[2*8]; |
589 | 1068 | ||
590 | sp_256_mont_inv_10(t1, p->z); | 1069 | sp_256_mont_inv_8(t1, p->z); |
591 | 1070 | ||
592 | sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod); | 1071 | sp_256_mont_sqr_8(t2, t1 /*, p256_mod, p256_mp_mod*/); |
593 | sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod); | 1072 | sp_256_mont_mul_8(t1, t2, t1 /*, p256_mod, p256_mp_mod*/); |
594 | 1073 | ||
595 | /* x /= z^2 */ | 1074 | /* x /= z^2 */ |
596 | sp_256_mont_mul_10(r->x, p->x, t2, p256_mod, p256_mp_mod); | 1075 | sp_256_mont_mul_8(r->x, p->x, t2 /*, p256_mod, p256_mp_mod*/); |
597 | memset(r->x + 10, 0, sizeof(r->x) / 2); | 1076 | memset(r->x + 8, 0, sizeof(r->x) / 2); |
598 | sp_256_mont_reduce_10(r->x, p256_mod, p256_mp_mod); | 1077 | sp_256_mont_reduce_8(r->x /*, p256_mod, p256_mp_mod*/); |
599 | /* Reduce x to less than modulus */ | 1078 | /* Reduce x to less than modulus */ |
600 | if (sp_256_cmp_10(r->x, p256_mod) >= 0) | 1079 | if (sp_256_cmp_8(r->x, p256_mod) >= 0) |
601 | sp_256_sub_10(r->x, r->x, p256_mod); | 1080 | sp_256_sub_8_p256_mod(r->x); |
602 | sp_256_norm_10(r->x); | 1081 | sp_256_norm_8(r->x); |
603 | 1082 | ||
604 | /* y /= z^3 */ | 1083 | /* y /= z^3 */ |
605 | sp_256_mont_mul_10(r->y, p->y, t1, p256_mod, p256_mp_mod); | 1084 | sp_256_mont_mul_8(r->y, p->y, t1 /*, p256_mod, p256_mp_mod*/); |
606 | memset(r->y + 10, 0, sizeof(r->y) / 2); | 1085 | memset(r->y + 8, 0, sizeof(r->y) / 2); |
607 | sp_256_mont_reduce_10(r->y, p256_mod, p256_mp_mod); | 1086 | sp_256_mont_reduce_8(r->y /*, p256_mod, p256_mp_mod*/); |
608 | /* Reduce y to less than modulus */ | 1087 | /* Reduce y to less than modulus */ |
609 | if (sp_256_cmp_10(r->y, p256_mod) >= 0) | 1088 | if (sp_256_cmp_8(r->y, p256_mod) >= 0) |
610 | sp_256_sub_10(r->y, r->y, p256_mod); | 1089 | sp_256_sub_8_p256_mod(r->y); |
611 | sp_256_norm_10(r->y); | 1090 | sp_256_norm_8(r->y); |
612 | 1091 | ||
613 | memset(r->z, 0, sizeof(r->z)); | 1092 | memset(r->z, 0, sizeof(r->z)); |
614 | r->z[0] = 1; | 1093 | r->z[0] = 1; |
@@ -619,56 +1098,62 @@ static void sp_256_map_10(sp_point* r, sp_point* p) | |||
619 | * r Result of doubling point. | 1098 | * r Result of doubling point. |
620 | * p Point to double. | 1099 | * p Point to double. |
621 | */ | 1100 | */ |
622 | static void sp_256_proj_point_dbl_10(sp_point* r, sp_point* p) | 1101 | static void sp_256_proj_point_dbl_8(sp_point* r, sp_point* p) |
623 | { | 1102 | { |
624 | sp_point tp; | 1103 | sp_digit t1[2*8]; |
625 | sp_digit t1[2*10]; | 1104 | sp_digit t2[2*8]; |
626 | sp_digit t2[2*10]; | ||
627 | 1105 | ||
628 | /* Put point to double into result */ | 1106 | /* Put point to double into result */ |
629 | if (r != p) | 1107 | if (r != p) |
630 | *r = *p; /* struct copy */ | 1108 | *r = *p; /* struct copy */ |
631 | 1109 | ||
632 | if (r->infinity) { | 1110 | if (r->infinity) |
633 | /* If infinity, don't double (work on dummy value) */ | 1111 | return; |
634 | r = &tp; | 1112 | |
1113 | if (SP_DEBUG) { | ||
1114 | /* unused part of t2, may result in spurios | ||
1115 | * differences in debug output. Clear it. | ||
1116 | */ | ||
1117 | memset(t2, 0, sizeof(t2)); | ||
635 | } | 1118 | } |
1119 | |||
636 | /* T1 = Z * Z */ | 1120 | /* T1 = Z * Z */ |
637 | sp_256_mont_sqr_10(t1, r->z, p256_mod, p256_mp_mod); | 1121 | sp_256_mont_sqr_8(t1, r->z /*, p256_mod, p256_mp_mod*/); |
638 | /* Z = Y * Z */ | 1122 | /* Z = Y * Z */ |
639 | sp_256_mont_mul_10(r->z, r->y, r->z, p256_mod, p256_mp_mod); | 1123 | sp_256_mont_mul_8(r->z, r->y, r->z /*, p256_mod, p256_mp_mod*/); |
640 | /* Z = 2Z */ | 1124 | /* Z = 2Z */ |
641 | sp_256_mont_dbl_10(r->z, r->z, p256_mod); | 1125 | sp_256_mont_dbl_8(r->z, r->z /*, p256_mod*/); |
642 | /* T2 = X - T1 */ | 1126 | /* T2 = X - T1 */ |
643 | sp_256_mont_sub_10(t2, r->x, t1, p256_mod); | 1127 | sp_256_mont_sub_8(t2, r->x, t1 /*, p256_mod*/); |
644 | /* T1 = X + T1 */ | 1128 | /* T1 = X + T1 */ |
645 | sp_256_mont_add_10(t1, r->x, t1, p256_mod); | 1129 | sp_256_mont_add_8(t1, r->x, t1 /*, p256_mod*/); |
646 | /* T2 = T1 * T2 */ | 1130 | /* T2 = T1 * T2 */ |
647 | sp_256_mont_mul_10(t2, t1, t2, p256_mod, p256_mp_mod); | 1131 | sp_256_mont_mul_8(t2, t1, t2 /*, p256_mod, p256_mp_mod*/); |
648 | /* T1 = 3T2 */ | 1132 | /* T1 = 3T2 */ |
649 | sp_256_mont_tpl_10(t1, t2, p256_mod); | 1133 | sp_256_mont_tpl_8(t1, t2 /*, p256_mod*/); |
650 | /* Y = 2Y */ | 1134 | /* Y = 2Y */ |
651 | sp_256_mont_dbl_10(r->y, r->y, p256_mod); | 1135 | sp_256_mont_dbl_8(r->y, r->y /*, p256_mod*/); |
652 | /* Y = Y * Y */ | 1136 | /* Y = Y * Y */ |
653 | sp_256_mont_sqr_10(r->y, r->y, p256_mod, p256_mp_mod); | 1137 | sp_256_mont_sqr_8(r->y, r->y /*, p256_mod, p256_mp_mod*/); |
654 | /* T2 = Y * Y */ | 1138 | /* T2 = Y * Y */ |
655 | sp_256_mont_sqr_10(t2, r->y, p256_mod, p256_mp_mod); | 1139 | sp_256_mont_sqr_8(t2, r->y /*, p256_mod, p256_mp_mod*/); |
656 | /* T2 = T2/2 */ | 1140 | /* T2 = T2/2 */ |
657 | sp_256_div2_10(t2, t2, p256_mod); | 1141 | sp_256_div2_8(t2, t2, p256_mod); |
658 | /* Y = Y * X */ | 1142 | /* Y = Y * X */ |
659 | sp_256_mont_mul_10(r->y, r->y, r->x, p256_mod, p256_mp_mod); | 1143 | sp_256_mont_mul_8(r->y, r->y, r->x /*, p256_mod, p256_mp_mod*/); |
660 | /* X = T1 * T1 */ | 1144 | /* X = T1 * T1 */ |
661 | sp_256_mont_mul_10(r->x, t1, t1, p256_mod, p256_mp_mod); | 1145 | sp_256_mont_mul_8(r->x, t1, t1 /*, p256_mod, p256_mp_mod*/); |
662 | /* X = X - Y */ | 1146 | /* X = X - Y */ |
663 | sp_256_mont_sub_10(r->x, r->x, r->y, p256_mod); | 1147 | sp_256_mont_sub_8(r->x, r->x, r->y /*, p256_mod*/); |
664 | /* X = X - Y */ | 1148 | /* X = X - Y */ |
665 | sp_256_mont_sub_10(r->x, r->x, r->y, p256_mod); | 1149 | sp_256_mont_sub_8(r->x, r->x, r->y /*, p256_mod*/); |
666 | /* Y = Y - X */ | 1150 | /* Y = Y - X */ |
667 | sp_256_mont_sub_10(r->y, r->y, r->x, p256_mod); | 1151 | sp_256_mont_sub_8(r->y, r->y, r->x /*, p256_mod*/); |
668 | /* Y = Y * T1 */ | 1152 | /* Y = Y * T1 */ |
669 | sp_256_mont_mul_10(r->y, r->y, t1, p256_mod, p256_mp_mod); | 1153 | sp_256_mont_mul_8(r->y, r->y, t1 /*, p256_mod, p256_mp_mod*/); |
670 | /* Y = Y - T2 */ | 1154 | /* Y = Y - T2 */ |
671 | sp_256_mont_sub_10(r->y, r->y, t2, p256_mod); | 1155 | sp_256_mont_sub_8(r->y, r->y, t2 /*, p256_mod*/); |
1156 | dump_512("y2 %s\n", r->y); | ||
672 | } | 1157 | } |
673 | 1158 | ||
674 | /* Add two Montgomery form projective points. | 1159 | /* Add two Montgomery form projective points. |
@@ -677,13 +1162,13 @@ static void sp_256_proj_point_dbl_10(sp_point* r, sp_point* p) | |||
677 | * p Frist point to add. | 1162 | * p Frist point to add. |
678 | * q Second point to add. | 1163 | * q Second point to add. |
679 | */ | 1164 | */ |
680 | static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q) | 1165 | static NOINLINE void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* q) |
681 | { | 1166 | { |
682 | sp_digit t1[2*10]; | 1167 | sp_digit t1[2*8]; |
683 | sp_digit t2[2*10]; | 1168 | sp_digit t2[2*8]; |
684 | sp_digit t3[2*10]; | 1169 | sp_digit t3[2*8]; |
685 | sp_digit t4[2*10]; | 1170 | sp_digit t4[2*8]; |
686 | sp_digit t5[2*10]; | 1171 | sp_digit t5[2*8]; |
687 | 1172 | ||
688 | /* Ensure only the first point is the same as the result. */ | 1173 | /* Ensure only the first point is the same as the result. */ |
689 | if (q == r) { | 1174 | if (q == r) { |
@@ -693,13 +1178,13 @@ static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q) | |||
693 | } | 1178 | } |
694 | 1179 | ||
695 | /* Check double */ | 1180 | /* Check double */ |
696 | sp_256_sub_10(t1, p256_mod, q->y); | 1181 | sp_256_sub_8(t1, p256_mod, q->y); |
697 | sp_256_norm_10(t1); | 1182 | sp_256_norm_8(t1); |
698 | if (sp_256_cmp_equal_10(p->x, q->x) | 1183 | if (sp_256_cmp_equal_8(p->x, q->x) |
699 | && sp_256_cmp_equal_10(p->z, q->z) | 1184 | && sp_256_cmp_equal_8(p->z, q->z) |
700 | && (sp_256_cmp_equal_10(p->y, q->y) || sp_256_cmp_equal_10(p->y, t1)) | 1185 | && (sp_256_cmp_equal_8(p->y, q->y) || sp_256_cmp_equal_8(p->y, t1)) |
701 | ) { | 1186 | ) { |
702 | sp_256_proj_point_dbl_10(r, p); | 1187 | sp_256_proj_point_dbl_8(r, p); |
703 | } | 1188 | } |
704 | else { | 1189 | else { |
705 | sp_point tp; | 1190 | sp_point tp; |
@@ -714,37 +1199,37 @@ static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q) | |||
714 | *r = p->infinity ? *q : *p; /* struct copy */ | 1199 | *r = p->infinity ? *q : *p; /* struct copy */ |
715 | 1200 | ||
716 | /* U1 = X1*Z2^2 */ | 1201 | /* U1 = X1*Z2^2 */ |
717 | sp_256_mont_sqr_10(t1, q->z, p256_mod, p256_mp_mod); | 1202 | sp_256_mont_sqr_8(t1, q->z /*, p256_mod, p256_mp_mod*/); |
718 | sp_256_mont_mul_10(t3, t1, q->z, p256_mod, p256_mp_mod); | 1203 | sp_256_mont_mul_8(t3, t1, q->z /*, p256_mod, p256_mp_mod*/); |
719 | sp_256_mont_mul_10(t1, t1, v->x, p256_mod, p256_mp_mod); | 1204 | sp_256_mont_mul_8(t1, t1, v->x /*, p256_mod, p256_mp_mod*/); |
720 | /* U2 = X2*Z1^2 */ | 1205 | /* U2 = X2*Z1^2 */ |
721 | sp_256_mont_sqr_10(t2, v->z, p256_mod, p256_mp_mod); | 1206 | sp_256_mont_sqr_8(t2, v->z /*, p256_mod, p256_mp_mod*/); |
722 | sp_256_mont_mul_10(t4, t2, v->z, p256_mod, p256_mp_mod); | 1207 | sp_256_mont_mul_8(t4, t2, v->z /*, p256_mod, p256_mp_mod*/); |
723 | sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod); | 1208 | sp_256_mont_mul_8(t2, t2, q->x /*, p256_mod, p256_mp_mod*/); |
724 | /* S1 = Y1*Z2^3 */ | 1209 | /* S1 = Y1*Z2^3 */ |
725 | sp_256_mont_mul_10(t3, t3, v->y, p256_mod, p256_mp_mod); | 1210 | sp_256_mont_mul_8(t3, t3, v->y /*, p256_mod, p256_mp_mod*/); |
726 | /* S2 = Y2*Z1^3 */ | 1211 | /* S2 = Y2*Z1^3 */ |
727 | sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod); | 1212 | sp_256_mont_mul_8(t4, t4, q->y /*, p256_mod, p256_mp_mod*/); |
728 | /* H = U2 - U1 */ | 1213 | /* H = U2 - U1 */ |
729 | sp_256_mont_sub_10(t2, t2, t1, p256_mod); | 1214 | sp_256_mont_sub_8(t2, t2, t1 /*, p256_mod*/); |
730 | /* R = S2 - S1 */ | 1215 | /* R = S2 - S1 */ |
731 | sp_256_mont_sub_10(t4, t4, t3, p256_mod); | 1216 | sp_256_mont_sub_8(t4, t4, t3 /*, p256_mod*/); |
732 | /* Z3 = H*Z1*Z2 */ | 1217 | /* Z3 = H*Z1*Z2 */ |
733 | sp_256_mont_mul_10(v->z, v->z, q->z, p256_mod, p256_mp_mod); | 1218 | sp_256_mont_mul_8(v->z, v->z, q->z /*, p256_mod, p256_mp_mod*/); |
734 | sp_256_mont_mul_10(v->z, v->z, t2, p256_mod, p256_mp_mod); | 1219 | sp_256_mont_mul_8(v->z, v->z, t2 /*, p256_mod, p256_mp_mod*/); |
735 | /* X3 = R^2 - H^3 - 2*U1*H^2 */ | 1220 | /* X3 = R^2 - H^3 - 2*U1*H^2 */ |
736 | sp_256_mont_sqr_10(v->x, t4, p256_mod, p256_mp_mod); | 1221 | sp_256_mont_sqr_8(v->x, t4 /*, p256_mod, p256_mp_mod*/); |
737 | sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod); | 1222 | sp_256_mont_sqr_8(t5, t2 /*, p256_mod, p256_mp_mod*/); |
738 | sp_256_mont_mul_10(v->y, t1, t5, p256_mod, p256_mp_mod); | 1223 | sp_256_mont_mul_8(v->y, t1, t5 /*, p256_mod, p256_mp_mod*/); |
739 | sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod); | 1224 | sp_256_mont_mul_8(t5, t5, t2 /*, p256_mod, p256_mp_mod*/); |
740 | sp_256_mont_sub_10(v->x, v->x, t5, p256_mod); | 1225 | sp_256_mont_sub_8(v->x, v->x, t5 /*, p256_mod*/); |
741 | sp_256_mont_dbl_10(t1, v->y, p256_mod); | 1226 | sp_256_mont_dbl_8(t1, v->y /*, p256_mod*/); |
742 | sp_256_mont_sub_10(v->x, v->x, t1, p256_mod); | 1227 | sp_256_mont_sub_8(v->x, v->x, t1 /*, p256_mod*/); |
743 | /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ | 1228 | /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ |
744 | sp_256_mont_sub_10(v->y, v->y, v->x, p256_mod); | 1229 | sp_256_mont_sub_8(v->y, v->y, v->x /*, p256_mod*/); |
745 | sp_256_mont_mul_10(v->y, v->y, t4, p256_mod, p256_mp_mod); | 1230 | sp_256_mont_mul_8(v->y, v->y, t4 /*, p256_mod, p256_mp_mod*/); |
746 | sp_256_mont_mul_10(t5, t5, t3, p256_mod, p256_mp_mod); | 1231 | sp_256_mont_mul_8(t5, t5, t3 /*, p256_mod, p256_mp_mod*/); |
747 | sp_256_mont_sub_10(v->y, v->y, t5, p256_mod); | 1232 | sp_256_mont_sub_8(v->y, v->y, t5 /*, p256_mod*/); |
748 | } | 1233 | } |
749 | } | 1234 | } |
750 | 1235 | ||
@@ -756,12 +1241,11 @@ static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q) | |||
756 | * k Scalar to multiply by. | 1241 | * k Scalar to multiply by. |
757 | * map Indicates whether to convert result to affine. | 1242 | * map Indicates whether to convert result to affine. |
758 | */ | 1243 | */ |
759 | static void sp_256_ecc_mulmod_10(sp_point* r, const sp_point* g, const sp_digit* k /*, int map*/) | 1244 | static void sp_256_ecc_mulmod_8(sp_point* r, const sp_point* g, const sp_digit* k /*, int map*/) |
760 | { | 1245 | { |
761 | enum { map = 1 }; /* we always convert result to affine coordinates */ | 1246 | enum { map = 1 }; /* we always convert result to affine coordinates */ |
762 | sp_point t[3]; | 1247 | sp_point t[3]; |
763 | sp_digit n; | 1248 | sp_digit n = n; /* for compiler */ |
764 | int i; | ||
765 | int c, y; | 1249 | int c, y; |
766 | 1250 | ||
767 | memset(t, 0, sizeof(t)); | 1251 | memset(t, 0, sizeof(t)); |
@@ -769,33 +1253,44 @@ static void sp_256_ecc_mulmod_10(sp_point* r, const sp_point* g, const sp_digit* | |||
769 | /* t[0] = {0, 0, 1} * norm */ | 1253 | /* t[0] = {0, 0, 1} * norm */ |
770 | t[0].infinity = 1; | 1254 | t[0].infinity = 1; |
771 | /* t[1] = {g->x, g->y, g->z} * norm */ | 1255 | /* t[1] = {g->x, g->y, g->z} * norm */ |
772 | sp_256_mod_mul_norm_10(t[1].x, g->x); | 1256 | sp_256_mod_mul_norm_8(t[1].x, g->x); |
773 | sp_256_mod_mul_norm_10(t[1].y, g->y); | 1257 | sp_256_mod_mul_norm_8(t[1].y, g->y); |
774 | sp_256_mod_mul_norm_10(t[1].z, g->z); | 1258 | sp_256_mod_mul_norm_8(t[1].z, g->z); |
775 | |||
776 | i = 9; | ||
777 | c = 22; | ||
778 | n = k[i--] << (26 - c); | ||
779 | for (; ; c--) { | ||
780 | if (c == 0) { | ||
781 | if (i == -1) | ||
782 | break; | ||
783 | 1259 | ||
784 | n = k[i--]; | 1260 | /* For every bit, starting from most significant... */ |
785 | c = 26; | 1261 | k += 7; |
1262 | c = 256; | ||
1263 | for (;;) { | ||
1264 | if ((c & 0x1f) == 0) { | ||
1265 | if (c == 0) | ||
1266 | break; | ||
1267 | n = *k--; | ||
786 | } | 1268 | } |
787 | 1269 | ||
788 | y = (n >> 25) & 1; | 1270 | y = (n >> 31); |
789 | n <<= 1; | 1271 | dbg("y:%d t[%d] = t[0]+t[1]\n", y, y^1); |
790 | 1272 | sp_256_proj_point_add_8(&t[y^1], &t[0], &t[1]); | |
791 | sp_256_proj_point_add_10(&t[y^1], &t[0], &t[1]); | 1273 | dump_512("t[0].x %s\n", t[0].x); |
1274 | dump_512("t[0].y %s\n", t[0].y); | ||
1275 | dump_512("t[0].z %s\n", t[0].z); | ||
1276 | dump_512("t[1].x %s\n", t[1].x); | ||
1277 | dump_512("t[1].y %s\n", t[1].y); | ||
1278 | dump_512("t[1].z %s\n", t[1].z); | ||
1279 | dbg("t[2] = t[%d]\n", y); | ||
792 | memcpy(&t[2], &t[y], sizeof(sp_point)); | 1280 | memcpy(&t[2], &t[y], sizeof(sp_point)); |
793 | sp_256_proj_point_dbl_10(&t[2], &t[2]); | 1281 | dbg("t[2] *= 2\n"); |
1282 | sp_256_proj_point_dbl_8(&t[2], &t[2]); | ||
1283 | dump_512("t[2].x %s\n", t[2].x); | ||
1284 | dump_512("t[2].y %s\n", t[2].y); | ||
1285 | dump_512("t[2].z %s\n", t[2].z); | ||
794 | memcpy(&t[y], &t[2], sizeof(sp_point)); | 1286 | memcpy(&t[y], &t[2], sizeof(sp_point)); |
1287 | |||
1288 | n <<= 1; | ||
1289 | c--; | ||
795 | } | 1290 | } |
796 | 1291 | ||
797 | if (map) | 1292 | if (map) |
798 | sp_256_map_10(r, &t[0]); | 1293 | sp_256_map_8(r, &t[0]); |
799 | else | 1294 | else |
800 | memcpy(r, &t[0], sizeof(sp_point)); | 1295 | memcpy(r, &t[0], sizeof(sp_point)); |
801 | 1296 | ||
@@ -809,7 +1304,7 @@ static void sp_256_ecc_mulmod_10(sp_point* r, const sp_point* g, const sp_digit* | |||
809 | * k Scalar to multiply by. | 1304 | * k Scalar to multiply by. |
810 | * map Indicates whether to convert result to affine. | 1305 | * map Indicates whether to convert result to affine. |
811 | */ | 1306 | */ |
812 | static void sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k /*, int map*/) | 1307 | static void sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k /*, int map*/) |
813 | { | 1308 | { |
814 | /* Since this function is called only once, save space: | 1309 | /* Since this function is called only once, save space: |
815 | * don't have "static const sp_point p256_base = {...}", | 1310 | * don't have "static const sp_point p256_base = {...}", |
@@ -826,7 +1321,7 @@ static void sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k /*, int map*/) | |||
826 | 1321 | ||
827 | sp_256_point_from_bin2x32(&p256_base, p256_base_bin); | 1322 | sp_256_point_from_bin2x32(&p256_base, p256_base_bin); |
828 | 1323 | ||
829 | sp_256_ecc_mulmod_10(r, &p256_base, k /*, map*/); | 1324 | sp_256_ecc_mulmod_8(r, &p256_base, k /*, map*/); |
830 | } | 1325 | } |
831 | 1326 | ||
832 | /* Multiply the point by the scalar and serialize the X ordinate. | 1327 | /* Multiply the point by the scalar and serialize the X ordinate. |
@@ -836,7 +1331,7 @@ static void sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k /*, int map*/) | |||
836 | * pub2x32 Point to multiply. | 1331 | * pub2x32 Point to multiply. |
837 | * out32 Buffer to hold X ordinate. | 1332 | * out32 Buffer to hold X ordinate. |
838 | */ | 1333 | */ |
839 | static void sp_ecc_secret_gen_256(const sp_digit priv[10], const uint8_t *pub2x32, uint8_t* out32) | 1334 | static void sp_ecc_secret_gen_256(const sp_digit priv[8], const uint8_t *pub2x32, uint8_t* out32) |
840 | { | 1335 | { |
841 | sp_point point[1]; | 1336 | sp_point point[1]; |
842 | 1337 | ||
@@ -847,66 +1342,51 @@ static void sp_ecc_secret_gen_256(const sp_digit priv[10], const uint8_t *pub2x3 | |||
847 | dump_hex(" %s\n", pub2x32 + 32, 32); | 1342 | dump_hex(" %s\n", pub2x32 + 32, 32); |
848 | 1343 | ||
849 | sp_256_point_from_bin2x32(point, pub2x32); | 1344 | sp_256_point_from_bin2x32(point, pub2x32); |
850 | dump_hex("point->x %s\n", point->x, sizeof(point->x)); | 1345 | dump_512("point->x %s\n", point->x); |
851 | dump_hex("point->y %s\n", point->y, sizeof(point->y)); | 1346 | dump_512("point->y %s\n", point->y); |
852 | 1347 | ||
853 | sp_256_ecc_mulmod_10(point, point, priv); | 1348 | sp_256_ecc_mulmod_8(point, point, priv); |
854 | 1349 | ||
855 | sp_256_to_bin(point->x, out32); | 1350 | sp_256_to_bin_8(point->x, out32); |
856 | dump_hex("out32: %s\n", out32, 32); | 1351 | dump_hex("out32: %s\n", out32, 32); |
857 | } | 1352 | } |
858 | 1353 | ||
859 | /* Generates a scalar that is in the range 1..order-1. */ | 1354 | /* Generates a random scalar in [1..order-1] range. */ |
860 | #define SIMPLIFY 1 | 1355 | static void sp_256_ecc_gen_k_8(sp_digit k[8]) |
861 | /* Add 1 to a. (a = a + 1) */ | ||
862 | static void sp_256_add_one_10(sp_digit* a) | ||
863 | { | 1356 | { |
864 | a[0]++; | 1357 | /* Since 32-bit words are "dense", no need to use |
865 | sp_256_norm_10(a); | 1358 | * sp_256_from_bin_8(k, buf) to convert random stream |
866 | } | 1359 | * to sp_digit array - just store random bits there directly. |
867 | static void sp_256_ecc_gen_k_10(sp_digit k[10]) | 1360 | */ |
868 | { | 1361 | tls_get_random(k, 8 * sizeof(k[0])); |
869 | #if !SIMPLIFY | ||
870 | /* The order of the curve P256 minus 2. */ | ||
871 | static const sp_digit p256_order2[10] = { | ||
872 | 0x063254f,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa, | ||
873 | 0x3ffffff,0x3ffffff,0x00003ff,0x3ff0000,0x03fffff, | ||
874 | }; | ||
875 | #endif | ||
876 | uint8_t buf[32]; | ||
877 | |||
878 | for (;;) { | ||
879 | tls_get_random(buf, sizeof(buf)); | ||
880 | #if FIXED_SECRET | 1362 | #if FIXED_SECRET |
881 | memset(buf, 0x77, sizeof(buf)); | 1363 | memset(k, 0x77, 8 * sizeof(k[0])); |
882 | #endif | ||
883 | sp_256_from_bin(k, 10, buf, sizeof(buf)); | ||
884 | #if !SIMPLIFY | ||
885 | if (sp_256_cmp_10(k, p256_order2) < 0) | ||
886 | break; | ||
887 | #else | ||
888 | /* non-loopy version (and not needing p256_order2[]): | ||
889 | * if most-significant word seems that k can be larger | ||
890 | * than p256_order2, fix it up: | ||
891 | */ | ||
892 | if (k[9] >= 0x03fffff) | ||
893 | k[9] = 0x03ffffe; | ||
894 | break; | ||
895 | #endif | 1364 | #endif |
896 | } | 1365 | |
897 | sp_256_add_one_10(k); | 1366 | // If scalar is too large, try again (pseudo-code) |
898 | #undef SIMPLIFY | 1367 | // if (k >= 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 - 1) // order of P256 |
1368 | // goto pick_another_random; | ||
1369 | // k++; // ensure non-zero | ||
1370 | /* Simpler alternative, at the cost of not choosing some valid | ||
1371 | * random values, and slightly non-uniform distribution */ | ||
1372 | if (k[0] == 0) | ||
1373 | k[0] = 1; | ||
1374 | if (k[7] >= 0xffffffff) | ||
1375 | k[7] = 0xfffffffe; | ||
899 | } | 1376 | } |
900 | 1377 | ||
901 | /* Makes a random EC key pair. */ | 1378 | /* Makes a random EC key pair. */ |
902 | static void sp_ecc_make_key_256(sp_digit privkey[10], uint8_t *pubkey) | 1379 | static void sp_ecc_make_key_256(sp_digit privkey[8], uint8_t *pubkey) |
903 | { | 1380 | { |
904 | sp_point point[1]; | 1381 | sp_point point[1]; |
905 | 1382 | ||
906 | sp_256_ecc_gen_k_10(privkey); | 1383 | sp_256_ecc_gen_k_8(privkey); |
907 | sp_256_ecc_mulmod_base_10(point, privkey); | 1384 | dump_256("privkey %s\n", privkey); |
908 | sp_256_to_bin(point->x, pubkey); | 1385 | sp_256_ecc_mulmod_base_8(point, privkey); |
909 | sp_256_to_bin(point->y, pubkey + 32); | 1386 | dump_512("point->x %s\n", point->x); |
1387 | dump_512("point->y %s\n", point->y); | ||
1388 | sp_256_to_bin_8(point->x, pubkey); | ||
1389 | sp_256_to_bin_8(point->y, pubkey + 32); | ||
910 | 1390 | ||
911 | memset(point, 0, sizeof(point)); //paranoia | 1391 | memset(point, 0, sizeof(point)); //paranoia |
912 | } | 1392 | } |
@@ -915,8 +1395,9 @@ void FAST_FUNC curve_P256_compute_pubkey_and_premaster( | |||
915 | uint8_t *pubkey2x32, uint8_t *premaster32, | 1395 | uint8_t *pubkey2x32, uint8_t *premaster32, |
916 | const uint8_t *peerkey2x32) | 1396 | const uint8_t *peerkey2x32) |
917 | { | 1397 | { |
918 | sp_digit privkey[10]; | 1398 | sp_digit privkey[8]; |
919 | 1399 | ||
1400 | dump_hex("peerkey2x32: %s\n", peerkey2x32, 64); | ||
920 | sp_ecc_make_key_256(privkey, pubkey2x32); | 1401 | sp_ecc_make_key_256(privkey, pubkey2x32); |
921 | dump_hex("pubkey: %s\n", pubkey2x32, 32); | 1402 | dump_hex("pubkey: %s\n", pubkey2x32, 32); |
922 | dump_hex(" %s\n", pubkey2x32 + 32, 32); | 1403 | dump_hex(" %s\n", pubkey2x32 + 32, 32); |
diff --git a/networking/tls_symmetric.h b/networking/tls_symmetric.h deleted file mode 100644 index 5e0e4b6d8..000000000 --- a/networking/tls_symmetric.h +++ /dev/null | |||
@@ -1,511 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Denys Vlasenko | ||
3 | * | ||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | */ | ||
6 | |||
7 | |||
8 | /* The part below is a section of matrixssl-3-7-2b-open/crypto/cryptolib.h | ||
9 | * Changes are flagged with //bbox | ||
10 | */ | ||
11 | |||
12 | /******************************************************************************/ | ||
13 | /* 32-bit Rotates */ | ||
14 | /******************************************************************************/ | ||
15 | #if defined(_MSC_VER) | ||
16 | /******************************************************************************/ | ||
17 | |||
18 | /* instrinsic rotate */ | ||
19 | #include <stdlib.h> | ||
20 | #pragma intrinsic(_lrotr,_lrotl) | ||
21 | #define ROR(x,n) _lrotr(x,n) | ||
22 | #define ROL(x,n) _lrotl(x,n) | ||
23 | |||
24 | /******************************************************************************/ | ||
25 | #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && \ | ||
26 | !defined(INTEL_CC) && !defined(PS_NO_ASM) | ||
27 | |||
28 | static ALWAYS_INLINE unsigned ROL(unsigned word, int i) | ||
29 | { | ||
30 | if (__builtin_constant_p(i)) { //box | ||
31 | // Rotates by constant use fewer registers, | ||
32 | // and on many Intel CPUs rotates by %cl take 2 cycles, not 1. | ||
33 | asm ("roll %2,%0" | ||
34 | :"=r" (word) | ||
35 | :"0" (word),"i" (i)); | ||
36 | return word; | ||
37 | } //box | ||
38 | asm ("roll %%cl,%0" | ||
39 | :"=r" (word) | ||
40 | :"0" (word),"c" (i)); | ||
41 | return word; | ||
42 | } | ||
43 | |||
44 | static ALWAYS_INLINE unsigned ROR(unsigned word, int i) | ||
45 | { | ||
46 | if (__builtin_constant_p(i)) { //box | ||
47 | asm ("rorl %2,%0" | ||
48 | :"=r" (word) | ||
49 | :"0" (word),"i" (i)); | ||
50 | return word; | ||
51 | } //box | ||
52 | asm ("rorl %%cl,%0" | ||
53 | :"=r" (word) | ||
54 | :"0" (word),"c" (i)); | ||
55 | return word; | ||
56 | } | ||
57 | |||
58 | /******************************************************************************/ | ||
59 | #else | ||
60 | |||
61 | /* rotates the hard way */ | ||
62 | #define ROL(x, y) \ | ||
63 | ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | \ | ||
64 | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & \ | ||
65 | 0xFFFFFFFFUL) | ||
66 | #define ROR(x, y) \ | ||
67 | ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \ | ||
68 | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) | ||
69 | |||
70 | #endif /* 32-bit Rotates */ | ||
71 | /******************************************************************************/ | ||
72 | |||
73 | #ifdef HAVE_NATIVE_INT64 | ||
74 | #ifdef _MSC_VER | ||
75 | #define CONST64(n) n ## ui64 | ||
76 | #else | ||
77 | #define CONST64(n) n ## ULL | ||
78 | #endif | ||
79 | #endif | ||
80 | |||
81 | /******************************************************************************/ | ||
82 | /* | ||
83 | Endian helper macros | ||
84 | */ | ||
85 | #if defined (ENDIAN_NEUTRAL) | ||
86 | #define STORE32L(x, y) { \ | ||
87 | (y)[3] = (unsigned char)(((x)>>24)&255); \ | ||
88 | (y)[2] = (unsigned char)(((x)>>16)&255); \ | ||
89 | (y)[1] = (unsigned char)(((x)>>8)&255); \ | ||
90 | (y)[0] = (unsigned char)((x)&255); \ | ||
91 | } | ||
92 | |||
93 | #define LOAD32L(x, y) { \ | ||
94 | x = ((unsigned long)((y)[3] & 255)<<24) | \ | ||
95 | ((unsigned long)((y)[2] & 255)<<16) | \ | ||
96 | ((unsigned long)((y)[1] & 255)<<8) | \ | ||
97 | ((unsigned long)((y)[0] & 255)); \ | ||
98 | } | ||
99 | |||
100 | #define STORE64L(x, y) { \ | ||
101 | (y)[7] = (unsigned char)(((x)>>56)&255); \ | ||
102 | (y)[6] = (unsigned char)(((x)>>48)&255); \ | ||
103 | (y)[5] = (unsigned char)(((x)>>40)&255); \ | ||
104 | (y)[4] = (unsigned char)(((x)>>32)&255); \ | ||
105 | (y)[3] = (unsigned char)(((x)>>24)&255); \ | ||
106 | (y)[2] = (unsigned char)(((x)>>16)&255); \ | ||
107 | (y)[1] = (unsigned char)(((x)>>8)&255); \ | ||
108 | (y)[0] = (unsigned char)((x)&255); \ | ||
109 | } | ||
110 | |||
111 | #define LOAD64L(x, y) { \ | ||
112 | x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \ | ||
113 | (((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \ | ||
114 | (((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \ | ||
115 | (((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ | ||
116 | } | ||
117 | |||
118 | #define STORE32H(x, y) { \ | ||
119 | (y)[0] = (unsigned char)(((x)>>24)&255); \ | ||
120 | (y)[1] = (unsigned char)(((x)>>16)&255); \ | ||
121 | (y)[2] = (unsigned char)(((x)>>8)&255); \ | ||
122 | (y)[3] = (unsigned char)((x)&255); \ | ||
123 | } | ||
124 | |||
125 | #define LOAD32H(x, y) { \ | ||
126 | x = ((unsigned long)((y)[0] & 255)<<24) | \ | ||
127 | ((unsigned long)((y)[1] & 255)<<16) | \ | ||
128 | ((unsigned long)((y)[2] & 255)<<8) | \ | ||
129 | ((unsigned long)((y)[3] & 255)); \ | ||
130 | } | ||
131 | |||
132 | #define STORE64H(x, y) { \ | ||
133 | (y)[0] = (unsigned char)(((x)>>56)&255); \ | ||
134 | (y)[1] = (unsigned char)(((x)>>48)&255); \ | ||
135 | (y)[2] = (unsigned char)(((x)>>40)&255); \ | ||
136 | (y)[3] = (unsigned char)(((x)>>32)&255); \ | ||
137 | (y)[4] = (unsigned char)(((x)>>24)&255); \ | ||
138 | (y)[5] = (unsigned char)(((x)>>16)&255); \ | ||
139 | (y)[6] = (unsigned char)(((x)>>8)&255); \ | ||
140 | (y)[7] = (unsigned char)((x)&255); \ | ||
141 | } | ||
142 | |||
143 | #define LOAD64H(x, y) { \ | ||
144 | x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \ | ||
145 | (((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \ | ||
146 | (((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \ | ||
147 | (((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); \ | ||
148 | } | ||
149 | |||
150 | #endif /* ENDIAN_NEUTRAL */ | ||
151 | |||
152 | #ifdef ENDIAN_LITTLE | ||
153 | #define STORE32H(x, y) { \ | ||
154 | (y)[0] = (unsigned char)(((x)>>24)&255); \ | ||
155 | (y)[1] = (unsigned char)(((x)>>16)&255); \ | ||
156 | (y)[2] = (unsigned char)(((x)>>8)&255); \ | ||
157 | (y)[3] = (unsigned char)((x)&255); \ | ||
158 | } | ||
159 | |||
160 | #define LOAD32H(x, y) { \ | ||
161 | x = ((unsigned long)((y)[0] & 255)<<24) | \ | ||
162 | ((unsigned long)((y)[1] & 255)<<16) | \ | ||
163 | ((unsigned long)((y)[2] & 255)<<8) | \ | ||
164 | ((unsigned long)((y)[3] & 255)); \ | ||
165 | } | ||
166 | |||
167 | #define STORE64H(x, y) { \ | ||
168 | (y)[0] = (unsigned char)(((x)>>56)&255); \ | ||
169 | (y)[1] = (unsigned char)(((x)>>48)&255); \ | ||
170 | (y)[2] = (unsigned char)(((x)>>40)&255); \ | ||
171 | (y)[3] = (unsigned char)(((x)>>32)&255); \ | ||
172 | (y)[4] = (unsigned char)(((x)>>24)&255); \ | ||
173 | (y)[5] = (unsigned char)(((x)>>16)&255); \ | ||
174 | (y)[6] = (unsigned char)(((x)>>8)&255); \ | ||
175 | (y)[7] = (unsigned char)((x)&255); \ | ||
176 | } | ||
177 | |||
178 | #define LOAD64H(x, y) { \ | ||
179 | x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \ | ||
180 | (((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \ | ||
181 | (((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \ | ||
182 | (((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); } | ||
183 | |||
184 | #ifdef ENDIAN_32BITWORD | ||
185 | #define STORE32L(x, y) { \ | ||
186 | unsigned long __t = (x); memcpy(y, &__t, 4); \ | ||
187 | } | ||
188 | |||
189 | #define LOAD32L(x, y) memcpy(&(x), y, 4); | ||
190 | |||
191 | #define STORE64L(x, y) { \ | ||
192 | (y)[7] = (unsigned char)(((x)>>56)&255); \ | ||
193 | (y)[6] = (unsigned char)(((x)>>48)&255); \ | ||
194 | (y)[5] = (unsigned char)(((x)>>40)&255); \ | ||
195 | (y)[4] = (unsigned char)(((x)>>32)&255); \ | ||
196 | (y)[3] = (unsigned char)(((x)>>24)&255); \ | ||
197 | (y)[2] = (unsigned char)(((x)>>16)&255); \ | ||
198 | (y)[1] = (unsigned char)(((x)>>8)&255); \ | ||
199 | (y)[0] = (unsigned char)((x)&255); \ | ||
200 | } | ||
201 | |||
202 | #define LOAD64L(x, y) { \ | ||
203 | x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \ | ||
204 | (((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \ | ||
205 | (((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \ | ||
206 | (((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ | ||
207 | } | ||
208 | |||
209 | #else /* 64-bit words then */ | ||
210 | #define STORE32L(x, y) \ | ||
211 | { unsigned long __t = (x); memcpy(y, &__t, 4); } | ||
212 | |||
213 | #define LOAD32L(x, y) \ | ||
214 | { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } | ||
215 | |||
216 | #define STORE64L(x, y) \ | ||
217 | { uint64 __t = (x); memcpy(y, &__t, 8); } | ||
218 | |||
219 | #define LOAD64L(x, y) \ | ||
220 | { memcpy(&(x), y, 8); } | ||
221 | |||
222 | #endif /* ENDIAN_64BITWORD */ | ||
223 | #endif /* ENDIAN_LITTLE */ | ||
224 | |||
225 | #ifdef ENDIAN_BIG | ||
226 | #define STORE32L(x, y) { \ | ||
227 | (y)[3] = (unsigned char)(((x)>>24)&255); \ | ||
228 | (y)[2] = (unsigned char)(((x)>>16)&255); \ | ||
229 | (y)[1] = (unsigned char)(((x)>>8)&255); \ | ||
230 | (y)[0] = (unsigned char)((x)&255); \ | ||
231 | } | ||
232 | |||
233 | #define LOAD32L(x, y) { \ | ||
234 | x = ((unsigned long)((y)[3] & 255)<<24) | \ | ||
235 | ((unsigned long)((y)[2] & 255)<<16) | \ | ||
236 | ((unsigned long)((y)[1] & 255)<<8) | \ | ||
237 | ((unsigned long)((y)[0] & 255)); \ | ||
238 | } | ||
239 | |||
240 | #define STORE64L(x, y) { \ | ||
241 | (y)[7] = (unsigned char)(((x)>>56)&255); \ | ||
242 | (y)[6] = (unsigned char)(((x)>>48)&255); \ | ||
243 | (y)[5] = (unsigned char)(((x)>>40)&255); \ | ||
244 | (y)[4] = (unsigned char)(((x)>>32)&255); \ | ||
245 | (y)[3] = (unsigned char)(((x)>>24)&255); \ | ||
246 | (y)[2] = (unsigned char)(((x)>>16)&255); \ | ||
247 | (y)[1] = (unsigned char)(((x)>>8)&255); \ | ||
248 | (y)[0] = (unsigned char)((x)&255); \ | ||
249 | } | ||
250 | |||
251 | #define LOAD64L(x, y) { \ | ||
252 | x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48) | \ | ||
253 | (((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32) | \ | ||
254 | (((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16) | \ | ||
255 | (((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ | ||
256 | } | ||
257 | |||
258 | #ifdef ENDIAN_32BITWORD | ||
259 | #define STORE32H(x, y) \ | ||
260 | { unsigned int __t = (x); memcpy(y, &__t, 4); } | ||
261 | |||
262 | #define LOAD32H(x, y) memcpy(&(x), y, 4); | ||
263 | |||
264 | #define STORE64H(x, y) { \ | ||
265 | (y)[0] = (unsigned char)(((x)>>56)&255); \ | ||
266 | (y)[1] = (unsigned char)(((x)>>48)&255); \ | ||
267 | (y)[2] = (unsigned char)(((x)>>40)&255); \ | ||
268 | (y)[3] = (unsigned char)(((x)>>32)&255); \ | ||
269 | (y)[4] = (unsigned char)(((x)>>24)&255); \ | ||
270 | (y)[5] = (unsigned char)(((x)>>16)&255); \ | ||
271 | (y)[6] = (unsigned char)(((x)>>8)&255); \ | ||
272 | (y)[7] = (unsigned char)((x)&255); \ | ||
273 | } | ||
274 | |||
275 | #define LOAD64H(x, y) { \ | ||
276 | x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48)| \ | ||
277 | (((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32)| \ | ||
278 | (((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16)| \ | ||
279 | (((uint64)((y)[6] & 255))<<8)| (((uint64)((y)[7] & 255))); \ | ||
280 | } | ||
281 | |||
282 | #else /* 64-bit words then */ | ||
283 | |||
284 | #define STORE32H(x, y) \ | ||
285 | { unsigned long __t = (x); memcpy(y, &__t, 4); } | ||
286 | |||
287 | #define LOAD32H(x, y) \ | ||
288 | { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } | ||
289 | |||
290 | #define STORE64H(x, y) \ | ||
291 | { uint64 __t = (x); memcpy(y, &__t, 8); } | ||
292 | |||
293 | #define LOAD64H(x, y) \ | ||
294 | { memcpy(&(x), y, 8); } | ||
295 | |||
296 | #endif /* ENDIAN_64BITWORD */ | ||
297 | #endif /* ENDIAN_BIG */ | ||
298 | |||
299 | #ifdef HAVE_NATIVE_INT64 | ||
300 | #define ROL64c(x, y) \ | ||
301 | ( (((x)<<((uint64)(y)&63)) | \ | ||
302 | (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) | ||
303 | |||
304 | #define ROR64c(x, y) \ | ||
305 | ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)(y)&CONST64(63))) | \ | ||
306 | ((x)<<((uint64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) | ||
307 | #endif /* HAVE_NATIVE_INT64 */ | ||
308 | /******************************************************************************/ | ||
309 | |||
310 | |||
311 | |||
312 | /* The part below is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/. | ||
313 | * Changes are flagged with //bbox | ||
314 | */ | ||
315 | |||
316 | /** | ||
317 | * @file symmetric.h | ||
318 | * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) | ||
319 | * | ||
320 | * Header for internal symmetric key cryptography support. | ||
321 | */ | ||
322 | /* | ||
323 | * Copyright (c) 2013-2015 INSIDE Secure Corporation | ||
324 | * Copyright (c) PeerSec Networks, 2002-2011 | ||
325 | * All Rights Reserved | ||
326 | * | ||
327 | * The latest version of this code is available at http://www.matrixssl.org | ||
328 | * | ||
329 | * This software is open source; you can redistribute it and/or modify | ||
330 | * it under the terms of the GNU General Public License as published by | ||
331 | * the Free Software Foundation; either version 2 of the License, or | ||
332 | * (at your option) any later version. | ||
333 | * | ||
334 | * This General Public License does NOT permit incorporating this software | ||
335 | * into proprietary programs. If you are unable to comply with the GPL, a | ||
336 | * commercial license for this software may be purchased from INSIDE at | ||
337 | * http://www.insidesecure.com/eng/Company/Locations | ||
338 | * | ||
339 | * This program is distributed in WITHOUT ANY WARRANTY; without even the | ||
340 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
341 | * See the GNU General Public License for more details. | ||
342 | * | ||
343 | * You should have received a copy of the GNU General Public License | ||
344 | * along with this program; if not, write to the Free Software | ||
345 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
346 | * http://www.gnu.org/copyleft/gpl.html | ||
347 | */ | ||
348 | /******************************************************************************/ | ||
349 | |||
350 | #ifndef _h_PS_SYMMETRIC | ||
351 | #define _h_PS_SYMMETRIC | ||
352 | |||
353 | /******************************************************************************/ | ||
354 | #ifdef USE_AES | ||
355 | /******************************************************************************/ | ||
356 | |||
357 | |||
358 | #ifndef USE_AES_CBC_EXTERNAL | ||
359 | typedef struct { | ||
360 | uint32 eK[64], dK[64]; | ||
361 | int32 Nr; | ||
362 | } psAesKey_t; | ||
363 | |||
364 | typedef struct { | ||
365 | int32 blocklen; | ||
366 | unsigned char IV[16]; | ||
367 | psAesKey_t key; | ||
368 | #if defined(USE_AES_GCM) || defined(USE_AES_CCM) | ||
369 | unsigned char EncCtr[16]; | ||
370 | unsigned char CtrBlock[16]; | ||
371 | #endif | ||
372 | #ifdef USE_AES_GCM | ||
373 | unsigned char gInit[16]; | ||
374 | uint32 TagTemp[4]; | ||
375 | unsigned char Hash_SubKey[16]; | ||
376 | uint32 ProcessedBitCount[4]; | ||
377 | uint32 InputBufferCount; | ||
378 | uint32 OutputBufferCount; | ||
379 | union | ||
380 | { | ||
381 | unsigned char Buffer[128]; | ||
382 | uint32 BufferAlignment; | ||
383 | } Input; | ||
384 | #endif /* USE_AES_GCM */ | ||
385 | #ifdef USE_AES_CCM | ||
386 | uint32_t ccmTagTemp[16 / sizeof(uint32_t)]; /* 32 */ | ||
387 | union | ||
388 | { | ||
389 | /* Used for formatting IV. */ | ||
390 | uint8_t Temporary[16]; | ||
391 | /* Used for processing Mac. */ | ||
392 | uint8_t Y0[16]; | ||
393 | } u; /* 48 */ | ||
394 | #endif /* USE_AES_CCM */ | ||
395 | } psAesCipher_t; | ||
396 | #endif /* USE_AES_CBC_EXTERNAL */ | ||
397 | |||
398 | #endif /* USE_AES */ | ||
399 | |||
400 | #ifdef USE_IDEA | ||
401 | #define SSL_IDEA_KEY_LEN 16 | ||
402 | #define SSL_IDEA_IV_LEN 8 | ||
403 | #define SSL_IDEA_BLOCK_LEN 8 | ||
404 | |||
405 | typedef struct { | ||
406 | uint16 key_schedule[52]; | ||
407 | } psIdeaKey_t; | ||
408 | |||
409 | typedef struct { | ||
410 | psIdeaKey_t key; | ||
411 | uint32 IV[2]; | ||
412 | short for_encryption; | ||
413 | short inverted; | ||
414 | } idea_CBC; | ||
415 | #endif | ||
416 | /******************************************************************************/ | ||
417 | |||
418 | /******************************************************************************/ | ||
419 | #ifdef USE_SEED | ||
420 | /******************************************************************************/ | ||
421 | #define SSL_SEED_KEY_LEN 16 | ||
422 | #define SSL_SEED_IV_LEN 16 | ||
423 | |||
424 | |||
425 | typedef struct { | ||
426 | uint32 K[32], dK[32]; | ||
427 | } psSeedKey_t; | ||
428 | |||
429 | typedef struct { | ||
430 | int32 blocklen; | ||
431 | unsigned char IV[16]; | ||
432 | psSeedKey_t key; | ||
433 | } seed_CBC; | ||
434 | |||
435 | #endif /* USE_SEED */ | ||
436 | /******************************************************************************/ | ||
437 | |||
438 | /******************************************************************************/ | ||
439 | #if defined(USE_3DES) || defined(USE_DES) | ||
440 | /******************************************************************************/ | ||
441 | #define DES3_KEY_LEN 24 | ||
442 | #define DES3_IV_LEN 8 | ||
443 | #define DES_KEY_LEN 8 | ||
444 | |||
445 | typedef struct { | ||
446 | uint32 ek[3][32], dk[3][32]; | ||
447 | } psDes3Key_t; | ||
448 | |||
449 | /* | ||
450 | A block cipher CBC structure | ||
451 | */ | ||
452 | typedef struct { | ||
453 | int32 blocklen; | ||
454 | unsigned char IV[8]; | ||
455 | psDes3Key_t key; | ||
456 | } des3_CBC; | ||
457 | |||
458 | #endif /* USE_3DES || USE_DES */ | ||
459 | /******************************************************************************/ | ||
460 | |||
461 | /******************************************************************************/ | ||
462 | #ifdef USE_ARC4 | ||
463 | typedef struct { | ||
464 | unsigned char state[256]; | ||
465 | uint32 byteCount; | ||
466 | unsigned char x; | ||
467 | unsigned char y; | ||
468 | } psRc4Key_t; | ||
469 | #endif /* USE_ARC4 */ | ||
470 | /******************************************************************************/ | ||
471 | #ifdef USE_RC2 | ||
472 | typedef struct { | ||
473 | unsigned xkey[64]; | ||
474 | } psRc2Key_t; | ||
475 | |||
476 | typedef struct { | ||
477 | int32 blocklen; | ||
478 | unsigned char IV[8]; | ||
479 | psRc2Key_t key; | ||
480 | } rc2_CBC; | ||
481 | #endif /* USE_RC2 */ | ||
482 | /******************************************************************************/ | ||
483 | /* Universal types and defines */ | ||
484 | /******************************************************************************/ | ||
485 | #define MAXBLOCKSIZE 24 | ||
486 | |||
487 | typedef union { | ||
488 | #ifdef USE_RC2 | ||
489 | rc2_CBC rc2; | ||
490 | #endif | ||
491 | #ifdef USE_ARC4 | ||
492 | psRc4Key_t arc4; | ||
493 | #endif | ||
494 | #ifdef USE_3DES | ||
495 | des3_CBC des3; | ||
496 | #endif | ||
497 | #ifdef USE_AES | ||
498 | psAesCipher_t aes; | ||
499 | #endif | ||
500 | #ifdef USE_SEED | ||
501 | seed_CBC seed; | ||
502 | #endif | ||
503 | #ifdef USE_IDEA | ||
504 | idea_CBC idea; | ||
505 | #endif | ||
506 | } psCipherContext_t; | ||
507 | |||
508 | #define byte(x, n) (((x) >> (8 * (n))) & 255) | ||
509 | |||
510 | #endif /* _h_PS_SYMMETRIC */ | ||
511 | /******************************************************************************/ | ||
diff --git a/networking/wget.c b/networking/wget.c index a5369be22..85a04eaba 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -135,7 +135,8 @@ | |||
135 | 135 | ||
136 | //usage:#define wget_trivial_usage | 136 | //usage:#define wget_trivial_usage |
137 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( | 137 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( |
138 | //usage: "[-cqS] [--spider] [-O FILE] [-o LOGFILE] [--header 'HEADER: VALUE'] [-Y on/off]\n" | 138 | //usage: "[-cqS] [--spider] [-O FILE] [-o LOGFILE] [--header STR]\n" |
139 | //usage: " [--post-data STR | --post-file FILE] [-Y on/off]\n" | ||
139 | /* Since we ignore these opts, we don't show them in --help */ | 140 | /* Since we ignore these opts, we don't show them in --help */ |
140 | /* //usage: " [--no-cache] [--passive-ftp] [-t TRIES]" */ | 141 | /* //usage: " [--no-cache] [--passive-ftp] [-t TRIES]" */ |
141 | /* //usage: " [-nv] [-nc] [-nH] [-np]" */ | 142 | /* //usage: " [-nv] [-nc] [-nH] [-np]" */ |
@@ -148,6 +149,9 @@ | |||
148 | //usage: "Retrieve files via HTTP or FTP\n" | 149 | //usage: "Retrieve files via HTTP or FTP\n" |
149 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( | 150 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( |
150 | //usage: "\n --spider Only check URL existence: $? is 0 if exists" | 151 | //usage: "\n --spider Only check URL existence: $? is 0 if exists" |
152 | //usage: "\n --header STR Add STR (of form 'header: value') to headers" | ||
153 | //usage: "\n --post-data STR Send STR using POST method" | ||
154 | //usage: "\n --post-file FILE Send FILE using POST method" | ||
151 | //usage: IF_FEATURE_WGET_OPENSSL( | 155 | //usage: IF_FEATURE_WGET_OPENSSL( |
152 | //usage: "\n --no-check-certificate Don't validate the server's certificate" | 156 | //usage: "\n --no-check-certificate Don't validate the server's certificate" |
153 | //usage: ) | 157 | //usage: ) |
@@ -244,6 +248,7 @@ struct globals { | |||
244 | char *dir_prefix; | 248 | char *dir_prefix; |
245 | #if ENABLE_FEATURE_WGET_LONG_OPTIONS | 249 | #if ENABLE_FEATURE_WGET_LONG_OPTIONS |
246 | char *post_data; | 250 | char *post_data; |
251 | char *post_file; | ||
247 | char *extra_headers; | 252 | char *extra_headers; |
248 | unsigned char user_headers; /* Headers mentioned by the user */ | 253 | unsigned char user_headers; /* Headers mentioned by the user */ |
249 | #endif | 254 | #endif |
@@ -292,10 +297,13 @@ enum { | |||
292 | WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 297 | WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
293 | WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 298 | WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
294 | WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | 299 | WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, |
300 | WGET_OPT_POST_FILE = (1 << 15) * ENABLE_FEATURE_WGET_LONG_OPTIONS, | ||
295 | /* hijack this bit for other than opts purposes: */ | 301 | /* hijack this bit for other than opts purposes: */ |
296 | WGET_NO_FTRUNCATE = (1 << 31) | 302 | WGET_NO_FTRUNCATE = (1 << 31) |
297 | }; | 303 | }; |
298 | 304 | ||
305 | #define WGET_OPT_POST (WGET_OPT_POST_DATA | WGET_OPT_POST_FILE) | ||
306 | |||
299 | enum { | 307 | enum { |
300 | PROGRESS_START = -1, | 308 | PROGRESS_START = -1, |
301 | PROGRESS_END = 0, | 309 | PROGRESS_END = 0, |
@@ -1246,7 +1254,7 @@ static void download_one_url(const char *url) | |||
1246 | target.path); | 1254 | target.path); |
1247 | } else { | 1255 | } else { |
1248 | SENDFMT(sfp, "%s /%s HTTP/1.1\r\n", | 1256 | SENDFMT(sfp, "%s /%s HTTP/1.1\r\n", |
1249 | (option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET", | 1257 | (option_mask32 & WGET_OPT_POST) ? "POST" : "GET", |
1250 | target.path); | 1258 | target.path); |
1251 | } | 1259 | } |
1252 | if (!USR_HEADER_HOST) | 1260 | if (!USR_HEADER_HOST) |
@@ -1279,7 +1287,13 @@ static void download_one_url(const char *url) | |||
1279 | fputs(G.extra_headers, sfp); | 1287 | fputs(G.extra_headers, sfp); |
1280 | } | 1288 | } |
1281 | 1289 | ||
1282 | if (option_mask32 & WGET_OPT_POST_DATA) { | 1290 | if (option_mask32 & WGET_OPT_POST_FILE) { |
1291 | int fd = xopen_stdin(G.post_file); | ||
1292 | G.post_data = xmalloc_read(fd, NULL); | ||
1293 | close(fd); | ||
1294 | } | ||
1295 | |||
1296 | if (G.post_data) { | ||
1283 | SENDFMT(sfp, | 1297 | SENDFMT(sfp, |
1284 | "Content-Type: application/x-www-form-urlencoded\r\n" | 1298 | "Content-Type: application/x-www-form-urlencoded\r\n" |
1285 | "Content-Length: %u\r\n" | 1299 | "Content-Length: %u\r\n" |
@@ -1522,6 +1536,7 @@ IF_DESKTOP( "tries\0" Required_argument "t") | |||
1522 | "post-data\0" Required_argument "\xfe" | 1536 | "post-data\0" Required_argument "\xfe" |
1523 | "spider\0" No_argument "\xfd" | 1537 | "spider\0" No_argument "\xfd" |
1524 | "no-check-certificate\0" No_argument "\xfc" | 1538 | "no-check-certificate\0" No_argument "\xfc" |
1539 | "post-file\0" Required_argument "\xfb" | ||
1525 | /* Ignored (we always use PASV): */ | 1540 | /* Ignored (we always use PASV): */ |
1526 | IF_DESKTOP( "passive-ftp\0" No_argument "\xf0") | 1541 | IF_DESKTOP( "passive-ftp\0" No_argument "\xf0") |
1527 | /* Ignored (we don't support caching) */ | 1542 | /* Ignored (we don't support caching) */ |
@@ -1565,6 +1580,9 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") | |||
1565 | */ | 1580 | */ |
1566 | "\0" | 1581 | "\0" |
1567 | "-1" /* at least one URL */ | 1582 | "-1" /* at least one URL */ |
1583 | IF_FEATURE_WGET_LONG_OPTIONS(":\xfe--\xfb") | ||
1584 | IF_FEATURE_WGET_LONG_OPTIONS(":\xfe--\xfe") | ||
1585 | IF_FEATURE_WGET_LONG_OPTIONS(":\xfb--\xfb") | ||
1568 | IF_FEATURE_WGET_LONG_OPTIONS(":\xff::") /* --header is a list */ | 1586 | IF_FEATURE_WGET_LONG_OPTIONS(":\xff::") /* --header is a list */ |
1569 | LONGOPTS | 1587 | LONGOPTS |
1570 | , &G.fname_out, &G.fname_log, &G.dir_prefix, | 1588 | , &G.fname_out, &G.fname_log, &G.dir_prefix, |
@@ -1574,6 +1592,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") | |||
1574 | NULL /* -n[ARG] */ | 1592 | NULL /* -n[ARG] */ |
1575 | IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist) | 1593 | IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist) |
1576 | IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data) | 1594 | IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data) |
1595 | IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_file) | ||
1577 | ); | 1596 | ); |
1578 | #if 0 /* option bits debug */ | 1597 | #if 0 /* option bits debug */ |
1579 | if (option_mask32 & WGET_OPT_RETRIES) bb_error_msg("-t NUM"); | 1598 | if (option_mask32 & WGET_OPT_RETRIES) bb_error_msg("-t NUM"); |
@@ -1582,6 +1601,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") | |||
1582 | if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data"); | 1601 | if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data"); |
1583 | if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider"); | 1602 | if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider"); |
1584 | if (option_mask32 & WGET_OPT_NO_CHECK_CERT) bb_error_msg("--no-check-certificate"); | 1603 | if (option_mask32 & WGET_OPT_NO_CHECK_CERT) bb_error_msg("--no-check-certificate"); |
1604 | if (option_mask32 & WGET_OPT_POST_FILE) bb_error_msg("--post-file"); | ||
1585 | exit(0); | 1605 | exit(0); |
1586 | #endif | 1606 | #endif |
1587 | argv += optind; | 1607 | argv += optind; |
diff --git a/procps/Config.src b/procps/Config.src index 2b1b8ab11..7fcce98c5 100644 --- a/procps/Config.src +++ b/procps/Config.src | |||
@@ -5,7 +5,12 @@ | |||
5 | 5 | ||
6 | menu "Process Utilities" | 6 | menu "Process Utilities" |
7 | 7 | ||
8 | INSERT | 8 | config FEATURE_FAST_TOP |
9 | bool "Faster /proc scanning code (+100 bytes)" | ||
10 | default n # all "fast or small" options default to small | ||
11 | help | ||
12 | This option makes top and ps ~20% faster (or 20% less CPU hungry), | ||
13 | but code size is slightly bigger. | ||
9 | 14 | ||
10 | config FEATURE_SHOW_THREADS | 15 | config FEATURE_SHOW_THREADS |
11 | bool "Support thread display in ps/pstree/top" | 16 | bool "Support thread display in ps/pstree/top" |
@@ -15,4 +20,6 @@ config FEATURE_SHOW_THREADS | |||
15 | Enables the ps -T option, showing of threads in pstree, | 20 | Enables the ps -T option, showing of threads in pstree, |
16 | and 'h' command in top. | 21 | and 'h' command in top. |
17 | 22 | ||
23 | INSERT | ||
24 | |||
18 | endmenu | 25 | endmenu |
diff --git a/procps/powertop.c b/procps/powertop.c index fc6018b7a..24c2b320f 100644 --- a/procps/powertop.c +++ b/procps/powertop.c | |||
@@ -505,7 +505,7 @@ static void cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, | |||
505 | unsigned int *edx) | 505 | unsigned int *edx) |
506 | { | 506 | { |
507 | /* EAX value specifies what information to return */ | 507 | /* EAX value specifies what information to return */ |
508 | __asm__( | 508 | asm ( |
509 | " pushl %%ebx\n" /* Save EBX */ | 509 | " pushl %%ebx\n" /* Save EBX */ |
510 | " cpuid\n" | 510 | " cpuid\n" |
511 | " movl %%ebx, %1\n" /* Save content of EBX */ | 511 | " movl %%ebx, %1\n" /* Save content of EBX */ |
diff --git a/procps/ps.c b/procps/ps.c index 801a6fdf3..4c6e07e8b 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -451,17 +451,19 @@ static void parse_o(char* opt) | |||
451 | opt = comma + 1; | 451 | opt = comma + 1; |
452 | continue; | 452 | continue; |
453 | } | 453 | } |
454 | break; | 454 | // opt points to last spec in comma separated list. |
455 | } | 455 | // This one can have =HEADER part. |
456 | // opt points to last spec in comma separated list. | 456 | new = new_out_t(); |
457 | // This one can have =HEADER part. | 457 | if (equal) |
458 | new = new_out_t(); | 458 | *equal = '\0'; |
459 | if (equal) | 459 | *new = *find_out_spec(opt); |
460 | *equal = '\0'; | 460 | if (!equal) |
461 | *new = *find_out_spec(opt); | 461 | break; |
462 | if (equal) { | 462 | *equal++ = '='; |
463 | *equal = '='; | 463 | new->header = equal; |
464 | new->header = equal + 1; | 464 | comma = strchr(equal, ','); |
465 | if (comma) | ||
466 | *comma = '\0'; | ||
465 | // POSIX: the field widths shall be ... at least as wide as | 467 | // POSIX: the field widths shall be ... at least as wide as |
466 | // the header text (default or overridden value). | 468 | // the header text (default or overridden value). |
467 | // If the header text is null, such as -o user=, | 469 | // If the header text is null, such as -o user=, |
@@ -469,10 +471,12 @@ static void parse_o(char* opt) | |||
469 | // default header text | 471 | // default header text |
470 | if (new->header[0]) { | 472 | if (new->header[0]) { |
471 | new->width = strlen(new->header); | 473 | new->width = strlen(new->header); |
472 | print_header = 1; | ||
473 | } | 474 | } |
474 | } else | 475 | if (!comma) |
475 | print_header = 1; | 476 | break; |
477 | //*comma = ','; /* no, new->header should stay NUL-terminated */ | ||
478 | opt = comma + 1; | ||
479 | } | ||
476 | } | 480 | } |
477 | 481 | ||
478 | static void alloc_line_buffer(void) | 482 | static void alloc_line_buffer(void) |
diff --git a/shell/ash.c b/shell/ash.c index 9214982c1..98da20f8a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -351,19 +351,6 @@ typedef long arith_t; | |||
351 | # error "Do not even bother, ash will not run on NOMMU machine" | 351 | # error "Do not even bother, ash will not run on NOMMU machine" |
352 | #endif | 352 | #endif |
353 | 353 | ||
354 | /* We use a trick to have more optimized code (fewer pointer reloads): | ||
355 | * ash.c: extern struct globals *const ash_ptr_to_globals; | ||
356 | * ash_ptr_hack.c: struct globals *ash_ptr_to_globals; | ||
357 | * This way, compiler in ash.c knows the pointer can not change. | ||
358 | * | ||
359 | * However, this may break on weird arches or toolchains. In this case, | ||
360 | * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable | ||
361 | * this optimization. | ||
362 | */ | ||
363 | #ifndef BB_GLOBAL_CONST | ||
364 | # define BB_GLOBAL_CONST const | ||
365 | #endif | ||
366 | |||
367 | #if ENABLE_PLATFORM_MINGW32 | 354 | #if ENABLE_PLATFORM_MINGW32 |
368 | # define FORKSHELL_DEBUG 0 | 355 | # define FORKSHELL_DEBUG 0 |
369 | 356 | ||
@@ -693,8 +680,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
693 | #endif | 680 | #endif |
694 | 681 | ||
695 | #define INIT_G_misc() do { \ | 682 | #define INIT_G_misc() do { \ |
696 | (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ | 683 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \ |
697 | barrier(); \ | ||
698 | savestatus = -1; \ | 684 | savestatus = -1; \ |
699 | curdir = nullstr; \ | 685 | curdir = nullstr; \ |
700 | physdir = nullstr; \ | 686 | physdir = nullstr; \ |
@@ -1783,8 +1769,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack; | |||
1783 | #define g_stacknleft (G_memstack.g_stacknleft) | 1769 | #define g_stacknleft (G_memstack.g_stacknleft) |
1784 | #define stackbase (G_memstack.stackbase ) | 1770 | #define stackbase (G_memstack.stackbase ) |
1785 | #define INIT_G_memstack() do { \ | 1771 | #define INIT_G_memstack() do { \ |
1786 | (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \ | 1772 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \ |
1787 | barrier(); \ | ||
1788 | g_stackp = &stackbase; \ | 1773 | g_stackp = &stackbase; \ |
1789 | g_stacknxt = stackbase.space; \ | 1774 | g_stacknxt = stackbase.space; \ |
1790 | g_stacknleft = MINSIZE; \ | 1775 | g_stacknleft = MINSIZE; \ |
@@ -2445,8 +2430,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; | |||
2445 | #endif | 2430 | #endif |
2446 | #define INIT_G_var() do { \ | 2431 | #define INIT_G_var() do { \ |
2447 | unsigned i; \ | 2432 | unsigned i; \ |
2448 | (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \ | 2433 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \ |
2449 | barrier(); \ | ||
2450 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ | 2434 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ |
2451 | varinit[i].flags = varinit_data[i].flags; \ | 2435 | varinit[i].flags = varinit_data[i].flags; \ |
2452 | varinit[i].var_text = varinit_data[i].var_text; \ | 2436 | varinit[i].var_text = varinit_data[i].var_text; \ |
@@ -7840,14 +7824,19 @@ subevalvar(char *start, char *str, int strloc, | |||
7840 | if ((unsigned)len > (orig_len - pos)) | 7824 | if ((unsigned)len > (orig_len - pos)) |
7841 | len = orig_len - pos; | 7825 | len = orig_len - pos; |
7842 | 7826 | ||
7843 | for (vstr = startp; pos; vstr++, pos--) { | 7827 | if (!quotes) { |
7844 | if (quotes && (unsigned char)*vstr == CTLESC) | 7828 | loc = mempcpy(startp, startp + pos, len); |
7829 | } else { | ||
7830 | for (vstr = startp; pos != 0; pos--) { | ||
7831 | if ((unsigned char)*vstr == CTLESC) | ||
7832 | vstr++; | ||
7845 | vstr++; | 7833 | vstr++; |
7846 | } | 7834 | } |
7847 | for (loc = startp; len; len--) { | 7835 | for (loc = startp; len != 0; len--) { |
7848 | if (quotes && (unsigned char)*vstr == CTLESC) | 7836 | if ((unsigned char)*vstr == CTLESC) |
7837 | *loc++ = *vstr++; | ||
7849 | *loc++ = *vstr++; | 7838 | *loc++ = *vstr++; |
7850 | *loc++ = *vstr++; | 7839 | } |
7851 | } | 7840 | } |
7852 | *loc = '\0'; | 7841 | *loc = '\0'; |
7853 | goto out; | 7842 | goto out; |
@@ -7901,7 +7890,7 @@ subevalvar(char *start, char *str, int strloc, | |||
7901 | #if BASH_PATTERN_SUBST | 7890 | #if BASH_PATTERN_SUBST |
7902 | workloc = expdest - (char *)stackblock(); | 7891 | workloc = expdest - (char *)stackblock(); |
7903 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { | 7892 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
7904 | size_t no_meta_len; | 7893 | size_t no_meta_len, first_escaped; |
7905 | int len; | 7894 | int len; |
7906 | char *idx, *end; | 7895 | char *idx, *end; |
7907 | 7896 | ||
@@ -7919,28 +7908,34 @@ subevalvar(char *start, char *str, int strloc, | |||
7919 | if (str[0] == '\0') | 7908 | if (str[0] == '\0') |
7920 | goto out1; | 7909 | goto out1; |
7921 | 7910 | ||
7922 | no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str); | 7911 | first_escaped = (str[0] == '\\' && str[1]); |
7912 | /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" | ||
7913 | * as literal too (as it is semi-common, and easy to accomodate | ||
7914 | * by just using str + 1). | ||
7915 | */ | ||
7916 | no_meta_len = strpbrk(str + first_escaped * 2, "*?[\\") ? 0 : strlen(str); | ||
7923 | len = 0; | 7917 | len = 0; |
7924 | idx = startp; | 7918 | idx = startp; |
7925 | end = str - 1; | 7919 | end = str - 1; |
7926 | while (idx <= end) { | 7920 | while (idx <= end) { |
7927 | try_to_match: | 7921 | try_to_match: |
7928 | if (no_meta_len == 0) { | 7922 | if (no_meta_len == 0) { |
7929 | /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ | 7923 | /* pattern has meta chars, have to glob */ |
7930 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); | 7924 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); |
7931 | } else { | 7925 | } else { |
7932 | /* Testcase for very slow replace (performs about 22k replaces): | 7926 | /* Testcase for very slow replace (performs about 22k replaces): |
7933 | * x=:::::::::::::::::::::: | 7927 | * x=:::::::::::::::::::::: |
7934 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 7928 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
7935 | * echo "${x//:/|}" | 7929 | * echo "${x//:/|}" |
7930 | * To test "first_escaped" logic, replace : with *. | ||
7936 | */ | 7931 | */ |
7937 | if (strncmp(rmesc, str, no_meta_len) != 0) | 7932 | if (strncmp(rmesc, str + first_escaped, no_meta_len - first_escaped) != 0) |
7938 | goto no_match; | 7933 | goto no_match; |
7939 | loc = idx; | 7934 | loc = idx; |
7940 | if (!quotes) { | 7935 | if (!quotes) { |
7941 | loc += no_meta_len; | 7936 | loc += no_meta_len - first_escaped; |
7942 | } else { | 7937 | } else { |
7943 | size_t n = no_meta_len; | 7938 | size_t n = no_meta_len - first_escaped; |
7944 | do { | 7939 | do { |
7945 | if ((unsigned char)*loc == CTLESC) | 7940 | if ((unsigned char)*loc == CTLESC) |
7946 | loc++; | 7941 | loc++; |
@@ -11811,14 +11806,14 @@ static void freestrings(struct strpush *sp) | |||
11811 | INT_OFF; | 11806 | INT_OFF; |
11812 | do { | 11807 | do { |
11813 | struct strpush *psp; | 11808 | struct strpush *psp; |
11814 | 11809 | #if ENABLE_ASH_ALIAS | |
11815 | if (sp->ap) { | 11810 | if (sp->ap) { |
11816 | sp->ap->flag &= ~ALIASINUSE; | 11811 | sp->ap->flag &= ~ALIASINUSE; |
11817 | if (sp->ap->flag & ALIASDEAD) { | 11812 | if (sp->ap->flag & ALIASDEAD) { |
11818 | unalias(sp->ap->name); | 11813 | unalias(sp->ap->name); |
11819 | } | 11814 | } |
11820 | } | 11815 | } |
11821 | 11816 | #endif | |
11822 | psp = sp; | 11817 | psp = sp; |
11823 | sp = sp->spfree; | 11818 | sp = sp->spfree; |
11824 | 11819 | ||
@@ -15497,7 +15492,7 @@ init(void) | |||
15497 | 15492 | ||
15498 | 15493 | ||
15499 | //usage:#define ash_trivial_usage | 15494 | //usage:#define ash_trivial_usage |
15500 | //usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" | 15495 | //usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]" |
15501 | //////// comes from ^^^^^^^^^^optletters | 15496 | //////// comes from ^^^^^^^^^^optletters |
15502 | //usage:#define ash_full_usage "\n\n" | 15497 | //usage:#define ash_full_usage "\n\n" |
15503 | //usage: "Unix shell interpreter" | 15498 | //usage: "Unix shell interpreter" |
@@ -15764,13 +15759,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
15764 | } | 15759 | } |
15765 | state2: | 15760 | state2: |
15766 | state = 3; | 15761 | state = 3; |
15767 | if ( | 15762 | if (iflag |
15768 | #if ENABLE_PLATFORM_POSIX | 15763 | #if ENABLE_PLATFORM_POSIX |
15769 | #ifndef linux | 15764 | #ifndef linux |
15770 | getuid() == geteuid() && getgid() == getegid() && | 15765 | && getuid() == geteuid() && getgid() == getegid() |
15771 | #endif | 15766 | #endif |
15772 | #endif | 15767 | #endif |
15773 | iflag | ||
15774 | ) { | 15768 | ) { |
15775 | const char *shinit = lookupvar("ENV"); | 15769 | const char *shinit = lookupvar("ENV"); |
15776 | if (shinit != NULL && *shinit != '\0') | 15770 | if (shinit != NULL && *shinit != '\0') |
diff --git a/shell/ash_test/ash-arith/arith-postinc.right b/shell/ash_test/ash-arith/arith-postinc.right index c95ce02bf..5cd4ba6b4 100644 --- a/shell/ash_test/ash-arith/arith-postinc.right +++ b/shell/ash_test/ash-arith/arith-postinc.right | |||
@@ -2,4 +2,7 @@ | |||
2 | 1 1 | 2 | 1 1 |
3 | 1 1 | 3 | 1 1 |
4 | 1 1 | 4 | 1 1 |
5 | 6 6 | ||
6 | 7 7 | ||
7 | 7 7 | ||
5 | Ok:0 | 8 | Ok:0 |
diff --git a/shell/ash_test/ash-arith/arith-postinc.tests b/shell/ash_test/ash-arith/arith-postinc.tests index 3fd9bfed5..f2ae778df 100755 --- a/shell/ash_test/ash-arith/arith-postinc.tests +++ b/shell/ash_test/ash-arith/arith-postinc.tests | |||
@@ -2,4 +2,8 @@ echo 1 $((0++1)) | |||
2 | echo 1 $((0--1)) | 2 | echo 1 $((0--1)) |
3 | x=-1; echo 1 $((0-$x)) | 3 | x=-1; echo 1 $((0-$x)) |
4 | x=+1; echo 1 $((0+$x)) | 4 | x=+1; echo 1 $((0+$x)) |
5 | a=3 | ||
6 | echo 6 $((a+++3)) # a++ + 3 | ||
7 | echo 7 $(((a)+++3)) # a + + + 3 | ||
8 | echo 7 $(((a)+++3)) # a + + + 3 | ||
5 | echo Ok:$? | 9 | echo Ok:$? |
diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 6936f1269..61fcab55e 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right | |||
@@ -43,40 +43,60 @@ Format: 'expected actual' | |||
43 | 4 4 | 43 | 4 4 |
44 | 29 29 | 44 | 29 29 |
45 | 5 5 | 45 | 5 5 |
46 | unary plus, minus | ||
46 | -4 -4 | 47 | -4 -4 |
47 | 4 4 | 48 | 4 4 |
49 | conditional expressions | ||
48 | 1 1 | 50 | 1 1 |
49 | 32 32 | 51 | 32 32 |
50 | 32 32 | 52 | 32 32 |
51 | 1 1 | 53 | 1 1 |
52 | 1 1 | 54 | 1 1 |
53 | 32 32 | 55 | 32 32 |
56 | check that the unevaluated part of the ternary operator does not do evaluation or assignment | ||
54 | 20 20 | 57 | 20 20 |
55 | 30 30 | 58 | 30 30 |
56 | 20 20 | 59 | 20 20 |
57 | 30 30 | 60 | 30 30 |
58 | ./arith.tests: line 117: arithmetic syntax error | 61 | check precedence of assignment vs. conditional operator |
62 | ./arith.tests: line 116: arithmetic syntax error | ||
63 | check precedence of assignment vs. conditional operator | ||
64 | associativity of assignment-operator operator | ||
59 | 6 6 | 65 | 6 6 |
60 | 6,5,3 6,5,3 | 66 | 6,5,3 6,5,3 |
67 | octal, hex | ||
61 | 263 263 | 68 | 263 263 |
62 | 255 255 | 69 | 255 255 |
63 | 40 40 | 70 | 40 40 |
64 | ./arith.tests: line 163: arithmetic syntax error | 71 | other bases |
65 | ./arith.tests: line 165: divide by zero | 72 | 10 10 |
66 | ./arith.tests: let: line 166: arithmetic syntax error | 73 | 10 10 |
67 | ./arith.tests: line 167: arithmetic syntax error | 74 | 10 10 |
68 | ./arith.tests: let: line 168: arithmetic syntax error | 75 | 10 10 |
76 | 10 10 | ||
77 | 10 10 | ||
78 | 36 36 | ||
79 | 36 36 | ||
80 | 62 62 | ||
81 | 63 63 | ||
82 | missing number after base | ||
83 | 0 0 | ||
84 | ./arith.tests: line 162: arithmetic syntax error | ||
85 | ./arith.tests: line 164: divide by zero | ||
86 | ./arith.tests: let: line 165: arithmetic syntax error | ||
87 | ./arith.tests: line 166: arithmetic syntax error | ||
88 | ./arith.tests: let: line 167: arithmetic syntax error | ||
69 | abc | 89 | abc |
70 | def | 90 | def |
71 | ghi | 91 | ghi |
72 | ./arith.tests: line 191: arithmetic syntax error | 92 | ./arith.tests: line 190: arithmetic syntax error |
73 | 16 16 | 93 | 16 16 |
74 | ./arith.tests: line 196: arithmetic syntax error | 94 | ./arith.tests: line 195: arithmetic syntax error |
75 | ./arith.tests: line 197: malformed ?: operator | 95 | ./arith.tests: line 196: malformed ?: operator |
76 | ./arith.tests: line 198: arithmetic syntax error | 96 | ./arith.tests: line 197: arithmetic syntax error |
77 | 9 9 | 97 | 9 9 |
78 | ./arith.tests: line 205: arithmetic syntax error | 98 | ./arith.tests: line 204: arithmetic syntax error |
79 | ./arith.tests: line 208: arithmetic syntax error | 99 | ./arith.tests: line 207: arithmetic syntax error |
80 | 9 9 | 100 | 9 9 |
81 | 9 9 | 101 | 9 9 |
82 | 9 9 | 102 | 9 9 |
@@ -97,14 +117,17 @@ ghi | |||
97 | 3 3 | 117 | 3 3 |
98 | 4 4 | 118 | 4 4 |
99 | 4 4 | 119 | 4 4 |
100 | ./arith.tests: line 257: arithmetic syntax error | 120 | 7 7 |
121 | ./arith.tests: line 256: arithmetic syntax error | ||
122 | ./arith.tests: line 258: arithmetic syntax error | ||
101 | ./arith.tests: line 259: arithmetic syntax error | 123 | ./arith.tests: line 259: arithmetic syntax error |
102 | ./arith.tests: line 260: arithmetic syntax error | 124 | ./arith.tests: line 261: arithmetic syntax error |
103 | ./arith.tests: line 262: arithmetic syntax error | 125 | ./arith.tests: line 262: arithmetic syntax error |
104 | ./arith.tests: line 263: arithmetic syntax error | ||
105 | 4 4 | 126 | 4 4 |
106 | 7 7 | 127 | 7 7 |
107 | -7 -7 | 128 | -7 -7 |
129 | 7 | ||
130 | 7 | ||
108 | ./arith1.sub: line 2: arithmetic syntax error | 131 | ./arith1.sub: line 2: arithmetic syntax error |
109 | ./arith1.sub: line 3: arithmetic syntax error | 132 | ./arith1.sub: line 3: arithmetic syntax error |
110 | ./arith1.sub: line 4: arithmetic syntax error | 133 | ./arith1.sub: line 4: arithmetic syntax error |
@@ -119,11 +142,12 @@ ghi | |||
119 | 2 2 | 142 | 2 2 |
120 | -2 -2 | 143 | -2 -2 |
121 | 1 1 | 144 | 1 1 |
122 | ./arith1.sub: line 37: arithmetic syntax error | 145 | 7 |
123 | ./arith2.sub: line 2: arithmetic syntax error | 146 | 7 |
124 | ./arith2.sub: line 3: arithmetic syntax error | 147 | 7 |
125 | ./arith2.sub: line 4: arithmetic syntax error | 148 | 7 |
126 | ./arith2.sub: line 5: arithmetic syntax error | 149 | 7 |
150 | 7 | ||
127 | 5 5 | 151 | 5 5 |
128 | 1 1 | 152 | 1 1 |
129 | 6 6 | 153 | 6 6 |
@@ -132,11 +156,17 @@ ghi | |||
132 | 1 1 | 156 | 1 1 |
133 | 4 4 | 157 | 4 4 |
134 | 0 0 | 158 | 0 0 |
135 | ./arith2.sub: line 42: arithmetic syntax error | 159 | -7 |
136 | ./arith2.sub: line 47: arithmetic syntax error | 160 | -7 |
161 | 7 | ||
162 | 7 | ||
163 | -7 -7 | ||
164 | -7 -7 | ||
165 | 7 7 | ||
166 | 7 7 | ||
137 | 8 12 | 167 | 8 12 |
138 | ./arith.tests: line 290: arithmetic syntax error | 168 | ./arith.tests: line 289: arithmetic syntax error |
139 | 42 | 169 | 42 |
140 | 42 | 170 | 42 |
141 | 42 | 171 | 42 |
142 | ./arith.tests: line 302: a[b[c]d]=e: not found | 172 | ./arith.tests: line 301: a[b[c]d]=e: not found |
diff --git a/shell/ash_test/ash-arith/arith.tests b/shell/ash_test/ash-arith/arith.tests index d65758e7d..b9cb8ba4c 100755 --- a/shell/ash_test/ash-arith/arith.tests +++ b/shell/ash_test/ash-arith/arith.tests | |||
@@ -75,11 +75,11 @@ echo 4 $(( iv &= 4 )) | |||
75 | echo 29 $(( iv += (jv + 9))) | 75 | echo 29 $(( iv += (jv + 9))) |
76 | echo 5 $(( (iv + 4) % 7 )) | 76 | echo 5 $(( (iv + 4) % 7 )) |
77 | 77 | ||
78 | # unary plus, minus | 78 | echo unary plus, minus |
79 | echo -4 $(( +4 - 8 )) | 79 | echo -4 $(( +4 - 8 )) |
80 | echo 4 $(( -4 + 8 )) | 80 | echo 4 $(( -4 + 8 )) |
81 | 81 | ||
82 | # conditional expressions | 82 | echo conditional expressions |
83 | echo 1 $(( 4<5 ? 1 : 32)) | 83 | echo 1 $(( 4<5 ? 1 : 32)) |
84 | echo 32 $(( 4>5 ? 1 : 32)) | 84 | echo 32 $(( 4>5 ? 1 : 32)) |
85 | echo 32 $(( 4>(2+3) ? 1 : 32)) | 85 | echo 32 $(( 4>(2+3) ? 1 : 32)) |
@@ -87,8 +87,7 @@ echo 1 $(( 4<(2+3) ? 1 : 32)) | |||
87 | echo 1 $(( (2+2)<(2+3) ? 1 : 32)) | 87 | echo 1 $(( (2+2)<(2+3) ? 1 : 32)) |
88 | echo 32 $(( (2+2)>(2+3) ? 1 : 32)) | 88 | echo 32 $(( (2+2)>(2+3) ? 1 : 32)) |
89 | 89 | ||
90 | # check that the unevaluated part of the ternary operator does not do | 90 | echo check that the unevaluated part of the ternary operator does not do evaluation or assignment |
91 | # evaluation or assignment | ||
92 | x=i+=2 | 91 | x=i+=2 |
93 | y=j+=2 | 92 | y=j+=2 |
94 | #ash# declare -i i=1 j=1 | 93 | #ash# declare -i i=1 j=1 |
@@ -109,20 +108,20 @@ echo 20 $((1 ? 20 : (x+=2))) | |||
109 | echo 30 $((0 ? (y+=2) : 30)) | 108 | echo 30 $((0 ? (y+=2) : 30)) |
110 | #ash# echo $i,$y # ash mishandles this | 109 | #ash# echo $i,$y # ash mishandles this |
111 | 110 | ||
112 | # check precedence of assignment vs. conditional operator | 111 | echo check precedence of assignment vs. conditional operator |
113 | # should be an error | 112 | # should be an error |
114 | #ash# declare -i x=2 | 113 | #ash# declare -i x=2 |
115 | x=2 | 114 | x=2 |
116 | #ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: | 115 | #ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: |
117 | ( y=$((1 ? 20 : x+=2)) ) | 116 | ( y=$((1 ? 20 : x+=2)) ) |
118 | 117 | ||
119 | # check precedence of assignment vs. conditional operator | 118 | echo check precedence of assignment vs. conditional operator |
120 | #ash# declare -i x=2 | 119 | #ash# declare -i x=2 |
121 | x=2 | 120 | x=2 |
122 | # ash says "line NNN: syntax error: 0 ? x+=2 : 20" | 121 | # ash says "line NNN: syntax error: 0 ? x+=2 : 20" |
123 | #ash# echo 20 $((0 ? x+=2 : 20)) | 122 | #ash# echo 20 $((0 ? x+=2 : 20)) |
124 | 123 | ||
125 | # associativity of assignment-operator operator | 124 | echo associativity of assignment-operator operator |
126 | #ash# declare -i i=1 j=2 k=3 | 125 | #ash# declare -i i=1 j=2 k=3 |
127 | i=1 | 126 | i=1 |
128 | j=2 | 127 | j=2 |
@@ -130,7 +129,7 @@ k=3 | |||
130 | echo 6 $((i += j += k)) | 129 | echo 6 $((i += j += k)) |
131 | echo 6,5,3 $i,$j,$k | 130 | echo 6,5,3 $i,$j,$k |
132 | 131 | ||
133 | # octal, hex | 132 | echo octal, hex |
134 | echo 263 $(( 0x100 | 007 )) | 133 | echo 263 $(( 0x100 | 007 )) |
135 | echo 255 $(( 0xff )) | 134 | echo 255 $(( 0xff )) |
136 | #ash# echo 255 $(( 16#ff )) | 135 | #ash# echo 255 $(( 16#ff )) |
@@ -139,25 +138,25 @@ echo 255 $(( 0xff )) | |||
139 | 138 | ||
140 | echo 40 $(( 8 ^ 32 )) | 139 | echo 40 $(( 8 ^ 32 )) |
141 | 140 | ||
142 | #ash# # other bases | 141 | echo other bases |
143 | #ash# echo 10 $(( 16#a )) | 142 | echo 10 $(( 16#a )) |
144 | #ash# echo 10 $(( 32#a )) | 143 | echo 10 $(( 32#a )) |
145 | #ash# echo 10 $(( 56#a )) | 144 | echo 10 $(( 56#a )) |
146 | #ash# echo 10 $(( 64#a )) | 145 | echo 10 $(( 64#a )) |
147 | #ash# | 146 | |
148 | #ash# echo 10 $(( 16#A )) | 147 | echo 10 $(( 16#A )) |
149 | #ash# echo 10 $(( 32#A )) | 148 | echo 10 $(( 32#A )) |
150 | #ash# echo 36 $(( 56#A )) | 149 | echo 36 $(( 56#A )) |
151 | #ash# echo 36 $(( 64#A )) | 150 | echo 36 $(( 64#A )) |
152 | #ash# | 151 | |
153 | #ash# echo 62 $(( 64#@ )) | 152 | echo 62 $(( 64#@ )) |
154 | #ash# echo 63 $(( 64#_ )) | 153 | echo 63 $(( 64#_ )) |
155 | 154 | ||
156 | #ash# # weird bases (error) | 155 | #ash# # weird bases (error) |
157 | #ash# echo $(( 3425#56 )) | 156 | #ash# echo $(( 3425#56 )) |
158 | 157 | ||
159 | #ash# # missing number after base | 158 | echo missing number after base |
160 | #ash# echo 0 $(( 2# )) | 159 | echo 0 $(( 2# )) |
161 | 160 | ||
162 | # these should generate errors | 161 | # these should generate errors |
163 | ( echo $(( 7 = 43 )) ) | 162 | ( echo $(( 7 = 43 )) ) |
@@ -252,8 +251,8 @@ echo 3 $x | |||
252 | echo 4 $(( ++x )) | 251 | echo 4 $(( ++x )) |
253 | echo 4 $x | 252 | echo 4 $x |
254 | 253 | ||
255 | # bash 3.2 apparently thinks that ++7 is 7 | 254 | # ++ is not a inc operator on non-variable, it is the + + sequence |
256 | #ash# echo 7 $(( ++7 )) | 255 | echo 7 $(( ++7 )) |
257 | ( echo $(( 7-- )) ) | 256 | ( echo $(( 7-- )) ) |
258 | 257 | ||
259 | ( echo $(( --x=7 )) ) | 258 | ( echo $(( --x=7 )) ) |
@@ -267,9 +266,9 @@ echo 4 $x | |||
267 | echo 7 $(( +7 )) | 266 | echo 7 $(( +7 )) |
268 | echo -7 $(( -7 )) | 267 | echo -7 $(( -7 )) |
269 | 268 | ||
270 | # bash 3.2 apparently thinks that ++7 is 7 | 269 | # ++ is not a inc operator on non-variable, it is the + + sequence |
271 | #ash# echo $(( ++7 )) | 270 | echo $(( ++7 )) |
272 | #ash# echo $(( --7 )) | 271 | echo $(( --7 )) |
273 | 272 | ||
274 | ${THIS_SH} ./arith1.sub | 273 | ${THIS_SH} ./arith1.sub |
275 | ${THIS_SH} ./arith2.sub | 274 | ${THIS_SH} ./arith2.sub |
diff --git a/shell/ash_test/ash-arith/arith1.sub b/shell/ash_test/ash-arith/arith1.sub index 80aa99922..a36785c67 100755 --- a/shell/ash_test/ash-arith/arith1.sub +++ b/shell/ash_test/ash-arith/arith1.sub | |||
@@ -35,6 +35,6 @@ echo 1 $a | |||
35 | 35 | ||
36 | #ash# (( ++ )) | 36 | #ash# (( ++ )) |
37 | ( echo $(( +++7 )) ) | 37 | ( echo $(( +++7 )) ) |
38 | # bash 3.2 apparently thinks that ++ +7 is 7 | 38 | # ++ is not a inc operator on non-variable, it is the + + sequence |
39 | #ash# echo $(( ++ + 7 )) | 39 | echo $(( ++ + 7 )) |
40 | #ash# (( -- )) | 40 | #ash# (( -- )) |
diff --git a/shell/ash_test/ash-arith/arith2.sub b/shell/ash_test/ash-arith/arith2.sub index 9105059db..8d7918114 100755 --- a/shell/ash_test/ash-arith/arith2.sub +++ b/shell/ash_test/ash-arith/arith2.sub | |||
@@ -1,4 +1,4 @@ | |||
1 | # bash 3.2 apparently thinks that ++7 is 7 etc | 1 | # ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences |
2 | ( echo $(( --7 )) ) | 2 | ( echo $(( --7 )) ) |
3 | ( echo $(( ++7 )) ) | 3 | ( echo $(( ++7 )) ) |
4 | ( echo $(( -- 7 )) ) | 4 | ( echo $(( -- 7 )) ) |
@@ -37,21 +37,17 @@ echo 4 $(( 4 - -- a )) | |||
37 | echo 0 $a | 37 | echo 0 $a |
38 | 38 | ||
39 | #ash# (( -- )) | 39 | #ash# (( -- )) |
40 | # bash 3.2 apparently thinks that ---7 is -7 | 40 | # -- is not a dec operator on non-variable, it is the - - sequence |
41 | #ash# echo $(( ---7 )) | 41 | echo $(( ---7 )) |
42 | ( echo $(( -- - 7 )) ) | 42 | ( echo $(( -- - 7 )) ) |
43 | 43 | ||
44 | #ash# (( ++ )) | 44 | #ash# (( ++ )) |
45 | # bash 3.2: 7 | 45 | # ++ is not a inc operator on non-variable, it is the + + sequence |
46 | #ash# echo 7 $(( ++7 )) | 46 | echo $(( ++7 )) |
47 | ( echo $(( ++ + 7 )) ) | 47 | ( echo $(( ++ + 7 )) ) |
48 | 48 | ||
49 | # bash 3.2: -7 | 49 | echo -7 $(( ++-7 )) |
50 | #ash# echo -7 $(( ++-7 )) | 50 | echo -7 $(( ++ - 7 )) |
51 | # bash 3.2: -7 | ||
52 | #ash# echo -7 $(( ++ - 7 )) | ||
53 | 51 | ||
54 | # bash 3.2: 7 | 52 | echo 7 $(( +--7 )) |
55 | #ash# echo 7 $(( +--7 )) | 53 | echo 7 $(( -- + 7 )) |
56 | # bash 3.2: 7 | ||
57 | #ash# echo 7 $(( -- + 7 )) | ||
diff --git a/shell/ash_test/ash-comm/comm.right b/shell/ash_test/ash-comm/comm.right new file mode 100644 index 000000000..1d836656f --- /dev/null +++ b/shell/ash_test/ash-comm/comm.right | |||
@@ -0,0 +1,6 @@ | |||
1 | ./SCRIPT.sh: | ||
2 | /proc/N/comm: SCRIPT.sh | ||
3 | exec ./SCRIPT.sh: | ||
4 | /proc/N/comm: SCRIPT.sh | ||
5 | sh ./SCRIPT.sh: | ||
6 | /proc/N/comm: ash | ||
diff --git a/shell/ash_test/ash-comm/comm.tests b/shell/ash_test/ash-comm/comm.tests new file mode 100755 index 000000000..671bfc176 --- /dev/null +++ b/shell/ash_test/ash-comm/comm.tests | |||
@@ -0,0 +1,20 @@ | |||
1 | { | ||
2 | echo "#!$THIS_SH" | ||
3 | echo 'procdir=/proc/$$' | ||
4 | #echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"' | ||
5 | echo 'echo " /proc/N/comm: $(cat $procdir/comm)"' | ||
6 | } >SCRIPT.sh | ||
7 | chmod 755 SCRIPT.sh | ||
8 | |||
9 | # comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y | ||
10 | echo './SCRIPT.sh:' | ||
11 | ./SCRIPT.sh | ||
12 | |||
13 | # comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y | ||
14 | echo 'exec ./SCRIPT.sh:' | ||
15 | (exec ./SCRIPT.sh) | ||
16 | |||
17 | echo 'sh ./SCRIPT.sh:' | ||
18 | $THIS_SH ./SCRIPT.sh | ||
19 | |||
20 | rm SCRIPT.sh | ||
diff --git a/shell/hush.c b/shell/hush.c index 6d472337f..6a27b1634 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -339,7 +339,7 @@ | |||
339 | * therefore we don't show them either. | 339 | * therefore we don't show them either. |
340 | */ | 340 | */ |
341 | //usage:#define hush_trivial_usage | 341 | //usage:#define hush_trivial_usage |
342 | //usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" | 342 | //usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]" |
343 | //usage:#define hush_full_usage "\n\n" | 343 | //usage:#define hush_full_usage "\n\n" |
344 | //usage: "Unix shell interpreter" | 344 | //usage: "Unix shell interpreter" |
345 | 345 | ||
@@ -373,7 +373,7 @@ | |||
373 | # define F_DUPFD_CLOEXEC F_DUPFD | 373 | # define F_DUPFD_CLOEXEC F_DUPFD |
374 | #endif | 374 | #endif |
375 | 375 | ||
376 | #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH) | 376 | #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !ENABLE_SHELL_ASH |
377 | # include "embedded_scripts.h" | 377 | # include "embedded_scripts.h" |
378 | #else | 378 | #else |
379 | # define NUM_SCRIPTS 0 | 379 | # define NUM_SCRIPTS 0 |
@@ -3360,7 +3360,7 @@ static int glob_brace(char *pattern, o_string *o, int n) | |||
3360 | * NEXT points past the terminator of the first element, and REST | 3360 | * NEXT points past the terminator of the first element, and REST |
3361 | * points past the final }. We will accumulate result names from | 3361 | * points past the final }. We will accumulate result names from |
3362 | * recursive runs for each brace alternative in the buffer using | 3362 | * recursive runs for each brace alternative in the buffer using |
3363 | * GLOB_APPEND. */ | 3363 | * GLOB_APPEND. */ |
3364 | 3364 | ||
3365 | p = begin + 1; | 3365 | p = begin + 1; |
3366 | while (1) { | 3366 | while (1) { |
@@ -6311,7 +6311,7 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int | |||
6311 | 6311 | ||
6312 | /* Expanding ARG in ${var+ARG}, ${var-ARG} | 6312 | /* Expanding ARG in ${var+ARG}, ${var-ARG} |
6313 | */ | 6313 | */ |
6314 | static int encode_then_append_var_plusminus(o_string *output, int n, | 6314 | static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n, |
6315 | char *str, int dquoted) | 6315 | char *str, int dquoted) |
6316 | { | 6316 | { |
6317 | struct in_str input; | 6317 | struct in_str input; |
@@ -6472,16 +6472,21 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) | |||
6472 | /* ${var/[/]pattern[/repl]} helpers */ | 6472 | /* ${var/[/]pattern[/repl]} helpers */ |
6473 | static char *strstr_pattern(char *val, const char *pattern, int *size) | 6473 | static char *strstr_pattern(char *val, const char *pattern, int *size) |
6474 | { | 6474 | { |
6475 | int sz = strcspn(pattern, "*?[\\"); | 6475 | int first_escaped = (pattern[0] == '\\' && pattern[1]); |
6476 | if (pattern[sz] == '\0') { | 6476 | /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" |
6477 | * as literal too (as it is semi-common, and easy to accomodate | ||
6478 | * by just using str + 1). | ||
6479 | */ | ||
6480 | int sz = strcspn(pattern + first_escaped * 2, "*?[\\"); | ||
6481 | if ((pattern + first_escaped * 2)[sz] == '\0') { | ||
6477 | /* Optimization for trivial patterns. | 6482 | /* Optimization for trivial patterns. |
6478 | * Testcase for very slow replace (performs about 22k replaces): | 6483 | * Testcase for very slow replace (performs about 22k replaces): |
6479 | * x=:::::::::::::::::::::: | 6484 | * x=:::::::::::::::::::::: |
6480 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 6485 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
6481 | * echo "${x//:/|}" | 6486 | * echo "${x//:/|}" |
6482 | */ | 6487 | */ |
6483 | *size = sz; | 6488 | *size = sz + first_escaped; |
6484 | return strstr(val, pattern); | 6489 | return strstr(val, pattern + first_escaped); |
6485 | } | 6490 | } |
6486 | 6491 | ||
6487 | while (1) { | 6492 | while (1) { |
@@ -10220,7 +10225,7 @@ int hush_main(int argc, char **argv) | |||
10220 | 10225 | ||
10221 | cached_getpid = getpid(); /* for tcsetpgrp() during init */ | 10226 | cached_getpid = getpid(); /* for tcsetpgrp() during init */ |
10222 | G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ | 10227 | G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ |
10223 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ | 10228 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ |
10224 | 10229 | ||
10225 | /* Deal with HUSH_VERSION */ | 10230 | /* Deal with HUSH_VERSION */ |
10226 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); | 10231 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); |
@@ -10351,6 +10356,29 @@ int hush_main(int argc, char **argv) | |||
10351 | /* Well, we cannot just declare interactiveness, | 10356 | /* Well, we cannot just declare interactiveness, |
10352 | * we have to have some stuff (ctty, etc) */ | 10357 | * we have to have some stuff (ctty, etc) */ |
10353 | /* G_interactive_fd++; */ | 10358 | /* G_interactive_fd++; */ |
10359 | //There are a few cases where bash -i -c 'SCRIPT' | ||
10360 | //has visible effect (differs from bash -c 'SCRIPT'): | ||
10361 | //it ignores TERM: | ||
10362 | // bash -i -c 'kill $$; echo ALIVE' | ||
10363 | // ALIVE | ||
10364 | //it resets SIG_INGed HUP to SIG_DFL: | ||
10365 | // trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE' | ||
10366 | // Hangup [the message is not printed by bash, it's the shell which started it] | ||
10367 | //is talkative about jobs and exiting: | ||
10368 | // bash -i -c 'sleep 1 & exit' | ||
10369 | // [1] 16170 | ||
10370 | // exit | ||
10371 | //includes $ENV file (only if run as "sh"): | ||
10372 | // echo last >/tmp/ENV; ENV=/tmp/ENV sh -i -c 'echo HERE' | ||
10373 | // last: cannot open /var/log/wtmp: No such file or directory | ||
10374 | // HERE | ||
10375 | //(under "bash", it's the opposite: it runs $BASH_ENV file only *without* -i). | ||
10376 | // | ||
10377 | //ash -i -c 'sleep 3; sleep 3', on ^C, drops into a prompt instead of exiting | ||
10378 | //(this may be a bug, bash does not do this). | ||
10379 | //(ash -i -c 'sleep 3' won't show this, the last command gets auto-"exec"ed) | ||
10380 | // | ||
10381 | //None of the above feel like useful features people would rely on. | ||
10354 | break; | 10382 | break; |
10355 | case 's': | 10383 | case 's': |
10356 | G.opt_s = 1; | 10384 | G.opt_s = 1; |
@@ -11727,7 +11755,7 @@ static int FAST_FUNC builtin_fg_bg(char **argv) | |||
11727 | /* TODO: bash prints a string representation | 11755 | /* TODO: bash prints a string representation |
11728 | * of job being foregrounded (like "sleep 1 | cat") */ | 11756 | * of job being foregrounded (like "sleep 1 | cat") */ |
11729 | if (argv[0][0] == 'f' && G_saved_tty_pgrp) { | 11757 | if (argv[0][0] == 'f' && G_saved_tty_pgrp) { |
11730 | /* Put the job into the foreground. */ | 11758 | /* Put the job into the foreground. */ |
11731 | tcsetpgrp(G_interactive_fd, pi->pgrp); | 11759 | tcsetpgrp(G_interactive_fd, pi->pgrp); |
11732 | } | 11760 | } |
11733 | 11761 | ||
diff --git a/shell/hush_test/hush-arith/arith-postinc.right b/shell/hush_test/hush-arith/arith-postinc.right index c95ce02bf..5cd4ba6b4 100644 --- a/shell/hush_test/hush-arith/arith-postinc.right +++ b/shell/hush_test/hush-arith/arith-postinc.right | |||
@@ -2,4 +2,7 @@ | |||
2 | 1 1 | 2 | 1 1 |
3 | 1 1 | 3 | 1 1 |
4 | 1 1 | 4 | 1 1 |
5 | 6 6 | ||
6 | 7 7 | ||
7 | 7 7 | ||
5 | Ok:0 | 8 | Ok:0 |
diff --git a/shell/hush_test/hush-arith/arith-postinc.tests b/shell/hush_test/hush-arith/arith-postinc.tests index 3fd9bfed5..f2ae778df 100755 --- a/shell/hush_test/hush-arith/arith-postinc.tests +++ b/shell/hush_test/hush-arith/arith-postinc.tests | |||
@@ -2,4 +2,8 @@ echo 1 $((0++1)) | |||
2 | echo 1 $((0--1)) | 2 | echo 1 $((0--1)) |
3 | x=-1; echo 1 $((0-$x)) | 3 | x=-1; echo 1 $((0-$x)) |
4 | x=+1; echo 1 $((0+$x)) | 4 | x=+1; echo 1 $((0+$x)) |
5 | a=3 | ||
6 | echo 6 $((a+++3)) # a++ + 3 | ||
7 | echo 7 $(((a)+++3)) # a + + + 3 | ||
8 | echo 7 $(((a)+++3)) # a + + + 3 | ||
5 | echo Ok:$? | 9 | echo Ok:$? |
diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index c48e468a5..a8612295e 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right | |||
@@ -70,6 +70,19 @@ octal, hex | |||
70 | 263 263 | 70 | 263 263 |
71 | 255 255 | 71 | 255 255 |
72 | 40 40 | 72 | 40 40 |
73 | other bases | ||
74 | 10 10 | ||
75 | 10 10 | ||
76 | 10 10 | ||
77 | 10 10 | ||
78 | 10 10 | ||
79 | 10 10 | ||
80 | 36 36 | ||
81 | 36 36 | ||
82 | 62 62 | ||
83 | 63 63 | ||
84 | missing number after base | ||
85 | 0 0 | ||
73 | hush: arithmetic syntax error | 86 | hush: arithmetic syntax error |
74 | hush: divide by zero | 87 | hush: divide by zero |
75 | hush: can't execute 'let': No such file or directory | 88 | hush: can't execute 'let': No such file or directory |
@@ -106,6 +119,7 @@ hush: arithmetic syntax error | |||
106 | 3 3 | 119 | 3 3 |
107 | 4 4 | 120 | 4 4 |
108 | 4 4 | 121 | 4 4 |
122 | 7 7 | ||
109 | hush: arithmetic syntax error | 123 | hush: arithmetic syntax error |
110 | hush: arithmetic syntax error | 124 | hush: arithmetic syntax error |
111 | hush: arithmetic syntax error | 125 | hush: arithmetic syntax error |
@@ -114,6 +128,8 @@ hush: arithmetic syntax error | |||
114 | 4 4 | 128 | 4 4 |
115 | 7 7 | 129 | 7 7 |
116 | -7 -7 | 130 | -7 -7 |
131 | 7 | ||
132 | 7 | ||
117 | hush: arithmetic syntax error | 133 | hush: arithmetic syntax error |
118 | hush: arithmetic syntax error | 134 | hush: arithmetic syntax error |
119 | hush: arithmetic syntax error | 135 | hush: arithmetic syntax error |
@@ -128,11 +144,12 @@ hush: arithmetic syntax error | |||
128 | 2 2 | 144 | 2 2 |
129 | -2 -2 | 145 | -2 -2 |
130 | 1 1 | 146 | 1 1 |
131 | hush: arithmetic syntax error | 147 | 7 |
132 | hush: arithmetic syntax error | 148 | 7 |
133 | hush: arithmetic syntax error | 149 | 7 |
134 | hush: arithmetic syntax error | 150 | 7 |
135 | hush: arithmetic syntax error | 151 | 7 |
152 | 7 | ||
136 | 5 5 | 153 | 5 5 |
137 | 1 1 | 154 | 1 1 |
138 | 6 6 | 155 | 6 6 |
@@ -141,8 +158,14 @@ hush: arithmetic syntax error | |||
141 | 1 1 | 158 | 1 1 |
142 | 4 4 | 159 | 4 4 |
143 | 0 0 | 160 | 0 0 |
144 | hush: arithmetic syntax error | 161 | -7 |
145 | hush: arithmetic syntax error | 162 | -7 |
163 | 7 | ||
164 | 7 | ||
165 | -7 -7 | ||
166 | -7 -7 | ||
167 | 7 7 | ||
168 | 7 7 | ||
146 | 8 12 | 169 | 8 12 |
147 | hush: arithmetic syntax error | 170 | hush: arithmetic syntax error |
148 | 42 | 171 | 42 |
diff --git a/shell/hush_test/hush-arith/arith.tests b/shell/hush_test/hush-arith/arith.tests index bc6b341d1..6b707486c 100755 --- a/shell/hush_test/hush-arith/arith.tests +++ b/shell/hush_test/hush-arith/arith.tests | |||
@@ -142,25 +142,25 @@ echo 255 $(( 0xff )) | |||
142 | 142 | ||
143 | echo 40 $(( 8 ^ 32 )) | 143 | echo 40 $(( 8 ^ 32 )) |
144 | 144 | ||
145 | #ash# # other bases | 145 | echo other bases |
146 | #ash# echo 10 $(( 16#a )) | 146 | echo 10 $(( 16#a )) |
147 | #ash# echo 10 $(( 32#a )) | 147 | echo 10 $(( 32#a )) |
148 | #ash# echo 10 $(( 56#a )) | 148 | echo 10 $(( 56#a )) |
149 | #ash# echo 10 $(( 64#a )) | 149 | echo 10 $(( 64#a )) |
150 | #ash# | 150 | |
151 | #ash# echo 10 $(( 16#A )) | 151 | echo 10 $(( 16#A )) |
152 | #ash# echo 10 $(( 32#A )) | 152 | echo 10 $(( 32#A )) |
153 | #ash# echo 36 $(( 56#A )) | 153 | echo 36 $(( 56#A )) |
154 | #ash# echo 36 $(( 64#A )) | 154 | echo 36 $(( 64#A )) |
155 | #ash# | 155 | |
156 | #ash# echo 62 $(( 64#@ )) | 156 | echo 62 $(( 64#@ )) |
157 | #ash# echo 63 $(( 64#_ )) | 157 | echo 63 $(( 64#_ )) |
158 | 158 | ||
159 | #ash# # weird bases (error) | 159 | #ash# # weird bases (error) |
160 | #ash# echo $(( 3425#56 )) | 160 | #ash# echo $(( 3425#56 )) |
161 | 161 | ||
162 | #ash# # missing number after base | 162 | echo missing number after base |
163 | #ash# echo 0 $(( 2# )) | 163 | echo 0 $(( 2# )) |
164 | 164 | ||
165 | # these should generate errors | 165 | # these should generate errors |
166 | ( echo $(( 7 = 43 )) ) | 166 | ( echo $(( 7 = 43 )) ) |
@@ -255,8 +255,8 @@ echo 3 $x | |||
255 | echo 4 $(( ++x )) | 255 | echo 4 $(( ++x )) |
256 | echo 4 $x | 256 | echo 4 $x |
257 | 257 | ||
258 | # bash 3.2 apparently thinks that ++7 is 7 | 258 | # ++ is not a inc operator on non-variable, it is the + + sequence |
259 | #ash# echo 7 $(( ++7 )) | 259 | echo 7 $(( ++7 )) |
260 | ( echo $(( 7-- )) ) | 260 | ( echo $(( 7-- )) ) |
261 | 261 | ||
262 | ( echo $(( --x=7 )) ) | 262 | ( echo $(( --x=7 )) ) |
@@ -270,9 +270,9 @@ echo 4 $x | |||
270 | echo 7 $(( +7 )) | 270 | echo 7 $(( +7 )) |
271 | echo -7 $(( -7 )) | 271 | echo -7 $(( -7 )) |
272 | 272 | ||
273 | # bash 3.2 apparently thinks that ++7 is 7 | 273 | # ++ is not a inc operator on non-variable, it is the + + sequence |
274 | #ash# echo $(( ++7 )) | 274 | echo $(( ++7 )) |
275 | #ash# echo $(( --7 )) | 275 | echo $(( --7 )) |
276 | 276 | ||
277 | ${THIS_SH} ./arith1.sub | 277 | ${THIS_SH} ./arith1.sub |
278 | ${THIS_SH} ./arith2.sub | 278 | ${THIS_SH} ./arith2.sub |
diff --git a/shell/hush_test/hush-arith/arith1.sub b/shell/hush_test/hush-arith/arith1.sub index 80aa99922..a36785c67 100755 --- a/shell/hush_test/hush-arith/arith1.sub +++ b/shell/hush_test/hush-arith/arith1.sub | |||
@@ -35,6 +35,6 @@ echo 1 $a | |||
35 | 35 | ||
36 | #ash# (( ++ )) | 36 | #ash# (( ++ )) |
37 | ( echo $(( +++7 )) ) | 37 | ( echo $(( +++7 )) ) |
38 | # bash 3.2 apparently thinks that ++ +7 is 7 | 38 | # ++ is not a inc operator on non-variable, it is the + + sequence |
39 | #ash# echo $(( ++ + 7 )) | 39 | echo $(( ++ + 7 )) |
40 | #ash# (( -- )) | 40 | #ash# (( -- )) |
diff --git a/shell/hush_test/hush-arith/arith2.sub b/shell/hush_test/hush-arith/arith2.sub index 9105059db..8d7918114 100755 --- a/shell/hush_test/hush-arith/arith2.sub +++ b/shell/hush_test/hush-arith/arith2.sub | |||
@@ -1,4 +1,4 @@ | |||
1 | # bash 3.2 apparently thinks that ++7 is 7 etc | 1 | # ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences |
2 | ( echo $(( --7 )) ) | 2 | ( echo $(( --7 )) ) |
3 | ( echo $(( ++7 )) ) | 3 | ( echo $(( ++7 )) ) |
4 | ( echo $(( -- 7 )) ) | 4 | ( echo $(( -- 7 )) ) |
@@ -37,21 +37,17 @@ echo 4 $(( 4 - -- a )) | |||
37 | echo 0 $a | 37 | echo 0 $a |
38 | 38 | ||
39 | #ash# (( -- )) | 39 | #ash# (( -- )) |
40 | # bash 3.2 apparently thinks that ---7 is -7 | 40 | # -- is not a dec operator on non-variable, it is the - - sequence |
41 | #ash# echo $(( ---7 )) | 41 | echo $(( ---7 )) |
42 | ( echo $(( -- - 7 )) ) | 42 | ( echo $(( -- - 7 )) ) |
43 | 43 | ||
44 | #ash# (( ++ )) | 44 | #ash# (( ++ )) |
45 | # bash 3.2: 7 | 45 | # ++ is not a inc operator on non-variable, it is the + + sequence |
46 | #ash# echo 7 $(( ++7 )) | 46 | echo $(( ++7 )) |
47 | ( echo $(( ++ + 7 )) ) | 47 | ( echo $(( ++ + 7 )) ) |
48 | 48 | ||
49 | # bash 3.2: -7 | 49 | echo -7 $(( ++-7 )) |
50 | #ash# echo -7 $(( ++-7 )) | 50 | echo -7 $(( ++ - 7 )) |
51 | # bash 3.2: -7 | ||
52 | #ash# echo -7 $(( ++ - 7 )) | ||
53 | 51 | ||
54 | # bash 3.2: 7 | 52 | echo 7 $(( +--7 )) |
55 | #ash# echo 7 $(( +--7 )) | 53 | echo 7 $(( -- + 7 )) |
56 | # bash 3.2: 7 | ||
57 | #ash# echo 7 $(( -- + 7 )) | ||
diff --git a/shell/hush_test/hush-comm/comm.right b/shell/hush_test/hush-comm/comm.right new file mode 100644 index 000000000..1b62b617e --- /dev/null +++ b/shell/hush_test/hush-comm/comm.right | |||
@@ -0,0 +1,6 @@ | |||
1 | ./SCRIPT.sh: | ||
2 | /proc/N/comm: SCRIPT.sh | ||
3 | exec ./SCRIPT.sh: | ||
4 | /proc/N/comm: SCRIPT.sh | ||
5 | sh ./SCRIPT.sh: | ||
6 | /proc/N/comm: hush | ||
diff --git a/shell/hush_test/hush-comm/comm.tests b/shell/hush_test/hush-comm/comm.tests new file mode 100755 index 000000000..671bfc176 --- /dev/null +++ b/shell/hush_test/hush-comm/comm.tests | |||
@@ -0,0 +1,20 @@ | |||
1 | { | ||
2 | echo "#!$THIS_SH" | ||
3 | echo 'procdir=/proc/$$' | ||
4 | #echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"' | ||
5 | echo 'echo " /proc/N/comm: $(cat $procdir/comm)"' | ||
6 | } >SCRIPT.sh | ||
7 | chmod 755 SCRIPT.sh | ||
8 | |||
9 | # comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y | ||
10 | echo './SCRIPT.sh:' | ||
11 | ./SCRIPT.sh | ||
12 | |||
13 | # comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y | ||
14 | echo 'exec ./SCRIPT.sh:' | ||
15 | (exec ./SCRIPT.sh) | ||
16 | |||
17 | echo 'sh ./SCRIPT.sh:' | ||
18 | $THIS_SH ./SCRIPT.sh | ||
19 | |||
20 | rm SCRIPT.sh | ||
diff --git a/shell/math.c b/shell/math.c index 2942cdd26..76d22c9bd 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -116,10 +116,6 @@ | |||
116 | #include "libbb.h" | 116 | #include "libbb.h" |
117 | #include "math.h" | 117 | #include "math.h" |
118 | 118 | ||
119 | #define lookupvar (math_state->lookupvar) | ||
120 | #define setvar (math_state->setvar ) | ||
121 | //#define endofname (math_state->endofname) | ||
122 | |||
123 | typedef unsigned char operator; | 119 | typedef unsigned char operator; |
124 | 120 | ||
125 | /* An operator's token id is a bit of a bitfield. The lower 5 bits are the | 121 | /* An operator's token id is a bit of a bitfield. The lower 5 bits are the |
@@ -258,7 +254,7 @@ static const char* | |||
258 | arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) | 254 | arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) |
259 | { | 255 | { |
260 | if (t->var) { | 256 | if (t->var) { |
261 | const char *p = lookupvar(t->var); | 257 | const char *p = math_state->lookupvar(t->var); |
262 | if (p) { | 258 | if (p) { |
263 | remembered_name *cur; | 259 | remembered_name *cur; |
264 | remembered_name cur_save; | 260 | remembered_name cur_save; |
@@ -445,16 +441,15 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
445 | 441 | ||
446 | if (top_of_stack->var == NULL) { | 442 | if (top_of_stack->var == NULL) { |
447 | /* Hmm, 1=2 ? */ | 443 | /* Hmm, 1=2 ? */ |
448 | //TODO: actually, bash allows ++7 but for some reason it evals to 7, not 8 | ||
449 | goto err; | 444 | goto err; |
450 | } | 445 | } |
451 | /* Save to shell variable */ | 446 | /* Save to shell variable */ |
452 | sprintf(buf, ARITH_FMT, rez); | 447 | sprintf(buf, ARITH_FMT, rez); |
453 | setvar(top_of_stack->var, buf); | 448 | math_state->setvar(top_of_stack->var, buf); |
454 | /* After saving, make previous value for v++ or v-- */ | 449 | /* After saving, make previous value for v++ or v-- */ |
455 | if (op == TOK_POST_INC) | 450 | if (op == TOK_POST_INC) |
456 | rez--; | 451 | rez--; |
457 | else if (op == TOK_POST_DEC) | 452 | if (op == TOK_POST_DEC) |
458 | rez++; | 453 | rez++; |
459 | } | 454 | } |
460 | 455 | ||
@@ -607,11 +602,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
607 | const char *p; | 602 | const char *p; |
608 | operator op; | 603 | operator op; |
609 | operator prec; | 604 | operator prec; |
610 | char arithval; | ||
611 | 605 | ||
612 | expr = skip_whitespace(expr); | 606 | expr = skip_whitespace(expr); |
613 | arithval = *expr; | 607 | if (*expr == '\0') { |
614 | if (arithval == '\0') { | ||
615 | if (expr == start_expr) { | 608 | if (expr == start_expr) { |
616 | /* Null expression */ | 609 | /* Null expression */ |
617 | numstack->val = 0; | 610 | numstack->val = 0; |
@@ -628,6 +621,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
628 | * append a closing right paren | 621 | * append a closing right paren |
629 | * and let the loop process it */ | 622 | * and let the loop process it */ |
630 | expr = ptr_to_rparen; | 623 | expr = ptr_to_rparen; |
624 | //bb_error_msg("expr=')'"); | ||
631 | continue; | 625 | continue; |
632 | } | 626 | } |
633 | /* At this point, we're done with the expression */ | 627 | /* At this point, we're done with the expression */ |
@@ -635,19 +629,16 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
635 | /* ...but if there isn't, it's bad */ | 629 | /* ...but if there isn't, it's bad */ |
636 | goto err; | 630 | goto err; |
637 | } | 631 | } |
638 | if (numstack->var) { | ||
639 | /* expression is $((var)) only, lookup now */ | ||
640 | errmsg = arith_lookup_val(math_state, numstack); | ||
641 | } | ||
642 | goto ret; | 632 | goto ret; |
643 | } | 633 | } |
644 | 634 | ||
645 | p = endofname(expr); | 635 | p = endofname(expr); |
646 | if (p != expr) { | 636 | if (p != expr) { |
647 | /* Name */ | 637 | /* Name */ |
648 | size_t var_name_size = (p-expr) + 1; /* +1 for NUL */ | 638 | size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ |
649 | numstackptr->var = alloca(var_name_size); | 639 | numstackptr->var = alloca(var_name_size); |
650 | safe_strncpy(numstackptr->var, expr, var_name_size); | 640 | safe_strncpy(numstackptr->var, expr, var_name_size); |
641 | //bb_error_msg("var:'%s'", numstackptr->var); | ||
651 | expr = p; | 642 | expr = p; |
652 | num: | 643 | num: |
653 | numstackptr->second_val_present = 0; | 644 | numstackptr->second_val_present = 0; |
@@ -656,11 +647,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
656 | continue; | 647 | continue; |
657 | } | 648 | } |
658 | 649 | ||
659 | if (isdigit(arithval)) { | 650 | if (isdigit(*expr)) { |
660 | /* Number */ | 651 | /* Number */ |
661 | numstackptr->var = NULL; | 652 | numstackptr->var = NULL; |
662 | errno = 0; | 653 | errno = 0; |
663 | numstackptr->val = strto_arith_t(expr, (char**) &expr); | 654 | numstackptr->val = strto_arith_t(expr, (char**) &expr); |
655 | //bb_error_msg("val:%lld", numstackptr->val); | ||
664 | if (errno) | 656 | if (errno) |
665 | numstackptr->val = 0; /* bash compat */ | 657 | numstackptr->val = 0; /* bash compat */ |
666 | goto num; | 658 | goto num; |
@@ -668,19 +660,26 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
668 | 660 | ||
669 | /* Should be an operator */ | 661 | /* Should be an operator */ |
670 | 662 | ||
671 | /* Special case: NUM-- and NUM++ are not recognized if NUM | 663 | /* Special case: XYZ--, XYZ++, --XYZ, ++XYZ are recognized |
672 | * is a literal number, not a variable. IOW: | 664 | * only if XYZ is a variable name, not a number or EXPR. IOW: |
673 | * "a+++v" is a++ + v. | 665 | * "a+++v" is a++ + v. |
666 | * "(a)+++7" is ( a ) + + + 7. | ||
674 | * "7+++v" is 7 + ++v, not 7++ + v. | 667 | * "7+++v" is 7 + ++v, not 7++ + v. |
668 | * "--7" is - - 7, not --7. | ||
669 | * "++++a" is + + ++a, not ++ ++a. | ||
675 | */ | 670 | */ |
676 | if (lasttok == TOK_NUM && !numstackptr[-1].var /* number literal */ | 671 | if ((expr[0] == '+' || expr[0] == '-') |
677 | && (expr[0] == '+' || expr[0] == '-') | ||
678 | && (expr[1] == expr[0]) | 672 | && (expr[1] == expr[0]) |
679 | ) { | 673 | ) { |
680 | //bb_error_msg("special %c%c", expr[0], expr[0]); | 674 | if (numstackptr == numstack || !numstackptr[-1].var) { /* not a VAR++ */ |
681 | op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); | 675 | char next = skip_whitespace(expr + 2)[0]; |
682 | expr += 1; | 676 | if (!(isalpha(next) || next == '_')) { /* not a ++VAR */ |
683 | goto tok_found1; | 677 | //bb_error_msg("special %c%c", expr[0], expr[0]); |
678 | op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); | ||
679 | expr++; | ||
680 | goto tok_found1; | ||
681 | } | ||
682 | } | ||
684 | } | 683 | } |
685 | 684 | ||
686 | p = op_tokens; | 685 | p = op_tokens; |
@@ -749,26 +748,40 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
749 | * "applied" in this way. | 748 | * "applied" in this way. |
750 | */ | 749 | */ |
751 | prec = PREC(op); | 750 | prec = PREC(op); |
751 | //bb_error_msg("prec:%02x", prec); | ||
752 | if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { | 752 | if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { |
753 | /* not left paren or unary */ | 753 | /* not left paren or unary */ |
754 | if (lasttok != TOK_NUM) { | 754 | if (lasttok != TOK_NUM) { |
755 | /* binary op must be preceded by a num */ | 755 | /* binary op must be preceded by a num */ |
756 | goto err; | 756 | goto err; |
757 | } | 757 | } |
758 | /* The algorithm employed here is simple: while we don't | ||
759 | * hit an open paren nor the bottom of the stack, pop | ||
760 | * tokens and apply them */ | ||
758 | while (stackptr != stack) { | 761 | while (stackptr != stack) { |
759 | operator prev_op = *--stackptr; | 762 | operator prev_op = *--stackptr; |
760 | if (op == TOK_RPAREN) { | 763 | if (op == TOK_RPAREN) { |
761 | /* The algorithm employed here is simple: while we don't | 764 | //bb_error_msg("op == TOK_RPAREN"); |
762 | * hit an open paren nor the bottom of the stack, pop | ||
763 | * tokens and apply them */ | ||
764 | if (prev_op == TOK_LPAREN) { | 765 | if (prev_op == TOK_LPAREN) { |
766 | //bb_error_msg("prev_op == TOK_LPAREN"); | ||
767 | //bb_error_msg(" %p %p numstackptr[-1].var:'%s'", numstack, numstackptr-1, numstackptr[-1].var); | ||
768 | if (numstackptr[-1].var) { | ||
769 | /* Expression is (var), lookup now */ | ||
770 | errmsg = arith_lookup_val(math_state, &numstackptr[-1]); | ||
771 | if (errmsg) | ||
772 | goto err_with_custom_msg; | ||
773 | /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */ | ||
774 | numstackptr[-1].var = NULL; | ||
775 | } | ||
765 | /* Any operator directly after a | 776 | /* Any operator directly after a |
766 | * close paren should consider itself binary */ | 777 | * close paren should consider itself binary */ |
767 | lasttok = TOK_NUM; | 778 | lasttok = TOK_NUM; |
768 | goto next; | 779 | goto next; |
769 | } | 780 | } |
781 | //bb_error_msg("prev_op != TOK_LPAREN"); | ||
770 | } else { | 782 | } else { |
771 | operator prev_prec = PREC(prev_op); | 783 | operator prev_prec = PREC(prev_op); |
784 | //bb_error_msg("op != TOK_RPAREN"); | ||
772 | fix_assignment_prec(prec); | 785 | fix_assignment_prec(prec); |
773 | fix_assignment_prec(prev_prec); | 786 | fix_assignment_prec(prev_prec); |
774 | if (prev_prec < prec | 787 | if (prev_prec < prec |
@@ -778,6 +791,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
778 | break; | 791 | break; |
779 | } | 792 | } |
780 | } | 793 | } |
794 | //bb_error_msg("arith_apply(prev_op:%02x)", prev_op); | ||
781 | errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); | 795 | errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); |
782 | if (errmsg) | 796 | if (errmsg) |
783 | goto err_with_custom_msg; | 797 | goto err_with_custom_msg; |
@@ -787,6 +801,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
787 | } | 801 | } |
788 | 802 | ||
789 | /* Push this operator to the stack and remember it */ | 803 | /* Push this operator to the stack and remember it */ |
804 | //bb_error_msg("push op:%02x", op); | ||
790 | *stackptr++ = lasttok = op; | 805 | *stackptr++ = lasttok = op; |
791 | next: ; | 806 | next: ; |
792 | } /* while (1) */ | 807 | } /* while (1) */ |
diff --git a/testsuite/realpath.tests b/testsuite/realpath.tests new file mode 100755 index 000000000..0e68e0279 --- /dev/null +++ b/testsuite/realpath.tests | |||
@@ -0,0 +1,45 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # Realpath tests. | ||
4 | # Copyright 2006 by Natanael Copa <n@tanael.org> | ||
5 | # Copyright 2021 by Ron Yorston <rmy@pobox.com> | ||
6 | # Licensed under GPLv2, see file LICENSE in this source tree. | ||
7 | |||
8 | . ./testing.sh | ||
9 | |||
10 | unset LC_ALL | ||
11 | unset LC_MESSAGES | ||
12 | unset LANG | ||
13 | unset LANGUAGE | ||
14 | |||
15 | TESTDIR=realpath_testdir | ||
16 | TESTLINK1="link1" | ||
17 | TESTLINK2="link2" | ||
18 | |||
19 | # create the dir and test files | ||
20 | mkdir -p "./$TESTDIR" | ||
21 | ln -s "./$TESTDIR/not_file" "./$TESTLINK1" | ||
22 | ln -s "./$TESTDIR/not_file/not_dir" "./$TESTLINK2" | ||
23 | |||
24 | # shell's $PWD may leave symlinks unresolved. | ||
25 | # "pwd" may be a built-in and have the same problem. | ||
26 | # External pwd _can't_ have that problem (current dir on Unix is physical). | ||
27 | pwd=`which pwd` | ||
28 | pwd=`$pwd` | ||
29 | testing "realpath on non-existent absolute path 1" "realpath /not_file" "/not_file\n" "" "" | ||
30 | testing "realpath on non-existent absolute path 2" "realpath /not_file/" "/not_file\n" "" "" | ||
31 | testing "realpath on non-existent absolute path 3" "realpath //not_file" "/not_file\n" "" "" | ||
32 | testing "realpath on non-existent absolute path 4" "realpath /not_dir/not_file 2>&1" "realpath: /not_dir/not_file: No such file or directory\n" "" "" | ||
33 | |||
34 | testing "realpath on non-existent local file 1" "realpath $TESTDIR/not_file" "$pwd/$TESTDIR/not_file\n" "" "" | ||
35 | testing "realpath on non-existent local file 2" "realpath $TESTDIR/not_dir/not_file 2>&1" "realpath: $TESTDIR/not_dir/not_file: No such file or directory\n" "" "" | ||
36 | |||
37 | testing "realpath on link to non-existent file 1" "realpath $TESTLINK1" "$pwd/$TESTDIR/not_file\n" "" "" | ||
38 | testing "realpath on link to non-existent file 2" "realpath $TESTLINK2 2>&1" "realpath: $TESTLINK2: No such file or directory\n" "" "" | ||
39 | testing "realpath on link to non-existent file 3" "realpath ./$TESTLINK1" "$pwd/$TESTDIR/not_file\n" "" "" | ||
40 | testing "realpath on link to non-existent file 4" "realpath ./$TESTLINK2 2>&1" "realpath: ./$TESTLINK2: No such file or directory\n" "" "" | ||
41 | |||
42 | # clean up | ||
43 | rm -r "$TESTLINK1" "$TESTLINK2" "$TESTDIR" | ||
44 | |||
45 | exit $((FAILCOUNT <= 255 ? FAILCOUNT : 255)) | ||
diff --git a/testsuite/xxd.tests b/testsuite/xxd.tests index 2e80be5fe..76fa96af9 100755 --- a/testsuite/xxd.tests +++ b/testsuite/xxd.tests | |||
@@ -31,4 +31,10 @@ testing 'xxd -p with 31 NULs' \ | |||
31 | '' \ | 31 | '' \ |
32 | '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' | 32 | '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' |
33 | 33 | ||
34 | testing 'xxd -p -r' \ | ||
35 | 'xxd -p -r' \ | ||
36 | '01234567765432100123456776543210' \ | ||
37 | '' \ | ||
38 | '30313233343536373736353433323130 30313233343536373736353433323130' | ||
39 | |||
34 | exit $FAILCOUNT | 40 | exit $FAILCOUNT |
diff --git a/util-linux/chrt.c b/util-linux/chrt.c index a8701b55f..6799abb2d 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c | |||
@@ -93,7 +93,7 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) | |||
93 | unsigned opt; | 93 | unsigned opt; |
94 | struct sched_param sp; | 94 | struct sched_param sp; |
95 | char *pid_str; | 95 | char *pid_str; |
96 | char *priority = priority; /* for compiler */ | 96 | char *priority = NULL; |
97 | const char *current_new; | 97 | const char *current_new; |
98 | int policy = SCHED_RR; | 98 | int policy = SCHED_RR; |
99 | int ret; | 99 | int ret; |
diff --git a/util-linux/fbset.c b/util-linux/fbset.c index cc5413b40..41cc29f37 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c | |||
@@ -267,7 +267,7 @@ static void ss(uint32_t *x, uint32_t flag, char *buf, const char *what) | |||
267 | * vsync high | 267 | * vsync high |
268 | * endmode | 268 | * endmode |
269 | */ | 269 | */ |
270 | static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, | 270 | static NOINLINE int read_mode_db(struct fb_var_screeninfo *base, const char *fn, |
271 | const char *mode) | 271 | const char *mode) |
272 | { | 272 | { |
273 | char *token[2], *p, *s; | 273 | char *token[2], *p, *s; |
diff --git a/util-linux/fdisk_sun.c b/util-linux/fdisk_sun.c index 66e434833..5b7760e8c 100644 --- a/util-linux/fdisk_sun.c +++ b/util-linux/fdisk_sun.c | |||
@@ -403,7 +403,7 @@ verify_sun_cmp(int *a, int *b) | |||
403 | return -1; | 403 | return -1; |
404 | } | 404 | } |
405 | 405 | ||
406 | static void | 406 | static NOINLINE void |
407 | verify_sun(void) | 407 | verify_sun(void) |
408 | { | 408 | { |
409 | unsigned starts[8], lens[8], start, stop; | 409 | unsigned starts[8], lens[8], start, stop; |
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index fe78f6242..76dada983 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c | |||
@@ -69,7 +69,7 @@ | |||
69 | #define OPT_c (1 << 7) | 69 | #define OPT_c (1 << 7) |
70 | #define OPT_o (1 << 8) | 70 | #define OPT_o (1 << 8) |
71 | 71 | ||
72 | static void reverse(unsigned opt, unsigned cols, const char *filename) | 72 | static void reverse(unsigned opt, const char *filename) |
73 | { | 73 | { |
74 | FILE *fp; | 74 | FILE *fp; |
75 | char *buf; | 75 | char *buf; |
@@ -77,9 +77,9 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
77 | fp = filename ? xfopen_for_read(filename) : stdin; | 77 | fp = filename ? xfopen_for_read(filename) : stdin; |
78 | 78 | ||
79 | while ((buf = xmalloc_fgetline(fp)) != NULL) { | 79 | while ((buf = xmalloc_fgetline(fp)) != NULL) { |
80 | char *p = buf; | 80 | char *p; |
81 | unsigned cnt = cols; | ||
82 | 81 | ||
82 | p = buf; | ||
83 | if (!(opt & OPT_p)) { | 83 | if (!(opt & OPT_p)) { |
84 | /* skip address */ | 84 | /* skip address */ |
85 | while (isxdigit(*p)) p++; | 85 | while (isxdigit(*p)) p++; |
@@ -92,9 +92,9 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
92 | } | 92 | } |
93 | 93 | ||
94 | /* Process hex bytes optionally separated by whitespace */ | 94 | /* Process hex bytes optionally separated by whitespace */ |
95 | do { | 95 | for (;;) { |
96 | uint8_t val, c; | 96 | uint8_t val, c; |
97 | 97 | nibble1: | |
98 | p = skip_whitespace(p); | 98 | p = skip_whitespace(p); |
99 | 99 | ||
100 | c = *p++; | 100 | c = *p++; |
@@ -102,8 +102,19 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
102 | val = c - '0'; | 102 | val = c - '0'; |
103 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') | 103 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') |
104 | val = (c|0x20) - ('a' - 10); | 104 | val = (c|0x20) - ('a' - 10); |
105 | else | 105 | else { |
106 | /* xxd V1.10 is inconsistent here. | ||
107 | * echo -e "31 !3 0a 0a" | xxd -r -p | ||
108 | * is "10<a0>" (no <cr>) - "!" is ignored, | ||
109 | * but | ||
110 | * echo -e "31 !!343434\n30 0a" | xxd -r -p | ||
111 | * is "10<cr>" - "!!" drops rest of the line. | ||
112 | * We will ignore all invalid chars: | ||
113 | */ | ||
114 | if (c != '\0') | ||
115 | goto nibble1; | ||
106 | break; | 116 | break; |
117 | } | ||
107 | val <<= 4; | 118 | val <<= 4; |
108 | 119 | ||
109 | /* Works the same with xxd V1.10: | 120 | /* Works the same with xxd V1.10: |
@@ -111,6 +122,7 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
111 | * echo "31 0 9 32 0a" | xxd -r -p | 122 | * echo "31 0 9 32 0a" | xxd -r -p |
112 | * thus allow whitespace even within the byte: | 123 | * thus allow whitespace even within the byte: |
113 | */ | 124 | */ |
125 | nibble2: | ||
114 | p = skip_whitespace(p); | 126 | p = skip_whitespace(p); |
115 | 127 | ||
116 | c = *p++; | 128 | c = *p++; |
@@ -118,10 +130,23 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
118 | val |= c - '0'; | 130 | val |= c - '0'; |
119 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') | 131 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') |
120 | val |= (c|0x20) - ('a' - 10); | 132 | val |= (c|0x20) - ('a' - 10); |
121 | else | 133 | else { |
122 | break; | 134 | if (c != '\0') { |
135 | /* "...3<not_hex_char>..." ignores both chars */ | ||
136 | goto nibble1; | ||
137 | } | ||
138 | /* Nibbles can join even through newline: | ||
139 | * echo -e "31 3\n2 0a" | xxd -r -p | ||
140 | * is "12<cr>". | ||
141 | */ | ||
142 | free(buf); | ||
143 | p = buf = xmalloc_fgetline(fp); | ||
144 | if (!buf) | ||
145 | break; | ||
146 | goto nibble2; | ||
147 | } | ||
123 | putchar(val); | 148 | putchar(val); |
124 | } while (!(opt & OPT_p) || --cnt != 0); | 149 | } |
125 | free(buf); | 150 | free(buf); |
126 | } | 151 | } |
127 | //fclose(fp); | 152 | //fclose(fp); |
@@ -174,6 +199,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
174 | //BUGGY for /proc/version (unseekable?) | 199 | //BUGGY for /proc/version (unseekable?) |
175 | } | 200 | } |
176 | 201 | ||
202 | if (opt & OPT_r) { | ||
203 | reverse(opt, argv[0]); | ||
204 | } | ||
205 | |||
177 | if (opt & OPT_o) { | 206 | if (opt & OPT_o) { |
178 | /* -o accepts negative numbers too */ | 207 | /* -o accepts negative numbers too */ |
179 | dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0); | 208 | dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0); |
@@ -194,10 +223,6 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
194 | bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " | 223 | bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " |
195 | } | 224 | } |
196 | 225 | ||
197 | if (opt & OPT_r) { | ||
198 | reverse(opt, cols, argv[0]); | ||
199 | } | ||
200 | |||
201 | if (bytes < 1 || bytes >= cols) { | 226 | if (bytes < 1 || bytes >= cols) { |
202 | sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX" | 227 | sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX" |
203 | bb_dump_add(dumper, buf); | 228 | bb_dump_add(dumper, buf); |
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index dbbcbc655..ebdc0c254 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
@@ -82,12 +82,12 @@ | |||
82 | //usage:#define mdev_trivial_usage | 82 | //usage:#define mdev_trivial_usage |
83 | //usage: "[-vS] " IF_FEATURE_MDEV_DAEMON("{ ") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df] }") | 83 | //usage: "[-vS] " IF_FEATURE_MDEV_DAEMON("{ ") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df] }") |
84 | //usage:#define mdev_full_usage "\n\n" | 84 | //usage:#define mdev_full_usage "\n\n" |
85 | //usage: " -v verbose\n" | 85 | //usage: " -v Verbose\n" |
86 | //usage: " -S log to syslog too\n" | 86 | //usage: " -S Log to syslog too\n" |
87 | //usage: " -s scan /sys and populate /dev\n" | 87 | //usage: " -s Scan /sys and populate /dev\n" |
88 | //usage: IF_FEATURE_MDEV_DAEMON( | 88 | //usage: IF_FEATURE_MDEV_DAEMON( |
89 | //usage: " -d daemon, listen on netlink\n" | 89 | //usage: " -d Daemon, listen on netlink\n" |
90 | //usage: " -f stay in foreground\n" | 90 | //usage: " -f Run in foreground\n" |
91 | //usage: ) | 91 | //usage: ) |
92 | //usage: "\n" | 92 | //usage: "\n" |
93 | //usage: "Bare mdev is a kernel hotplug helper. To activate it:\n" | 93 | //usage: "Bare mdev is a kernel hotplug helper. To activate it:\n" |
diff --git a/util-linux/mount.c b/util-linux/mount.c index 44afdbcff..4e65b6b46 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c | |||
@@ -589,7 +589,7 @@ static void append_mount_options(char **oldopts, const char *newopts) | |||
589 | 589 | ||
590 | // Use the mount_options list to parse options into flags. | 590 | // Use the mount_options list to parse options into flags. |
591 | // Also update list of unrecognized options if unrecognized != NULL | 591 | // Also update list of unrecognized options if unrecognized != NULL |
592 | static unsigned long parse_mount_options(char *options, char **unrecognized) | 592 | static unsigned long parse_mount_options(char *options, char **unrecognized, uint32_t *opt) |
593 | { | 593 | { |
594 | unsigned long flags = MS_SILENT; | 594 | unsigned long flags = MS_SILENT; |
595 | 595 | ||
@@ -617,6 +617,11 @@ static unsigned long parse_mount_options(char *options, char **unrecognized) | |||
617 | flags &= fl; | 617 | flags &= fl; |
618 | else | 618 | else |
619 | flags |= fl; | 619 | flags |= fl; |
620 | /* If we see "-o rw" on command line, it's the same as -w: | ||
621 | * "do not try to fall back to RO mounts" | ||
622 | */ | ||
623 | if (fl == ~MS_RDONLY && opt) | ||
624 | (*opt) |= OPT_w; | ||
620 | goto found; | 625 | goto found; |
621 | } | 626 | } |
622 | option_str += opt_len + 1; | 627 | option_str += opt_len + 1; |
@@ -1973,7 +1978,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
1973 | 1978 | ||
1974 | errno = 0; | 1979 | errno = 0; |
1975 | 1980 | ||
1976 | vfsflags = parse_mount_options(mp->mnt_opts, &filteropts); | 1981 | vfsflags = parse_mount_options(mp->mnt_opts, &filteropts, NULL); |
1977 | 1982 | ||
1978 | // Treat fstype "auto" as unspecified | 1983 | // Treat fstype "auto" as unspecified |
1979 | if (mp->mnt_type && strcmp(mp->mnt_type, "auto") == 0) | 1984 | if (mp->mnt_type && strcmp(mp->mnt_type, "auto") == 0) |
@@ -2047,7 +2052,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
2047 | len, share, | 2052 | len, share, |
2048 | share + len + 1 /* "dir1/dir2" */ | 2053 | share + len + 1 /* "dir1/dir2" */ |
2049 | ); | 2054 | ); |
2050 | parse_mount_options(unc, &filteropts); | 2055 | parse_mount_options(unc, &filteropts, NULL); |
2051 | if (ENABLE_FEATURE_CLEAN_UP) free(unc); | 2056 | if (ENABLE_FEATURE_CLEAN_UP) free(unc); |
2052 | } | 2057 | } |
2053 | 2058 | ||
@@ -2073,7 +2078,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
2073 | // (instead of _numeric_ iface_id) with glibc. | 2078 | // (instead of _numeric_ iface_id) with glibc. |
2074 | // This probably should be fixed in glibc, not here. | 2079 | // This probably should be fixed in glibc, not here. |
2075 | // The workaround is to manually specify correct "ip=ADDR%n" option. | 2080 | // The workaround is to manually specify correct "ip=ADDR%n" option. |
2076 | parse_mount_options(ip, &filteropts); | 2081 | parse_mount_options(ip, &filteropts, NULL); |
2077 | if (ENABLE_FEATURE_CLEAN_UP) free(ip); | 2082 | if (ENABLE_FEATURE_CLEAN_UP) free(ip); |
2078 | } | 2083 | } |
2079 | 2084 | ||
@@ -2355,7 +2360,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
2355 | // Past this point, we are handling either "mount -a [opts]" | 2360 | // Past this point, we are handling either "mount -a [opts]" |
2356 | // or "mount [opts] single_param" | 2361 | // or "mount [opts] single_param" |
2357 | 2362 | ||
2358 | cmdopt_flags = parse_mount_options(cmdopts, NULL); | 2363 | cmdopt_flags = parse_mount_options(cmdopts, NULL, &option_mask32); |
2359 | if (nonroot && (cmdopt_flags & ~MS_SILENT)) // Non-root users cannot specify flags | 2364 | if (nonroot && (cmdopt_flags & ~MS_SILENT)) // Non-root users cannot specify flags |
2360 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | 2365 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); |
2361 | 2366 | ||
@@ -2429,7 +2434,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
2429 | continue; | 2434 | continue; |
2430 | 2435 | ||
2431 | // Skip noauto and swap anyway | 2436 | // Skip noauto and swap anyway |
2432 | if ((parse_mount_options(mtcur->mnt_opts, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP)) | 2437 | if ((parse_mount_options(mtcur->mnt_opts, NULL, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP)) |
2433 | // swap is bogus "fstype", parse_mount_options can't check fstypes | 2438 | // swap is bogus "fstype", parse_mount_options can't check fstypes |
2434 | || strcasecmp(mtcur->mnt_type, "swap") == 0 | 2439 | || strcasecmp(mtcur->mnt_type, "swap") == 0 |
2435 | ) { | 2440 | ) { |
@@ -2490,7 +2495,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
2490 | // exit_group(32) = ? | 2495 | // exit_group(32) = ? |
2491 | #if 0 | 2496 | #if 0 |
2492 | // In case we want to simply skip swap partitions: | 2497 | // In case we want to simply skip swap partitions: |
2493 | l = parse_mount_options(mtcur->mnt_opts, NULL); | 2498 | l = parse_mount_options(mtcur->mnt_opts, NULL, NULL); |
2494 | if ((l & MOUNT_SWAP) | 2499 | if ((l & MOUNT_SWAP) |
2495 | // swap is bogus "fstype", parse_mount_options can't check fstypes | 2500 | // swap is bogus "fstype", parse_mount_options can't check fstypes |
2496 | || strcasecmp(mtcur->mnt_type, "swap") == 0 | 2501 | || strcasecmp(mtcur->mnt_type, "swap") == 0 |
@@ -2500,7 +2505,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
2500 | #endif | 2505 | #endif |
2501 | if (nonroot) { | 2506 | if (nonroot) { |
2502 | // fstab must have "users" or "user" | 2507 | // fstab must have "users" or "user" |
2503 | l = parse_mount_options(mtcur->mnt_opts, NULL); | 2508 | l = parse_mount_options(mtcur->mnt_opts, NULL, NULL); |
2504 | if (!(l & MOUNT_USERS)) | 2509 | if (!(l & MOUNT_USERS)) |
2505 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); | 2510 | bb_simple_error_msg_and_die(bb_msg_you_must_be_root); |
2506 | } | 2511 | } |