parse_function_arguments: stricter type parsing

Use normalization the equality comparisons instead of loose regular
expressions to determine the type of an argument of a test function.

Now declarations are parsed in a stricter way: there can't be ignored junk
at the beginning or at the end. For example, `long long unsigned int x`
was accepted as a test function argument (but not `long long unsigned x`),
although this was misleading since the value was truncated to the range of
int. Now only recognized types are accepted.

The new code is slightly looser in that it accepts `char const*` as well as
`const char*`.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/tests/scripts/generate_test_code.py b/tests/scripts/generate_test_code.py
index b72e2cb..263cd90 100755
--- a/tests/scripts/generate_test_code.py
+++ b/tests/scripts/generate_test_code.py
@@ -171,6 +171,13 @@
 import argparse
 
 
+# Types regognized as integer arguments in test functions.
+INTEGER_TYPES = frozenset(['int'])
+# Types recognized as string arguments in test functions.
+STRING_TYPES = frozenset(['char*', 'const char*', 'char const*'])
+# Types recognized as hex data arguments in test functions.
+DATA_TYPES = frozenset(['data_t*', 'const data_t*', 'data_t const*'])
+
 BEGIN_HEADER_REGEX = r'/\*\s*BEGIN_HEADER\s*\*/'
 END_HEADER_REGEX = r'/\*\s*END_HEADER\s*\*/'
 
@@ -192,9 +199,6 @@
                                                      CONDITION_OPERATOR_REGEX,
                                                      CONDITION_VALUE_REGEX)
 TEST_FUNCTION_VALIDATION_REGEX = r'\s*void\s+(?P<func_name>\w+)\s*\('
-INT_CHECK_REGEX = r'int\s+.*'
-CHAR_CHECK_REGEX = r'char\s*\*\s*.*'
-DATA_T_CHECK_REGEX = r'data_t\s*\*\s*.*'
 FUNCTION_ARG_LIST_END_REGEX = r'.*\)'
 EXIT_LABEL_REGEX = r'^exit:'
 
@@ -444,6 +448,7 @@
     return dependencies
 
 
+ARGUMENT_DECLARATION_REGEX = re.compile(r'(.+?) ?(?:\bconst\b)? ?(\w+)\Z', re.S)
 def parse_function_argument(arg, arg_idx, args, local_vars, args_dispatch):
     """
     Parses one test function's argument declaration.
@@ -456,16 +461,25 @@
     :return: the number of new wrapper arguments,
              or None if the argument declaration is invalid.
     """
+    # Normalize whitespace
     arg = arg.strip()
-    if re.search(INT_CHECK_REGEX, arg.strip()):
+    arg = re.sub(r'\s*\*\s*', r'*', arg)
+    arg = re.sub(r'\s+', r' ', arg)
+    # Extract name and type
+    m = ARGUMENT_DECLARATION_REGEX.search(arg)
+    if not m:
+        # E.g. "int x[42]"
+        return None
+    typ, _ = m.groups()
+    if typ in INTEGER_TYPES:
         args.append('int')
         args_dispatch.append('((mbedtls_test_argument_t*)params[%d])->s32' % arg_idx)
         return 1
-    if re.search(CHAR_CHECK_REGEX, arg.strip()):
+    if typ in STRING_TYPES:
         args.append('char*')
         args_dispatch.append('(char *) params[%d]' % arg_idx)
         return 1
-    if re.search(DATA_T_CHECK_REGEX, arg.strip()):
+    if typ in DATA_TYPES:
         args.append('hex')
         # create a structure
         pointer_initializer = '(uint8_t *) params[%d]' % arg_idx