Make dir servers include a "Date:" http header more often
[tor.git] / src / test / test-memwipe.c
blob484f13dd0583525523a9909260e183c4fbf5ccc5
1 #include "orconfig.h"
2 #include <string.h>
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include <stdlib.h>
7 #include "crypto.h"
8 #include "compat.h"
9 #include "util.h"
11 static unsigned fill_a_buffer_memset(void) __attribute__((noinline));
12 static unsigned fill_a_buffer_memwipe(void) __attribute__((noinline));
13 static unsigned fill_a_buffer_nothing(void) __attribute__((noinline));
14 static unsigned fill_heap_buffer_memset(void) __attribute__((noinline));
15 static unsigned fill_heap_buffer_memwipe(void) __attribute__((noinline));
16 static unsigned fill_heap_buffer_nothing(void) __attribute__((noinline));
17 static unsigned check_a_buffer(void) __attribute__((noinline));
19 extern const char *s; /* Make the linkage global */
20 const char *s = NULL;
22 #define BUF_LEN 2048
24 #define FILL_BUFFER_IMPL() \
25 unsigned int i; \
26 unsigned sum = 0; \
28 /* Fill up a 1k buffer with a recognizable pattern. */ \
29 for (i = 0; i < BUF_LEN; i += strlen(s)) { \
30 memcpy(buf+i, s, MIN(strlen(s), BUF_LEN-i)); \
31 } \
33 /* Use the buffer as input to a computation so the above can't get */ \
34 /* optimized away. */ \
35 for (i = 0; i < BUF_LEN; ++i) { \
36 sum += (unsigned char)buf[i]; \
39 #ifdef OpenBSD
40 /* Disable some of OpenBSD's malloc protections for this test. This helps
41 * us do bad things, such as access freed buffers, without crashing. */
42 const char *malloc_options="sufjj";
43 #endif
45 static unsigned
46 fill_a_buffer_memset(void)
48 char buf[BUF_LEN];
49 FILL_BUFFER_IMPL()
50 memset(buf, 0, sizeof(buf));
51 return sum;
54 static unsigned
55 fill_a_buffer_memwipe(void)
57 char buf[BUF_LEN];
58 FILL_BUFFER_IMPL()
59 memwipe(buf, 0, sizeof(buf));
60 return sum;
63 static unsigned
64 fill_a_buffer_nothing(void)
66 char buf[BUF_LEN];
67 FILL_BUFFER_IMPL()
68 return sum;
71 static inline int
72 vmemeq(volatile char *a, const char *b, size_t n)
74 while (n--) {
75 if (*a++ != *b++)
76 return 0;
78 return 1;
81 static unsigned
82 check_a_buffer(void)
84 unsigned int i;
85 volatile char buf[BUF_LEN];
86 unsigned sum = 0;
88 /* See if this buffer has the string in it.
90 YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM AN UNINITIALIZED
91 BUFFER.
93 If you know a better way to figure out whether the compiler eliminated
94 the memset/memwipe calls or not, please let me know.
96 for (i = 0; i < BUF_LEN - strlen(s); ++i) {
97 if (vmemeq(buf+i, s, strlen(s)))
98 ++sum;
101 return sum;
104 static char *heap_buf = NULL;
106 static unsigned
107 fill_heap_buffer_memset(void)
109 char *buf = heap_buf = raw_malloc(BUF_LEN);
110 FILL_BUFFER_IMPL()
111 memset(buf, 0, BUF_LEN);
112 raw_free(buf);
113 return sum;
116 static unsigned
117 fill_heap_buffer_memwipe(void)
119 char *buf = heap_buf = raw_malloc(BUF_LEN);
120 FILL_BUFFER_IMPL()
121 memwipe(buf, 0, BUF_LEN);
122 raw_free(buf);
123 return sum;
126 static unsigned
127 fill_heap_buffer_nothing(void)
129 char *buf = heap_buf = raw_malloc(BUF_LEN);
130 FILL_BUFFER_IMPL()
131 raw_free(buf);
132 return sum;
135 static unsigned
136 check_heap_buffer(void)
138 unsigned int i;
139 unsigned sum = 0;
140 volatile char *buf = heap_buf;
142 /* See if this buffer has the string in it.
144 YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM A FREED BUFFER.
146 If you know a better way to figure out whether the compiler eliminated
147 the memset/memwipe calls or not, please let me know.
149 for (i = 0; i < BUF_LEN - strlen(s); ++i) {
150 if (vmemeq(buf+i, s, strlen(s)))
151 ++sum;
154 return sum;
157 static struct testcase {
158 const char *name;
159 /* this spacing satisfies make check-spaces */
160 unsigned
161 (*fill_fn)(void);
162 unsigned
163 (*check_fn)(void);
164 } testcases[] = {
165 { "nil", fill_a_buffer_nothing, check_a_buffer },
166 { "nil-heap", fill_heap_buffer_nothing, check_heap_buffer },
167 { "memset", fill_a_buffer_memset, check_a_buffer },
168 { "memset-heap", fill_heap_buffer_memset, check_heap_buffer },
169 { "memwipe", fill_a_buffer_memwipe, check_a_buffer },
170 { "memwipe-heap", fill_heap_buffer_memwipe, check_heap_buffer },
171 { NULL, NULL, NULL }
175 main(int argc, char **argv)
177 unsigned x, x2;
178 int i;
179 int working = 1;
180 unsigned found[6];
181 (void) argc; (void) argv;
183 s = "squamous haberdasher gallimaufry";
185 memset(found, 0, sizeof(found));
187 for (i = 0; testcases[i].name; ++i) {
188 x = testcases[i].fill_fn();
189 found[i] = testcases[i].check_fn();
191 x2 = fill_a_buffer_nothing();
193 if (x != x2) {
194 working = 0;
198 if (!working || !found[0] || !found[1]) {
199 printf("It appears that this test case may not give you reliable "
200 "information. Sorry.\n");
203 if (!found[2] && !found[3]) {
204 printf("It appears that memset is good enough on this platform. Good.\n");
207 if (found[4] || found[5]) {
208 printf("ERROR: memwipe does not wipe data!\n");
209 return 1;
210 } else {
211 printf("OKAY: memwipe seems to work.\n");
212 return 0;