aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2022-01-08 22:42:35 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2022-01-08 22:42:35 +0100
commite2952dfaff67f3641d3a6d3226753356170ff808 (patch)
tree6d77f7f379ba14fbc86bc8ef362fccefa8039f70
parent84a1305888ffcd0f4e47cfc4c6fc57918b97bdda (diff)
downloadbusybox-w32-e2952dfaff67f3641d3a6d3226753356170ff808.tar.gz
busybox-w32-e2952dfaff67f3641d3a6d3226753356170ff808.tar.bz2
busybox-w32-e2952dfaff67f3641d3a6d3226753356170ff808.zip
awk: input numbers are never octal or hex (only program consts can be)
function old new delta next_token 825 930 +105 getvar_i 114 129 +15 nextchar 49 53 +4 my_strtod 138 - -138 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 3/0 up/down: 124/-138) Total: -14 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/awk.c29
-rwxr-xr-xtestsuite/awk.tests12
2 files changed, 33 insertions, 8 deletions
diff --git a/editors/awk.c b/editors/awk.c
index f6314ac72..079d0bde5 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -848,7 +848,7 @@ static char *nextword(char **s)
848static char nextchar(char **s) 848static char nextchar(char **s)
849{ 849{
850 char c, *pps; 850 char c, *pps;
851 851 again:
852 c = *(*s)++; 852 c = *(*s)++;
853 pps = *s; 853 pps = *s;
854 if (c == '\\') 854 if (c == '\\')
@@ -859,8 +859,11 @@ static char nextchar(char **s)
859 */ 859 */
860 if (c == '\\' && *s == pps) { /* unrecognized \z? */ 860 if (c == '\\' && *s == pps) { /* unrecognized \z? */
861 c = *(*s); /* yes, fetch z */ 861 c = *(*s); /* yes, fetch z */
862 if (c) 862 if (c) { /* advance unless z = NUL */
863 (*s)++; /* advance unless z = NUL */ 863 (*s)++;
864 if (c == '\n') /* \<newline>? eat it */
865 goto again;
866 }
864 } 867 }
865 return c; 868 return c;
866} 869}
@@ -882,7 +885,13 @@ static ALWAYS_INLINE int isalnum_(int c)
882static double my_strtod(char **pp) 885static double my_strtod(char **pp)
883{ 886{
884 char *cp = *pp; 887 char *cp = *pp;
885 if (ENABLE_DESKTOP && cp[0] == '0') { 888 return strtod(cp, pp);
889}
890#if ENABLE_DESKTOP
891static double my_strtod_or_hexoct(char **pp)
892{
893 char *cp = *pp;
894 if (cp[0] == '0') {
886 /* Might be hex or octal integer: 0x123abc or 07777 */ 895 /* Might be hex or octal integer: 0x123abc or 07777 */
887 char c = (cp[1] | 0x20); 896 char c = (cp[1] | 0x20);
888 if (c == 'x' || isdigit(cp[1])) { 897 if (c == 'x' || isdigit(cp[1])) {
@@ -901,6 +910,9 @@ static double my_strtod(char **pp)
901 } 910 }
902 return strtod(cp, pp); 911 return strtod(cp, pp);
903} 912}
913#else
914# define my_strtod_or_hexoct(p) my_strtod(p)
915#endif
904 916
905/* -------- working with variables (set/get/copy/etc) -------- */ 917/* -------- working with variables (set/get/copy/etc) -------- */
906 918
@@ -1014,6 +1026,7 @@ static double getvar_i(var *v)
1014 if (s && *s) { 1026 if (s && *s) {
1015 debug_printf_eval("getvar_i: '%s'->", s); 1027 debug_printf_eval("getvar_i: '%s'->", s);
1016 v->number = my_strtod(&s); 1028 v->number = my_strtod(&s);
1029 /* ^^^ hex/oct NOT allowed here! */
1017 debug_printf_eval("%f (s:'%s')\n", v->number, s); 1030 debug_printf_eval("%f (s:'%s')\n", v->number, s);
1018 if (v->type & VF_USER) { 1031 if (v->type & VF_USER) {
1019//TODO: skip_spaces() also skips backslash+newline, is it intended here? 1032//TODO: skip_spaces() also skips backslash+newline, is it intended here?
@@ -1125,10 +1138,10 @@ static uint32_t next_token(uint32_t expected)
1125 if (*p == '\0') { 1138 if (*p == '\0') {
1126 tc = TC_EOF; 1139 tc = TC_EOF;
1127 debug_printf_parse("%s: token found: TC_EOF\n", __func__); 1140 debug_printf_parse("%s: token found: TC_EOF\n", __func__);
1128 } else if (*p == '\"') { 1141 } else if (*p == '"') {
1129 /* it's a string */ 1142 /* it's a string */
1130 char *s = t_string = ++p; 1143 char *s = t_string = ++p;
1131 while (*p != '\"') { 1144 while (*p != '"') {
1132 char *pp; 1145 char *pp;
1133 if (*p == '\0' || *p == '\n') 1146 if (*p == '\0' || *p == '\n')
1134 syntax_error(EMSG_UNEXP_EOS); 1147 syntax_error(EMSG_UNEXP_EOS);
@@ -1166,7 +1179,8 @@ static uint32_t next_token(uint32_t expected)
1166 } else if (*p == '.' || isdigit(*p)) { 1179 } else if (*p == '.' || isdigit(*p)) {
1167 /* it's a number */ 1180 /* it's a number */
1168 char *pp = p; 1181 char *pp = p;
1169 t_double = my_strtod(&pp); 1182 t_double = my_strtod_or_hexoct(&pp);
1183 /* ^^^ awk only allows hex/oct consts in _program_, not in _input_ */
1170 p = pp; 1184 p = pp;
1171 if (*p == '.') 1185 if (*p == '.')
1172 syntax_error(EMSG_UNEXP_TOKEN); 1186 syntax_error(EMSG_UNEXP_TOKEN);
@@ -3503,6 +3517,7 @@ static var *evaluate(node *op, var *res)
3503 i = (Ld == 0); 3517 i = (Ld == 0);
3504 break; 3518 break;
3505 } 3519 }
3520 debug_printf_eval("COMPARE result: %d\n", (i == 0) ^ (opn & 1));
3506 setvar_i(res, (i == 0) ^ (opn & 1)); 3521 setvar_i(res, (i == 0) ^ (opn & 1));
3507 break; 3522 break;
3508 } 3523 }
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index bcaafe8fd..93e25d8c1 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -102,9 +102,13 @@ testing "awk unused function args are evaluated" \
102optional DESKTOP 102optional DESKTOP
103testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n" 103testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n"
104testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2147483649\n" "" "\n" 104testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2147483649\n" "" "\n"
105testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" 105testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n"
106SKIP= 106SKIP=
107 107
108# check that "hex/oct integer" heuristic doesn't kick in on input
109# (must be done only when parsing program text)
110testing "awk input is never oct" "awk '{ print \$1, \$1+1 }'" "011 12\n" "" "011\n"
111
108# check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN 112# check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN
109testing "awk floating const with leading zeroes" \ 113testing "awk floating const with leading zeroes" \
110 "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \ 114 "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \
@@ -469,4 +473,10 @@ testing 'awk printf %% prints one %' \
469 "%\n" \ 473 "%\n" \
470 '' '' 474 '' ''
471 475
476testing 'awk backslash+newline eaten with no trace' \
477 "awk 'BEGIN { printf \"Hello\\
478 world\n\" }'" \
479 "Hello world\n" \
480 '' ''
481
472exit $FAILCOUNT 482exit $FAILCOUNT