1 /* Copyright (C) 2000  Free Software Foundation.
2 
3    If the argument to va_end() has side effects, test whether side
4    effects from that argument are honored.
5 
6    Written by Kaveh R. Ghazi, 10/31/2000.  */
7 
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 #ifndef __GNUC__
13 #define __attribute__(x)
14 #endif
15 
16 static void __attribute__ ((__format__ (__printf__, 1, 2)))
doit(const char * s,...)17 doit (const char *s, ...)
18 {
19   va_list *ap_array[3], **ap_ptr = ap_array;
20 
21   ap_array[0] = malloc (sizeof(va_list));
22   ap_array[1] = NULL;
23   ap_array[2] = malloc (sizeof(va_list));
24 
25   va_start (*ap_array[0], s);
26   vprintf (s, **ap_ptr);
27   /* Increment the va_list pointer once.  */
28   va_end (**ap_ptr++);
29 
30   /* Increment the va_list pointer a second time.  */
31   ap_ptr++;
32 
33   va_start (*ap_array[2], s);
34   /* If we failed to increment ap_ptr twice, then the parameter passed
35      in here will dereference NULL and should cause a crash.  */
36   vprintf (s, **ap_ptr);
37   va_end (**ap_ptr);
38 
39   /* Just in case, If *ap_ptr is NULL abort anyway.  */
40   if (*ap_ptr == 0)
41     abort();
42 }
43 
main()44 int main()
45 {
46   doit ("%s", "hello world\n");
47   exit (0);
48 }
49