bc: do not perform domr limit checks when they can't work (e.g. on 32-bit arches)
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 7 Dec 2018 14:50:14 +0000 (15:50 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 7 Dec 2018 14:50:14 +0000 (15:50 +0100)
Also, optimize printing of messages with fixed limit strings
by including limits as strings.

function                                             old     new   delta
bc_num_ulong                                         103      95      -8
bc_lex_number                                        296     281     -15
dc_lex_token                                         701     684     -17
bc_lex_name                                           90      73     -17
bc_num_shift                                          72      54     -18
bc_lex_token                                        1299    1280     -19
bc_parse_stmt                                       1868    1768    -100
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/7 up/down: 0/-194)           Total: -194 bytes
   text    data     bss     dec     hex filename
 985814     485    7296  993595   f293b busybox_old
 985526     485    7296  993307   f281b busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
miscutils/bc.c

index 9eafa80e9d496afcc6649ef7aaf70d1310aa6fff..3da03b43779b30285cac91bd76a92fb969641fe8 100644 (file)
@@ -725,14 +725,39 @@ typedef unsigned long (*BcProgramBuiltIn)(BcNum *);
 #define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
 #define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
 
-#define BC_MAX_OBASE  ((unsigned) 999)
-#define BC_MAX_DIM    ((unsigned) INT_MAX)
-#define BC_MAX_SCALE  ((unsigned) UINT_MAX)
-#define BC_MAX_STRING ((unsigned) UINT_MAX - 1)
-#define BC_MAX_NAME   BC_MAX_STRING
-#define BC_MAX_NUM    BC_MAX_STRING
-#define BC_MAX_EXP    ((unsigned long) LONG_MAX)
-#define BC_MAX_VARS   ((unsigned long) SIZE_MAX - 1)
+#define BC_MAX_OBASE    ((unsigned) 999)
+#define BC_MAX_DIM      ((unsigned) INT_MAX)
+#define BC_MAX_SCALE    ((unsigned) UINT_MAX)
+#define BC_MAX_STRING   ((unsigned) UINT_MAX - 1)
+#define BC_MAX_NUM      BC_MAX_STRING
+// Unused apart from "limits" message. Just show a "biggish number" there.
+//#define BC_MAX_NAME     BC_MAX_STRING
+//#define BC_MAX_EXP      ((unsigned long) LONG_MAX)
+//#define BC_MAX_VARS     ((unsigned long) SIZE_MAX - 1)
+#define BC_MAX_NAME_STR "999999999"
+#define BC_MAX_EXP_STR  "999999999"
+#define BC_MAX_VARS_STR "999999999"
+
+#define BC_MAX_OBASE_STR "999"
+
+#if INT_MAX == 2147483647
+# define BC_MAX_DIM_STR "2147483647"
+#elif INT_MAX == 9223372036854775807
+# define BC_MAX_DIM_STR "9223372036854775807"
+#else
+# error Strange INT_MAX
+#endif
+
+#if UINT_MAX == 4294967295
+# define BC_MAX_SCALE_STR  "4294967295"
+# define BC_MAX_STRING_STR "4294967294"
+#elif UINT_MAX == 18446744073709551615
+# define BC_MAX_SCALE_STR  "18446744073709551615"
+# define BC_MAX_STRING_STR "18446744073709551614"
+#else
+# error Strange UINT_MAX
+#endif
+#define BC_MAX_NUM_STR BC_MAX_STRING_STR
 
 struct globals {
        IF_FEATURE_BC_SIGNALS(smallint ttyin;)
@@ -1590,8 +1615,12 @@ static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a,
 static BcStatus bc_num_shift(BcNum *n, size_t places)
 {
        if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS;
-       if (places + n->len > BC_MAX_NUM)
-               return bc_error("number too long: must be [1, BC_NUM_MAX]");
+
+       // This check makes sense only if size_t is (much) larger than BC_MAX_NUM.
+       if (SIZE_MAX > (BC_MAX_NUM | 0xff)) {
+               if (places + n->len > BC_MAX_NUM)
+                       return bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]");
+       }
 
        if (n->rdx >= places)
                n->rdx -= places;
@@ -2891,8 +2920,11 @@ static BcStatus bc_lex_number(BcLex *l, char start)
        }
 
        len = i + !last_pt - bslashes * 2;
-       if (len > BC_MAX_NUM)
-               return bc_error("number too long: must be [1, BC_NUM_MAX]");
+       // This check makes sense only if size_t is (much) larger than BC_MAX_NUM.
+       if (SIZE_MAX > (BC_MAX_NUM | 0xff)) {
+               if (len > BC_MAX_NUM)
+                       return bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]");
+       }
 
        bc_vec_pop_all(&l->t.v);
        bc_vec_expand(&l->t.v, len + 1);
@@ -2929,8 +2961,11 @@ static BcStatus bc_lex_name(BcLex *l)
 
        while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i];
 
