Merge pull request #3165 from ronald-cron-arm/unmet-dependencies-buffer-overflow-fix-2.7

[backport 2.7] Unmet dependencies buffer overflow fix
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index 797fac2..96e18da 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -72,6 +72,41 @@
     mbedtls_exit( 1 );                                             \
 }
 
+#if defined(__GNUC__)
+/* Test if arg and &(arg)[0] have the same type. This is true if arg is
+ * an array but not if it's a pointer. */
+#define IS_ARRAY_NOT_POINTER( arg )                                     \
+    ( ! __builtin_types_compatible_p( __typeof__( arg ),                \
+                                      __typeof__( &( arg )[0] ) ) )
+#else
+/* On platforms where we don't know how to implement this check,
+ * omit it. Oh well, a non-portable check is better than nothing. */
+#define IS_ARRAY_NOT_POINTER( arg ) 1
+#endif
+
+/* A compile-time constant with the value 0. If `const_expr` is not a
+ * compile-time constant with a nonzero value, cause a compile-time error. */
+#define STATIC_ASSERT_EXPR( const_expr )                                \
+    ( 0 && sizeof( struct { int STATIC_ASSERT : 1 - 2 * ! ( const_expr ); } ) )
+/* Return the scalar value `value` (possibly promoted). This is a compile-time
+ * constant if `value` is. `condition` must be a compile-time constant.
+ * If `condition` is false, arrange to cause a compile-time error. */
+#define STATIC_ASSERT_THEN_RETURN( condition, value )   \
+    ( STATIC_ASSERT_EXPR( condition ) ? 0 : ( value ) )
+
+#define ARRAY_LENGTH_UNSAFE( array )            \
+    ( sizeof( array ) / sizeof( *( array ) ) )
+/** Return the number of elements of a static or stack array.
+ *
+ * \param array         A value of array (not pointer) type.
+ *
+ * \return The number of elements of the array.
+ */
+#define ARRAY_LENGTH( array )                                           \
+    ( STATIC_ASSERT_THEN_RETURN( IS_ARRAY_NOT_POINTER( array ),         \
+                                 ARRAY_LENGTH_UNSAFE( array ) ) )
+
+
 /*
  * 32-bit integer manipulation macros (big endian)
  */
diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function
index 8f134ff..9b2fa2b 100644
--- a/tests/suites/main_test.function
+++ b/tests/suites/main_test.function
@@ -262,14 +262,15 @@
     const char *default_filename = "TESTCASE_FILENAME";
     const char *test_filename = NULL;
     const char **test_files = NULL;
-    int testfile_count = 0;
+    size_t testfile_count = 0;
     int option_verbose = 0;
 
     /* Other Local variables */
     int arg_index = 1;
     const char *next_arg;
-    int testfile_index, ret, i, cnt;
-    int total_errors = 0, total_tests = 0, total_skipped = 0;
+    size_t testfile_index, i, cnt;
+    int ret;
+    unsigned total_errors = 0, total_tests = 0, total_skipped = 0;
     FILE *file;
     char buf[5000];
     char *params[50];
@@ -347,8 +348,9 @@
           testfile_index < testfile_count;
           testfile_index++ )
     {
-        int unmet_dep_count = 0;
+        size_t unmet_dep_count = 0;
         char *unmet_dependencies[20]; /* only filled when verbose != 0 */
+        int missing_unmet_dependencies = 0;
 
         test_filename = test_files[ testfile_index ];
 
@@ -370,6 +372,7 @@
             }
             unmet_dep_count = 0;
             memset( unmet_dependencies, 0, sizeof( unmet_dependencies ) );
+            missing_unmet_dependencies = 0;
 
             if( ( ret = get_line( file, buf, sizeof(buf) ) ) != 0 )
                 break;
@@ -392,18 +395,26 @@
                 {
                     if( dep_check( params[i] ) != DEPENDENCY_SUPPORTED )
                     {
-                        if( 0 != option_verbose )
+                        if( unmet_dep_count <
+                            ARRAY_LENGTH( unmet_dependencies ) )
                         {
-                            unmet_dependencies[unmet_dep_count] =
-                                strdup( params[i] );
-                            if(  unmet_dependencies[unmet_dep_count] == NULL )
+                            if( 0 != option_verbose )
                             {
-                                mbedtls_fprintf( stderr,
-                                                 "FATAL: Out of memory\n" );
-                                mbedtls_exit( MBEDTLS_EXIT_FAILURE );
+                                unmet_dependencies[unmet_dep_count] =
+                                    strdup( params[i] );
+                                if( unmet_dependencies[unmet_dep_count] == NULL )
+                                {
+                                    mbedtls_fprintf( stderr,
+                                                     "FATAL: Out of memory\n" );
+                                    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
+                                }
                             }
+                            unmet_dep_count++;
                         }
-                        unmet_dep_count++;
+                        else
+                        {
+                            missing_unmet_dependencies = 1;
+                        }
                     }
                 }
 
@@ -463,11 +474,14 @@
                                         unmet_dependencies[i]);
                         free(unmet_dependencies[i]);
                     }
+                    if( missing_unmet_dependencies )
+                        mbedtls_fprintf( stdout, "..." );
                 }
                 mbedtls_fprintf( stdout, "\n" );
                 fflush( stdout );
 
                 unmet_dep_count = 0;
+                missing_unmet_dependencies = 0;
             }
             else if( ret == DISPATCH_TEST_SUCCESS )
             {
@@ -516,7 +530,7 @@
     else
         mbedtls_fprintf( stdout, "FAILED" );
 
-    mbedtls_fprintf( stdout, " (%d / %d tests (%d skipped))\n",
+    mbedtls_fprintf( stdout, " (%u / %u tests (%u skipped))\n",
              total_tests - total_errors, total_tests, total_skipped );
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \