blob: b8dffa9bbd122e13af0df82be6c8f45b8110c28f [file] [log] [blame]
Gilles Peskine33406b62023-11-02 18:48:39 +01001/** \file metatest.c
2 *
3 * \brief Test features of the test framework.
Gilles Peskinecce00122023-11-10 15:36:15 +01004 *
5 * When you run this program, it runs a single "meta-test". A meta-test
6 * performs an operation which should be caught as a failure by our
7 * test framework. The meta-test passes if this program calls `exit` with
8 * a nonzero status, or aborts, or is terminated by a signal, or if the
9 * framework running the program considers the run an error (this happens
10 * with Valgrind for a memory leak). The non-success of the meta-test
11 * program means that the test failure has been caught correctly.
12 *
13 * Some failures are purely functional: the logic of the code causes the
14 * test result to be set to FAIL. Other failures come from extra
15 * instrumentation which is not present in a normal build; for example,
16 * Asan or Valgrind to detect memory leaks. This is reflected by the
17 * "platform" associated with each meta-test.
18 *
19 * Use the companion script `tests/scripts/run-metatests.sh` to run all
20 * the meta-tests for a given platform and validate that they trigger a
21 * detected failure as expected.
Gilles Peskine33406b62023-11-02 18:48:39 +010022 */
23
24/*
25 * Copyright The Mbed TLS Contributors
26 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
27 */
28
29#define MBEDTLS_ALLOW_PRIVATE_ACCESS
30
31#include <mbedtls/platform.h>
Gilles Peskine69e8db02023-11-02 19:52:32 +010032#include <mbedtls/platform_util.h>
Gilles Peskine33406b62023-11-02 18:48:39 +010033#include "test/helpers.h"
Gilles Peskine102aea22023-11-03 18:05:38 +010034#include "test/macros.h"
Gilles Peskine33406b62023-11-02 18:48:39 +010035
36#include <stdio.h>
37#include <string.h>
38
Gilles Peskine102aea22023-11-03 18:05:38 +010039#if defined(MBEDTLS_THREADING_C)
40#include <mbedtls/threading.h>
41#endif
42
Gilles Peskine33406b62023-11-02 18:48:39 +010043
Gilles Peskine69e8db02023-11-02 19:52:32 +010044/* This is an external variable, so the compiler doesn't know that we're never
45 * changing its value.
Gilles Peskine69e8db02023-11-02 19:52:32 +010046 */
Gilles Peskined2fa6982023-11-09 21:46:24 +010047volatile int false_but_the_compiler_does_not_know = 0;
48
Gilles Peskine7a715c42023-11-21 13:42:40 +010049/* Hide calls to calloc/free from static checkers such as
50 * `gcc-12 -Wuse-after-free`, to avoid compile-time complaints about
51 * code where we do mean to cause a runtime error. */
52void * (* volatile calloc_but_the_compiler_does_not_know)(size_t, size_t) = mbedtls_calloc;
53void(*volatile free_but_the_compiler_does_not_know)(void *) = mbedtls_free;
54
Gilles Peskined2fa6982023-11-09 21:46:24 +010055/* Set n bytes at the address p to all-bits-zero, in such a way that
56 * the compiler should not know that p is all-bits-zero. */
Gilles Peskineda6e7a22023-11-10 10:09:27 +010057static void set_to_zero_but_the_compiler_does_not_know(volatile void *p, size_t n)
Gilles Peskined2fa6982023-11-09 21:46:24 +010058{
Gilles Peskineda6e7a22023-11-10 10:09:27 +010059 memset((void *) p, false_but_the_compiler_does_not_know, n);
Gilles Peskined2fa6982023-11-09 21:46:24 +010060}
Gilles Peskine69e8db02023-11-02 19:52:32 +010061
62
Gilles Peskine33406b62023-11-02 18:48:39 +010063/****************************************************************/
Gilles Peskinef309fbf2023-11-02 18:49:52 +010064/* Test framework features */
65/****************************************************************/
66
67void meta_test_fail(const char *name)
68{
69 (void) name;
70 mbedtls_test_fail("Forced test failure", __LINE__, __FILE__);
71}
72
73
74/****************************************************************/
Gilles Peskine80ba8322023-11-02 19:23:26 +010075/* Platform features */
76/****************************************************************/
77
78void null_pointer_dereference(const char *name)
79{
80 (void) name;
Gilles Peskineda6e7a22023-11-10 10:09:27 +010081 volatile char *volatile p;
Gilles Peskined2fa6982023-11-09 21:46:24 +010082 set_to_zero_but_the_compiler_does_not_know(&p, sizeof(p));
Gilles Peskine2f40cc02023-11-16 15:11:44 +010083 /* Undefined behavior (read from null data pointer) */
Gilles Peskine69e8db02023-11-02 19:52:32 +010084 mbedtls_printf("%p -> %u\n", p, (unsigned) *p);
Gilles Peskine80ba8322023-11-02 19:23:26 +010085}
86
87void null_pointer_call(const char *name)
88{
89 (void) name;
Gilles Peskineda6e7a22023-11-10 10:09:27 +010090 unsigned(*volatile p)(void);
Gilles Peskined2fa6982023-11-09 21:46:24 +010091 set_to_zero_but_the_compiler_does_not_know(&p, sizeof(p));
Gilles Peskine2f40cc02023-11-16 15:11:44 +010092 /* Undefined behavior (execute null function pointer) */
Gilles Peskinef0d5cf92023-11-03 10:58:57 +010093 /* The pointer representation may be truncated, but we don't care:
94 * the only point of printing it is to have some use of the pointer
95 * to dissuade the compiler from optimizing it away. */
96 mbedtls_printf("%lx() -> %u\n", (unsigned long) (uintptr_t) p, p());
Gilles Peskine80ba8322023-11-02 19:23:26 +010097}
98
99
100/****************************************************************/
Gilles Peskine102aea22023-11-03 18:05:38 +0100101/* Memory */
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100102/****************************************************************/
103
104void read_after_free(const char *name)
105{
106 (void) name;
Gilles Peskine7a715c42023-11-21 13:42:40 +0100107 volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100108 *p = 'a';
Gilles Peskine7a715c42023-11-21 13:42:40 +0100109 free_but_the_compiler_does_not_know((void *) p);
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100110 /* Undefined behavior (read after free) */
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100111 mbedtls_printf("%u\n", (unsigned) *p);
112}
113
114void double_free(const char *name)
115{
116 (void) name;
Gilles Peskine7a715c42023-11-21 13:42:40 +0100117 volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100118 *p = 'a';
Gilles Peskine7a715c42023-11-21 13:42:40 +0100119 free_but_the_compiler_does_not_know((void *) p);
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100120 /* Undefined behavior (double free) */
Gilles Peskine7a715c42023-11-21 13:42:40 +0100121 free_but_the_compiler_does_not_know((void *) p);
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100122}
123
124void read_uninitialized_stack(const char *name)
125{
126 (void) name;
Gilles Peskineccb12152023-11-10 11:35:36 +0100127 char buf[1];
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100128 if (false_but_the_compiler_does_not_know) {
129 buf[0] = '!';
130 }
Gilles Peskineccb12152023-11-10 11:35:36 +0100131 char *volatile p = buf;
132 if (*p != 0) {
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100133 /* Unspecified result (read from uninitialized memory) */
Gilles Peskineccb12152023-11-10 11:35:36 +0100134 mbedtls_printf("%u\n", (unsigned) *p);
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100135 }
136}
137
138void memory_leak(const char *name)
139{
140 (void) name;
Gilles Peskine7a715c42023-11-21 13:42:40 +0100141 volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
Gilles Peskined2fa6982023-11-09 21:46:24 +0100142 mbedtls_printf("%u\n", (unsigned) *p);
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100143 /* Leak of a heap object */
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100144}
145
146
147/****************************************************************/
Gilles Peskine102aea22023-11-03 18:05:38 +0100148/* Threading */
149/****************************************************************/
150
151void mutex_lock_not_initialized(const char *name)
152{
153 (void) name;
Gilles Peskinead2a17e2023-11-16 15:09:48 +0100154#if defined(MBEDTLS_THREADING_C)
Gilles Peskine102aea22023-11-03 18:05:38 +0100155 mbedtls_threading_mutex_t mutex;
156 memset(&mutex, 0, sizeof(mutex));
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100157 /* This mutex usage error is detected by our test framework's mutex usage
158 * verification framework. See tests/src/threading_helpers.c. Other
159 * threading implementations (e.g. pthread without our instrumentation)
160 * might consider this normal usage. */
Gilles Peskine102aea22023-11-03 18:05:38 +0100161 TEST_ASSERT(mbedtls_mutex_lock(&mutex) == 0);
162exit:
163 ;
164#endif
165}
166
167void mutex_unlock_not_initialized(const char *name)
168{
169 (void) name;
Gilles Peskine102aea22023-11-03 18:05:38 +0100170#if defined(MBEDTLS_THREADING_C)
171 mbedtls_threading_mutex_t mutex;
172 memset(&mutex, 0, sizeof(mutex));
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100173 /* This mutex usage error is detected by our test framework's mutex usage
174 * verification framework. See tests/src/threading_helpers.c. Other
175 * threading implementations (e.g. pthread without our instrumentation)
176 * might consider this normal usage. */
Gilles Peskine102aea22023-11-03 18:05:38 +0100177 TEST_ASSERT(mbedtls_mutex_unlock(&mutex) == 0);
178exit:
179 ;
180#endif
181}
182
183void mutex_free_not_initialized(const char *name)
184{
185 (void) name;
Gilles Peskine102aea22023-11-03 18:05:38 +0100186#if defined(MBEDTLS_THREADING_C)
187 mbedtls_threading_mutex_t mutex;
188 memset(&mutex, 0, sizeof(mutex));
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100189 /* This mutex usage error is detected by our test framework's mutex usage
190 * verification framework. See tests/src/threading_helpers.c. Other
191 * threading implementations (e.g. pthread without our instrumentation)
192 * might consider this normal usage. */
Gilles Peskine102aea22023-11-03 18:05:38 +0100193 mbedtls_mutex_free(&mutex);
194#endif
195}
196
197void mutex_double_init(const char *name)
198{
199 (void) name;
200#if defined(MBEDTLS_THREADING_C)
201 mbedtls_threading_mutex_t mutex;
202 mbedtls_mutex_init(&mutex);
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100203 /* This mutex usage error is detected by our test framework's mutex usage
204 * verification framework. See tests/src/threading_helpers.c. Other
205 * threading implementations (e.g. pthread without our instrumentation)
206 * might consider this normal usage. */
Gilles Peskine102aea22023-11-03 18:05:38 +0100207 mbedtls_mutex_init(&mutex);
208 mbedtls_mutex_free(&mutex);
209#endif
210}
211
212void mutex_double_free(const char *name)
213{
214 (void) name;
215#if defined(MBEDTLS_THREADING_C)
216 mbedtls_threading_mutex_t mutex;
217 mbedtls_mutex_init(&mutex);
218 mbedtls_mutex_free(&mutex);
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100219 /* This mutex usage error is detected by our test framework's mutex usage
220 * verification framework. See tests/src/threading_helpers.c. Other
221 * threading implementations (e.g. pthread without our instrumentation)
222 * might consider this normal usage. */
Gilles Peskine102aea22023-11-03 18:05:38 +0100223 mbedtls_mutex_free(&mutex);
224#endif
225}
226
227void mutex_leak(const char *name)
228{
229 (void) name;
Gilles Peskinead2a17e2023-11-16 15:09:48 +0100230#if defined(MBEDTLS_THREADING_C)
Gilles Peskine102aea22023-11-03 18:05:38 +0100231 mbedtls_threading_mutex_t mutex;
232 mbedtls_mutex_init(&mutex);
233#endif
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100234 /* This mutex usage error is detected by our test framework's mutex usage
235 * verification framework. See tests/src/threading_helpers.c. Other
236 * threading implementations (e.g. pthread without our instrumentation)
237 * might consider this normal usage. */
Gilles Peskine102aea22023-11-03 18:05:38 +0100238}
239
240
241/****************************************************************/
Gilles Peskine33406b62023-11-02 18:48:39 +0100242/* Command line entry point */
243/****************************************************************/
244
245typedef struct {
Gilles Peskinecce00122023-11-10 15:36:15 +0100246 /** Command line argument that will trigger that metatest.
247 *
248 * Conventionally matches "[a-z0-9_]+". */
Gilles Peskine33406b62023-11-02 18:48:39 +0100249 const char *name;
Gilles Peskinecce00122023-11-10 15:36:15 +0100250
251 /** Platform under which that metatest is valid.
252 *
253 * - "any": should work anywhere.
254 * - "asan": triggers ASan (Address Sanitizer).
255 * - "msan": triggers MSan (Memory Sanitizer).
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100256 * - "pthread": requires MBEDTLS_THREADING_PTHREAD and MBEDTLS_TEST_HOOKS,
257 * which enables MBEDTLS_TEST_MUTEX_USAGE internally in the test
258 * framework (see tests/src/threading_helpers.c).
Gilles Peskinecce00122023-11-10 15:36:15 +0100259 */
Gilles Peskine33406b62023-11-02 18:48:39 +0100260 const char *platform;
Gilles Peskinecce00122023-11-10 15:36:15 +0100261
262 /** Function that performs the metatest.
263 *
264 * The function receives the name as an argument. This allows using the
265 * same function to perform multiple variants of a test based on the name.
266 *
267 * When executed on a conforming platform, the function is expected to
268 * either cause a test failure (mbedtls_test_fail()), or cause the
269 * program to abort in some way (e.g. by causing a segfault or by
270 * triggering a sanitizer).
271 *
272 * When executed on a non-conforming platform, the function may return
273 * normally or may have unpredictable behavior.
274 */
Gilles Peskine33406b62023-11-02 18:48:39 +0100275 void (*entry_point)(const char *name);
276} metatest_t;
277
Gilles Peskinecce00122023-11-10 15:36:15 +0100278/* The list of availble meta-tests. Remember to register new functions here!
279 *
280 * Note that we always compile all the functions, so that `metatest --list`
281 * will always list all the available meta-tests.
Gilles Peskine2f40cc02023-11-16 15:11:44 +0100282 *
283 * See the documentation of metatest_t::platform for the meaning of
284 * platform values.
Gilles Peskinecce00122023-11-10 15:36:15 +0100285 */
Gilles Peskine33406b62023-11-02 18:48:39 +0100286metatest_t metatests[] = {
Gilles Peskinef309fbf2023-11-02 18:49:52 +0100287 { "test_fail", "any", meta_test_fail },
Gilles Peskine80ba8322023-11-02 19:23:26 +0100288 { "null_dereference", "any", null_pointer_dereference },
289 { "null_call", "any", null_pointer_call },
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100290 { "read_after_free", "asan", read_after_free },
291 { "double_free", "asan", double_free },
292 { "read_uninitialized_stack", "msan", read_uninitialized_stack },
293 { "memory_leak", "asan", memory_leak },
Gilles Peskine102aea22023-11-03 18:05:38 +0100294 { "mutex_lock_not_initialized", "pthread", mutex_lock_not_initialized },
295 { "mutex_unlock_not_initialized", "pthread", mutex_unlock_not_initialized },
296 { "mutex_free_not_initialized", "pthread", mutex_free_not_initialized },
297 { "mutex_double_init", "pthread", mutex_double_init },
298 { "mutex_double_free", "pthread", mutex_double_free },
299 { "mutex_leak", "pthread", mutex_leak },
Gilles Peskine33406b62023-11-02 18:48:39 +0100300 { NULL, NULL, NULL }
301};
302
303static void help(FILE *out, const char *argv0)
304{
305 mbedtls_fprintf(out, "Usage: %s list|TEST\n", argv0);
306 mbedtls_fprintf(out, "Run a meta-test that should cause a test failure.\n");
307 mbedtls_fprintf(out, "With 'list', list the available tests and their platform requirement.\n");
308}
309
310int main(int argc, char *argv[])
311{
312 const char *argv0 = argc > 0 ? argv[0] : "metatest";
313 if (argc != 2) {
314 help(stderr, argv0);
315 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
316 }
317
318 /* Support "-help", "--help", "--list", etc. */
319 const char *command = argv[1];
320 while (*command == '-') {
321 ++command;
322 }
323
324 if (strcmp(argv[1], "help") == 0) {
325 help(stdout, argv0);
326 mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
327 }
328 if (strcmp(argv[1], "list") == 0) {
329 for (const metatest_t *p = metatests; p->name != NULL; p++) {
330 mbedtls_printf("%s %s\n", p->name, p->platform);
331 }
332 mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
333 }
334
Gilles Peskine102aea22023-11-03 18:05:38 +0100335#if defined(MBEDTLS_TEST_MUTEX_USAGE)
336 mbedtls_test_mutex_usage_init();
337#endif
338
Gilles Peskine33406b62023-11-02 18:48:39 +0100339 for (const metatest_t *p = metatests; p->name != NULL; p++) {
340 if (strcmp(argv[1], p->name) == 0) {
341 mbedtls_printf("Running metatest %s...\n", argv[1]);
342 p->entry_point(argv[1]);
Gilles Peskine102aea22023-11-03 18:05:38 +0100343#if defined(MBEDTLS_TEST_MUTEX_USAGE)
344 mbedtls_test_mutex_usage_check();
345#endif
Gilles Peskine33406b62023-11-02 18:48:39 +0100346 mbedtls_printf("Running metatest %s... done, result=%d\n",
347 argv[1], (int) mbedtls_test_info.result);
348 mbedtls_exit(mbedtls_test_info.result == MBEDTLS_TEST_RESULT_SUCCESS ?
349 MBEDTLS_EXIT_SUCCESS :
350 MBEDTLS_EXIT_FAILURE);
351 }
352 }
353
354 mbedtls_fprintf(stderr, "%s: FATAL: No such metatest: %s\n",
355 argv0, command);
356 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
357}