failtest: Fix incorrect reuse of va_list in test/run-malloc.c.
[ccan] / ccan / failtest / test / run-malloc.c
1 #include <stdlib.h>
2 #include <setjmp.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <assert.h>
6 #include <ccan/tap/tap.h>
7
8 /* We don't actually want it to exit... */
9 static jmp_buf exited;
10 #define exit(status) longjmp(exited, (status) + 1)
11
12 #define printf saved_printf
13 static int saved_printf(const char *fmt, ...);
14
15 #define fprintf saved_fprintf
16 static int saved_fprintf(FILE *ignored, const char *fmt, ...);
17
18 #define vfprintf saved_vfprintf
19 static int saved_vfprintf(FILE *ignored, const char *fmt, va_list ap);
20
21 /* Hack to avoid a memory leak which valgrind complains about. */
22 #define realloc set_realloc
23 static void *set_realloc(void *ptr, size_t size);
24
25 #define free set_free
26 static void set_free(void *ptr);
27
28 /* Include the C files directly. */
29 #include <ccan/failtest/failtest.c>
30
31 #undef realloc
32 #undef free
33
34 static char *buffer;
35 static void *set_realloc(void *ptr, size_t size)
36 {
37         return buffer = realloc(ptr, size);
38 }
39
40 static void set_free(void *ptr)
41 {
42         if (ptr == buffer)
43                 buffer = NULL;
44         free(ptr);
45 }
46
47 static char *output = NULL;
48
49 static int saved_vprintf(const char *fmt, va_list ap)
50 {
51         int ret;
52         int len = 0;
53         va_list ap2;
54
55         va_copy(ap2, ap);
56         ret = vsnprintf(NULL, 0, fmt, ap2);
57         va_end(ap2);
58
59         if (output)
60                 len = strlen(output);
61
62         output = realloc(output, len + ret + 1);
63         return vsprintf(output + len, fmt, ap);
64 }
65
66 static int saved_vfprintf(FILE *ignored, const char *fmt, va_list ap)
67 {
68         return saved_vprintf(fmt, ap);
69 }
70
71 static int saved_printf(const char *fmt, ...)
72 {
73         va_list ap;
74         int ret;
75
76         va_start(ap, fmt);
77         ret = saved_vprintf(fmt, ap);
78         va_end(ap);
79         return ret;
80 }       
81
82 static int saved_fprintf(FILE *ignored, const char *fmt, ...)
83 {
84         va_list ap;
85         int ret;
86
87         va_start(ap, fmt);
88         ret = saved_vprintf(fmt, ap);
89         va_end(ap);
90         return ret;
91 }       
92
93 int main(void)
94 {
95         int status;
96
97         plan_tests(3);
98
99         status = setjmp(exited);
100         if (status == 0) {
101                 char *p = failtest_malloc(1, "run-malloc.c", 1);
102                 /* If we just segv, valgrind counts that as a failure.
103                  * So kill ourselves creatively. */
104                 if (!p)
105                         kill(getpid(), SIGSEGV);
106                 fail("Expected child to crash!");
107         } else {
108                 ok1(status == 2);
109                 ok1(strstr(output, "Killed by signal"));
110                 ok1(strstr(output, "--failpath=M\n"));
111         }
112         free(buffer);
113         return exit_status();
114 }