From a299043d5823e60801ab455d655c77459de230b0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Sun, 4 Dec 2022 00:28:56 +0100 Subject: [PATCH] Simplify parsing of integers in .datax files In the .datax parser, since we're calling strtol() anyway, rely on it for verification. This makes the .datax parser very slightly more liberal (leading spaces and '+' are now accepted), and changes the interpretation of numbers with leading zeros to octal. Before, an argument like :0123: was parsed as decimal, but an argument like :0123+1: was parsed as a C expression and hence the leading zero marked an octal representation. Now, a leading zero is always interpreted according to C syntax, namely indicating octal. There are no nonzero integer constants with a leading zero in a .data file, so this does not affect existing test cases. In the .datax generator, allow negative arguments to be 'int' (before, they were systematically treated as 'exp' even though they didn't need to be). In the .datax parser, validate the range of integer constants. They have to fit in int32_t. In the .datax generator, use 'exp' instead of 'int' for integer constants that are out of range. Signed-off-by: Gilles Peskine --- tests/scripts/generate_test_code.py | 14 ++++++-- tests/suites/helpers.function | 2 ++ tests/suites/host_test.function | 54 +++++++++-------------------- 3 files changed, 30 insertions(+), 40 deletions(-) diff --git a/tests/scripts/generate_test_code.py b/tests/scripts/generate_test_code.py index 9759f2ab2d..6b5f11bb46 100755 --- a/tests/scripts/generate_test_code.py +++ b/tests/scripts/generate_test_code.py @@ -846,6 +846,14 @@ def write_dependencies(out_data_f, test_dependencies, unique_dependencies): return dep_check_code +INT_VAL_REGEX = re.compile(r'-?(\d+|0x[0-9a-f]+)$', re.I) +def val_is_int(val: str) -> bool: + """Whether val is suitable as an 'int' parameter in the .datax file.""" + if not INT_VAL_REGEX.match(val): + return False + # Limit the range to what is guaranteed to get through strtol() + return abs(int(val, 0)) <= 0x7fffffff + def write_parameters(out_data_f, test_args, func_args, unique_expressions): """ Writes test parameters to the intermediate data file, replacing @@ -864,9 +872,9 @@ def write_parameters(out_data_f, test_args, func_args, unique_expressions): typ = func_args[i] val = test_args[i] - # check if val is a non literal int val (i.e. an expression) - if typ == 'int' and not re.match(r'(\d+|0x[0-9a-f]+)$', - val, re.I): + # Pass small integer constants literally. This reduces the size of + # the C code. Register anything else as an expression. + if typ == 'int' and not val_is_int(val): typ = 'exp' if val not in unique_expressions: unique_expressions.append(val) diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index b45702d834..6af48c4aae 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -7,6 +7,8 @@ #include #include +#include +#include #include #include #include diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function index a99a7c7c83..565ded3768 100644 --- a/tests/suites/host_test.function +++ b/tests/suites/host_test.function @@ -32,46 +32,26 @@ int verify_string(char **str) * * \return 0 if success else 1 */ -int verify_int(char *str, int32_t *value) +int verify_int(char *str, int32_t *p_value) { - size_t i; - int minus = 0; - int digits = 1; - int hex = 0; - - for (i = 0; i < strlen(str); i++) { - if (i == 0 && str[i] == '-') { - minus = 1; - continue; - } - - if (((minus && i == 2) || (!minus && i == 1)) && - str[i - 1] == '0' && (str[i] == 'x' || str[i] == 'X')) { - hex = 1; - continue; - } - - if (!((str[i] >= '0' && str[i] <= '9') || - (hex && ((str[i] >= 'a' && str[i] <= 'f') || - (str[i] >= 'A' && str[i] <= 'F'))))) { - digits = 0; - break; - } + char *end = NULL; + errno = 0; + long value = strtol(str, &end, 0); + if (errno == EINVAL || *end != '\0') { + mbedtls_fprintf(stderr, + "Expected integer for parameter and got: %s\n", str); + return KEY_VALUE_MAPPING_NOT_FOUND; } - - if (digits) { - if (hex) { - *value = strtol(str, NULL, 16); - } else { - *value = strtol(str, NULL, 10); - } - - return 0; + if (errno == ERANGE +#if LONG_MAX > 0x7fffffff + || value > 0x7fffffffL || value < -0x80000000L +#endif + ) { + mbedtls_fprintf(stderr, "Integer out of range: %s\n", str); + return KEY_VALUE_MAPPING_NOT_FOUND; } - - mbedtls_fprintf(stderr, - "Expected integer for parameter and got: %s\n", str); - return KEY_VALUE_MAPPING_NOT_FOUND; + *p_value = value; + return 0; }