blob: 7e173ee27086157b1c1356de4b0124aa1abac9f9 [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>
Gilles Peskine69e8db02023-11-02 19:52:32 +010014#include <mbedtls/platform_util.h>
Gilles Peskine33406b62023-11-02 18:48:39 +010015#include "test/helpers.h"
Gilles Peskine102aea22023-11-03 18:05:38 +010016#include "test/macros.h"
Gilles Peskine33406b62023-11-02 18:48:39 +010017
18#include <stdio.h>
19#include <string.h>
20
Gilles Peskine102aea22023-11-03 18:05:38 +010021#if defined(MBEDTLS_THREADING_C)
22#include <mbedtls/threading.h>
23#endif
24
Gilles Peskine33406b62023-11-02 18:48:39 +010025
Gilles Peskine69e8db02023-11-02 19:52:32 +010026/* This is an external variable, so the compiler doesn't know that we're never
27 * changing its value.
28 *
29 * TODO: LTO (link-time-optimization) would defeat this.
30 */
31int false_but_the_compiler_does_not_know = 0;
32
33
Gilles Peskine33406b62023-11-02 18:48:39 +010034/****************************************************************/
Gilles Peskinef309fbf2023-11-02 18:49:52 +010035/* Test framework features */
36/****************************************************************/
37
38void meta_test_fail(const char *name)
39{
40 (void) name;
41 mbedtls_test_fail("Forced test failure", __LINE__, __FILE__);
42}
43
44
45/****************************************************************/
Gilles Peskine80ba8322023-11-02 19:23:26 +010046/* Platform features */
47/****************************************************************/
48
49void null_pointer_dereference(const char *name)
50{
51 (void) name;
Gilles Peskine69e8db02023-11-02 19:52:32 +010052 volatile char *p;
Gilles Peskine6aa9f322023-11-02 21:31:07 +010053 mbedtls_platform_zeroize((void *) &p, sizeof(p));
Gilles Peskine69e8db02023-11-02 19:52:32 +010054 mbedtls_printf("%p -> %u\n", p, (unsigned) *p);
Gilles Peskine80ba8322023-11-02 19:23:26 +010055}
56
57void null_pointer_call(const char *name)
58{
59 (void) name;
Gilles Peskine69e8db02023-11-02 19:52:32 +010060 unsigned (*p)(void);
61 mbedtls_platform_zeroize(&p, sizeof(p));
Gilles Peskinef0d5cf92023-11-03 10:58:57 +010062 /* The pointer representation may be truncated, but we don't care:
63 * the only point of printing it is to have some use of the pointer
64 * to dissuade the compiler from optimizing it away. */
65 mbedtls_printf("%lx() -> %u\n", (unsigned long) (uintptr_t) p, p());
Gilles Peskine80ba8322023-11-02 19:23:26 +010066}
67
68
69/****************************************************************/
Gilles Peskine102aea22023-11-03 18:05:38 +010070/* Memory */
Gilles Peskineb0f0a642023-11-02 19:42:13 +010071/****************************************************************/
72
73void read_after_free(const char *name)
74{
75 (void) name;
76 volatile char *p = mbedtls_calloc(1, 1);
77 *p = 'a';
78 mbedtls_free((void *) p);
79 mbedtls_printf("%u\n", (unsigned) *p);
80}
81
82void double_free(const char *name)
83{
84 (void) name;
85 volatile char *p = mbedtls_calloc(1, 1);
86 *p = 'a';
87 mbedtls_free((void *) p);
88 mbedtls_free((void *) p);
89}
90
91void read_uninitialized_stack(const char *name)
92{
93 (void) name;
94 volatile char buf[1];
Gilles Peskineb0f0a642023-11-02 19:42:13 +010095 if (false_but_the_compiler_does_not_know) {
96 buf[0] = '!';
97 }
98 if (*buf != 0) {
99 mbedtls_printf("%u\n", (unsigned) *buf);
100 }
101}
102
103void memory_leak(const char *name)
104{
105 (void) name;
106 volatile char *p = mbedtls_calloc(1, 1);
107 /* Hint to the compiler that calloc must not be optimized away. */
108 (void) *p;
109}
110
111
112/****************************************************************/
Gilles Peskine102aea22023-11-03 18:05:38 +0100113/* Threading */
114/****************************************************************/
115
116void mutex_lock_not_initialized(const char *name)
117{
118 (void) name;
119 /* Mutex usage verification is only done with pthread, not with other
120 * threading implementations. See tests/src/threading_helpers.c. */
121#if defined(MBEDTLS_THREADING_PTHREAD)
122 mbedtls_threading_mutex_t mutex;
123 memset(&mutex, 0, sizeof(mutex));
124 TEST_ASSERT(mbedtls_mutex_lock(&mutex) == 0);
125exit:
126 ;
127#endif
128}
129
130void mutex_unlock_not_initialized(const char *name)
131{
132 (void) name;
133 /* Mutex usage verification is only done with pthread, not with other
134 * threading implementations. See tests/src/threading_helpers.c. */
135#if defined(MBEDTLS_THREADING_C)
136 mbedtls_threading_mutex_t mutex;
137 memset(&mutex, 0, sizeof(mutex));
138 TEST_ASSERT(mbedtls_mutex_unlock(&mutex) == 0);
139exit:
140 ;
141#endif
142}
143
144void mutex_free_not_initialized(const char *name)
145{
146 (void) name;
147 /* Mutex usage verification is only done with pthread, not with other
148 * threading implementations. See tests/src/threading_helpers.c. */
149#if defined(MBEDTLS_THREADING_C)
150 mbedtls_threading_mutex_t mutex;
151 memset(&mutex, 0, sizeof(mutex));
152 mbedtls_mutex_free(&mutex);
153#endif
154}
155
156void mutex_double_init(const char *name)
157{
158 (void) name;
159#if defined(MBEDTLS_THREADING_C)
160 mbedtls_threading_mutex_t mutex;
161 mbedtls_mutex_init(&mutex);
162 mbedtls_mutex_init(&mutex);
163 mbedtls_mutex_free(&mutex);
164#endif
165}
166
167void mutex_double_free(const char *name)
168{
169 (void) name;
170#if defined(MBEDTLS_THREADING_C)
171 mbedtls_threading_mutex_t mutex;
172 mbedtls_mutex_init(&mutex);
173 mbedtls_mutex_free(&mutex);
174 mbedtls_mutex_free(&mutex);
175#endif
176}
177
178void mutex_leak(const char *name)
179{
180 (void) name;
181 /* Mutex usage verification is only done with pthread, not with other
182 * threading implementations. See tests/src/threading_helpers.c. */
183#if defined(MBEDTLS_THREADING_PTHREAD)
184 mbedtls_threading_mutex_t mutex;
185 mbedtls_mutex_init(&mutex);
186#endif
187}
188
189
190/****************************************************************/
Gilles Peskine33406b62023-11-02 18:48:39 +0100191/* Command line entry point */
192/****************************************************************/
193
194typedef struct {
195 const char *name;
196 const char *platform;
197 void (*entry_point)(const char *name);
198} metatest_t;
199
200metatest_t metatests[] = {
Gilles Peskinef309fbf2023-11-02 18:49:52 +0100201 { "test_fail", "any", meta_test_fail },
Gilles Peskine80ba8322023-11-02 19:23:26 +0100202 { "null_dereference", "any", null_pointer_dereference },
203 { "null_call", "any", null_pointer_call },
Gilles Peskineb0f0a642023-11-02 19:42:13 +0100204 { "read_after_free", "asan", read_after_free },
205 { "double_free", "asan", double_free },
206 { "read_uninitialized_stack", "msan", read_uninitialized_stack },
207 { "memory_leak", "asan", memory_leak },
Gilles Peskine102aea22023-11-03 18:05:38 +0100208 /* Mutex usage verification is only done with pthread, not with other
209 * threading implementations. See tests/src/threading_helpers.c. */
210 { "mutex_lock_not_initialized", "pthread", mutex_lock_not_initialized },
211 { "mutex_unlock_not_initialized", "pthread", mutex_unlock_not_initialized },
212 { "mutex_free_not_initialized", "pthread", mutex_free_not_initialized },
213 { "mutex_double_init", "pthread", mutex_double_init },
214 { "mutex_double_free", "pthread", mutex_double_free },
215 { "mutex_leak", "pthread", mutex_leak },
Gilles Peskine33406b62023-11-02 18:48:39 +0100216 { NULL, NULL, NULL }
217};
218
219static void help(FILE *out, const char *argv0)
220{
221 mbedtls_fprintf(out, "Usage: %s list|TEST\n", argv0);
222 mbedtls_fprintf(out, "Run a meta-test that should cause a test failure.\n");
223 mbedtls_fprintf(out, "With 'list', list the available tests and their platform requirement.\n");
224}
225
226int main(int argc, char *argv[])
227{
228 const char *argv0 = argc > 0 ? argv[0] : "metatest";
229 if (argc != 2) {
230 help(stderr, argv0);
231 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
232 }
233
234 /* Support "-help", "--help", "--list", etc. */
235 const char *command = argv[1];
236 while (*command == '-') {
237 ++command;
238 }
239
240 if (strcmp(argv[1], "help") == 0) {
241 help(stdout, argv0);
242 mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
243 }
244 if (strcmp(argv[1], "list") == 0) {
245 for (const metatest_t *p = metatests; p->name != NULL; p++) {
246 mbedtls_printf("%s %s\n", p->name, p->platform);
247 }
248 mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
249 }
250
Gilles Peskine102aea22023-11-03 18:05:38 +0100251#if defined(MBEDTLS_TEST_MUTEX_USAGE)
252 mbedtls_test_mutex_usage_init();
253#endif
254
Gilles Peskine33406b62023-11-02 18:48:39 +0100255 for (const metatest_t *p = metatests; p->name != NULL; p++) {
256 if (strcmp(argv[1], p->name) == 0) {
257 mbedtls_printf("Running metatest %s...\n", argv[1]);
258 p->entry_point(argv[1]);
Gilles Peskine102aea22023-11-03 18:05:38 +0100259#if defined(MBEDTLS_TEST_MUTEX_USAGE)
260 mbedtls_test_mutex_usage_check();
261#endif
Gilles Peskine33406b62023-11-02 18:48:39 +0100262 mbedtls_printf("Running metatest %s... done, result=%d\n",
263 argv[1], (int) mbedtls_test_info.result);
264 mbedtls_exit(mbedtls_test_info.result == MBEDTLS_TEST_RESULT_SUCCESS ?
265 MBEDTLS_EXIT_SUCCESS :
266 MBEDTLS_EXIT_FAILURE);
267 }
268 }
269
270 mbedtls_fprintf(stderr, "%s: FATAL: No such metatest: %s\n",
271 argv0, command);
272 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
273}