blob: 91a1e2a7d9d1285c92c2fff66c4ea8858ff0dce4 [file] [log] [blame]
Gilles Peskine33406b62023-11-02 18:48:39 +01001/** \file metatest.c
2 *
3 * \brief Test features of the test framework.
4 */
5
6/*
7 * Copyright The Mbed TLS Contributors
8 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
9 */
10
11#define MBEDTLS_ALLOW_PRIVATE_ACCESS
12
13#include <mbedtls/platform.h>
14#include "test/helpers.h"
15
16#include <stdio.h>
17#include <string.h>
18
19
20/****************************************************************/
Gilles Peskinef309fbf2023-11-02 18:49:52 +010021/* Test framework features */
22/****************************************************************/
23
24void meta_test_fail(const char *name)
25{
26 (void) name;
27 mbedtls_test_fail("Forced test failure", __LINE__, __FILE__);
28}
29
30
31/****************************************************************/
Gilles Peskine80ba8322023-11-02 19:23:26 +010032/* Platform features */
33/****************************************************************/
34
35void null_pointer_dereference(const char *name)
36{
37 (void) name;
38 char *p;
39 memset(&p, 0, sizeof(p));
40 volatile char c;
41 c = *p;
42 (void) c;
43}
44
45void null_pointer_call(const char *name)
46{
47 (void) name;
48 void (*p)(void);
49 memset(&p, 0, sizeof(p));
50 p();
51}
52
53
54/****************************************************************/
Gilles Peskineb0f0a642023-11-02 19:42:13 +010055/* Sanitizers */
56/****************************************************************/
57
58void read_after_free(const char *name)
59{
60 (void) name;
61 volatile char *p = mbedtls_calloc(1, 1);
62 *p = 'a';
63 mbedtls_free((void *) p);
64 mbedtls_printf("%u\n", (unsigned) *p);
65}
66
67void double_free(const char *name)
68{
69 (void) name;
70 volatile char *p = mbedtls_calloc(1, 1);
71 *p = 'a';
72 mbedtls_free((void *) p);
73 mbedtls_free((void *) p);
74}
75
76void read_uninitialized_stack(const char *name)
77{
78 (void) name;
79 volatile char buf[1];
80 static int false_but_the_compiler_does_not_know = 0;
81 if (false_but_the_compiler_does_not_know) {
82 buf[0] = '!';
83 }
84 if (*buf != 0) {
85 mbedtls_printf("%u\n", (unsigned) *buf);
86 }
87}
88
89void memory_leak(const char *name)
90{
91 (void) name;
92 volatile char *p = mbedtls_calloc(1, 1);
93 /* Hint to the compiler that calloc must not be optimized away. */
94 (void) *p;
95}
96
97
98/****************************************************************/
Gilles Peskine33406b62023-11-02 18:48:39 +010099/* Command line entry point */
100/****************************************************************/
101
102typedef struct {
103 const char *name;
104 const char *platform;
105 void (*entry_point)(const char *name);
106} metatest_t;
107
108metatest_t metatests[] = {
Gilles Peskinef309fbf2023-11-02 18:49:52 +0100109 { "test_fail", "any", meta_test_fail },
Gilles Peskine80ba8322023-11-02 19:23:26 +0100110 { "null_dereference", "any", null_pointer_dereference },
111 { "null_call", "any", null_pointer_call },
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100112 { "read_after_free", "asan", read_after_free },
113 { "double_free", "asan", double_free },
114 { "read_uninitialized_stack", "msan", read_uninitialized_stack },
115 { "memory_leak", "asan", memory_leak },
Gilles Peskine33406b62023-11-02 18:48:39 +0100116 { NULL, NULL, NULL }
117};
118
119static void help(FILE *out, const char *argv0)
120{
121 mbedtls_fprintf(out, "Usage: %s list|TEST\n", argv0);
122 mbedtls_fprintf(out, "Run a meta-test that should cause a test failure.\n");
123 mbedtls_fprintf(out, "With 'list', list the available tests and their platform requirement.\n");
124}
125
126int main(int argc, char *argv[])
127{
128 const char *argv0 = argc > 0 ? argv[0] : "metatest";
129 if (argc != 2) {
130 help(stderr, argv0);
131 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
132 }
133
134 /* Support "-help", "--help", "--list", etc. */
135 const char *command = argv[1];
136 while (*command == '-') {
137 ++command;
138 }
139
140 if (strcmp(argv[1], "help") == 0) {
141 help(stdout, argv0);
142 mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
143 }
144 if (strcmp(argv[1], "list") == 0) {
145 for (const metatest_t *p = metatests; p->name != NULL; p++) {
146 mbedtls_printf("%s %s\n", p->name, p->platform);
147 }
148 mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
149 }
150
151 for (const metatest_t *p = metatests; p->name != NULL; p++) {
152 if (strcmp(argv[1], p->name) == 0) {
153 mbedtls_printf("Running metatest %s...\n", argv[1]);
154 p->entry_point(argv[1]);
155 mbedtls_printf("Running metatest %s... done, result=%d\n",
156 argv[1], (int) mbedtls_test_info.result);
157 mbedtls_exit(mbedtls_test_info.result == MBEDTLS_TEST_RESULT_SUCCESS ?
158 MBEDTLS_EXIT_SUCCESS :
159 MBEDTLS_EXIT_FAILURE);
160 }
161 }
162
163 mbedtls_fprintf(stderr, "%s: FATAL: No such metatest: %s\n",
164 argv0, command);
165 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
166}