-       if (i > BC_MAX_STRING)
-               return bc_error("name too long: must be [1, BC_NAME_MAX]");
+       // This check makes sense only if size_t is (much) larger than BC_MAX_STRING.
+       if (SIZE_MAX > (BC_MAX_STRING | 0xff)) {
+               if (i > BC_MAX_STRING)
+                       return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]");
+       }
        bc_vec_string(&l->t.v, i, buf);
 
        // Increment the index. We minus 1 because it has already been incremented.
@@ -3047,8 +3082,11 @@ static BcStatus bc_lex_string(BcLex *l)
        }
 
        len = i - l->i;
-       if (len > BC_MAX_STRING)
-               return bc_error("string too long: must be [1, BC_STRING_MAX]");
+       // This check makes sense only if size_t is (much) larger than BC_MAX_STRING.
+       if (SIZE_MAX > (BC_MAX_STRING | 0xff)) {
+               if (len > BC_MAX_STRING)
+                       return bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]");
+       }
        bc_vec_string(&l->t.v, len, l->buf + l->i);
 
        l->i = i + 1;
@@ -3426,8 +3464,11 @@ static BcStatus dc_lex_string(BcLex *l)
        }
 
        bc_vec_pushZeroByte(&l->t.v);
-       if (i - l->i > BC_MAX_STRING)
-               return bc_error("string too long: must be [1, BC_STRING_MAX]");
+       // This check makes sense only if size_t is (much) larger than BC_MAX_STRING.
+       if (SIZE_MAX > (BC_MAX_STRING | 0xff)) {
+               if (i - l->i > BC_MAX_STRING)
+                       return bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]");
+       }
 
        l->i = i;
        l->line += nls;
@@ -4700,14 +4741,16 @@ static BcStatus bc_parse_stmt(BcParse *p)
                        // the output is produced at _parse time_.
                        s = bc_lex_next(&p->l);
                        if (s) return s;
-                       printf("BC_BASE_MAX     = %u\n", BC_MAX_OBASE);
-                       printf("BC_DIM_MAX      = %u\n", BC_MAX_DIM);
-                       printf("BC_SCALE_MAX    = %u\n", BC_MAX_SCALE);
-                       printf("BC_STRING_MAX   = %u\n", BC_MAX_STRING);
-                       printf("BC_NAME_MAX     = %u\n", BC_MAX_NAME);
-                       printf("BC_NUM_MAX      = %u\n", BC_MAX_NUM);
-                       printf("MAX Exponent    = %lu\n", BC_MAX_EXP);
-                       printf("Number of vars  = %lu\n", BC_MAX_VARS);
+                       printf(
+                               "BC_BASE_MAX     = "BC_MAX_OBASE_STR "\n"
+                               "BC_DIM_MAX      = "BC_MAX_DIM_STR   "\n"
+                               "BC_SCALE_MAX    = "BC_MAX_SCALE_STR "\n"
+                               "BC_STRING_MAX   = "BC_MAX_STRING_STR"\n"
+                               "BC_NAME_MAX     = "BC_MAX_NAME_STR  "\n"
+                               "BC_NUM_MAX      = "BC_MAX_NUM_STR   "\n"
+                               "MAX Exponent    = "BC_MAX_EXP_STR   "\n"
+                               "Number of vars  = "BC_MAX_VARS_STR  "\n"
+                       );
                        break;
                }
 
@@ -5903,12 +5946,12 @@ static BcStatus bc_program_assign(char inst)
 
        if (ib || sc || left->t == BC_RESULT_OBASE) {
                static const char *const msg[] = {
-                       "bad ibase; must be [2, 16]",           //BC_RESULT_IBASE
-                       "bad scale; must be [0, BC_SCALE_MAX]", //BC_RESULT_SCALE
-                       NULL, //can't happen                    //BC_RESULT_LAST
-                       NULL, //can't happen                    //BC_RESULT_CONSTANT
-                       NULL, //can't happen                    //BC_RESULT_ONE
-                       "bad obase; must be [2, BC_BASE_MAX]",  //BC_RESULT_OBASE
+                       "bad ibase; must be [2,16]",                 //BC_RESULT_IBASE
+                       "bad scale; must be [0,"BC_MAX_SCALE_STR"]", //BC_RESULT_SCALE
+                       NULL, //can't happen                         //BC_RESULT_LAST
+                       NULL, //can't happen                         //BC_RESULT_CONSTANT
+                       NULL, //can't happen                         //BC_RESULT_ONE
+                       "bad obase; must be [2,"BC_MAX_OBASE_STR"]", //BC_RESULT_OBASE
                };
                size_t *ptr;
                unsigned long val, max;
@@ -6020,7 +6063,7 @@ static BcStatus bc_program_pushArray(char *code, size_t *bgn,
                if (s) goto err;
 
                if (temp > BC_MAX_DIM) {
-                       s = bc_error("array too long; must be [1, BC_DIM_MAX]");
+                       s = bc_error("array too long; must be [1,"BC_MAX_DIM_STR"]");
                        goto err;
                }