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 */
24 #define FILL_BUFFER_IMPL() \
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)); \
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]; \
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";
46 fill_a_buffer_memset(void)
50 memset(buf
, 0, sizeof(buf
));
55 fill_a_buffer_memwipe(void)
59 memwipe(buf
, 0, sizeof(buf
));
64 fill_a_buffer_nothing(void)
72 vmemeq(volatile char *a
, const char *b
, size_t n
)
85 volatile char buf
[BUF_LEN
];
88 /* See if this buffer has the string in it.
90 YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM AN UNINITIALIZED
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
)))
104 static char *heap_buf
= NULL
;
107 fill_heap_buffer_memset(void)
109 char *buf
= heap_buf
= raw_malloc(BUF_LEN
);
111 memset(buf
, 0, BUF_LEN
);
117 fill_heap_buffer_memwipe(void)
119 char *buf
= heap_buf
= raw_malloc(BUF_LEN
);
121 memwipe(buf
, 0, BUF_LEN
);
127 fill_heap_buffer_nothing(void)
129 char *buf
= heap_buf
= raw_malloc(BUF_LEN
);
136 check_heap_buffer(void)
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
)))
157 static struct testcase
{
159 /* this spacing satisfies make check-spaces */
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
},
175 main(int argc
, char **argv
)
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();
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");
211 printf("OKAY: memwipe seems to work.\n");