1/* PR target/38902 */
2/* { dg-do run } */
3/* { dg-options "-O2 -fstack-protector" } */
4/* { dg-require-effective-target fstack_protector } */
5
6#ifdef DEBUG
7#include <stdio.h>
8#define debug(format, args...) printf (format , ## args)
9#else
10extern int sprintf (char *, const char *, ...);
11#define debug(format, args...)
12#endif
13
14extern void abort (void);
15
16/*
17
18Copyright (C) 2009 Canonical, Ltd.
19Author: Kees Cook <kees@ubuntu.com>
20License: GPLv3
21
22http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38616
23https://bugs.launchpad.net/ubuntu/+source/gcc-4.3/+bug/316019
24http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38902
25
26gcc -O2 -fstack-protector truncate.c -o truncate
27
28    Broken:
29
30        Only the first operation fails, so create a new function for each test.
31        Source must be local (literal or stack)
32
33        __builtin_memmove
34        __builtin_memcpy
35        __builtin_strcpy  (optimized to __builtin_memcpy?)
36        sprintf (direct)  (optmized to __builtin_strcpy?)
37        sprintf (via %s)  (optmized to __builtin_strcpy?)
38
39    OK:
40        __builtin_strcat
41        sprintf (complex format)
42
43 */
44
45char *heap = "1234567890abcdefghijklmnopqrstuvwxyz";
46
47int failed = 0;
48
49#define CHECK(count, a...) \
50void test##count (void) \
51{ \
52  char *local = "1234567890abcdefghijklmnopqrstuvwxyz"; \
53  char buffer[1024]=""; \
54    a; \
55    if (__builtin_strcmp(buffer, heap) == 0) { \
56        debug("Okay(%d):\n\t%s\n", count, # a); \
57    } \
58    else { \
59        debug("Failed(%d):\n\t%s\n", count, # a); \
60	failed++; \
61    } \
62}
63
64
65CHECK( 0, __builtin_memcpy (buffer, "1234567890abcdefghijklmnopqrstuvwxyz", __builtin_strlen("1234567890abcdefghijklmnopqrstuvwxyz")+1);                                        );
66CHECK( 1, __builtin_memcpy (buffer, local, __builtin_strlen(local)+1);                );
67CHECK( 2, __builtin_memcpy (buffer, heap, __builtin_strlen(heap)+1);                );
68
69CHECK( 3, __builtin_memmove (buffer, "1234567890abcdefghijklmnopqrstuvwxyz", __builtin_strlen("1234567890abcdefghijklmnopqrstuvwxyz")+1);                                       );
70CHECK( 4, __builtin_memmove (buffer, local, __builtin_strlen(local)+1);               );
71CHECK( 5, __builtin_memmove (buffer, heap, __builtin_strlen(heap)+1);               );
72
73CHECK( 6, __builtin_strcpy (buffer, "1234567890abcdefghijklmnopqrstuvwxyz");          );
74CHECK( 7, __builtin_strcpy (buffer, local);                                      );
75CHECK( 8, __builtin_strcpy (buffer, heap);                                      );
76
77CHECK( 9,  sprintf (buffer, "1234567890abcdefghijklmnopqrstuvwxyz");         );
78CHECK(10,  sprintf (buffer, local);                                     );
79CHECK(11,  sprintf (buffer, heap);                                     );
80
81CHECK(12,  sprintf (buffer, "%s", "1234567890abcdefghijklmnopqrstuvwxyz");   );
82CHECK(13,  sprintf (buffer, "%s", local);                               );
83CHECK(14,  sprintf (buffer, "%s", heap);                               );
84
85CHECK(15, __builtin_strcat (buffer, "1234567890abcdefghijklmnopqrstuvwxyz");          );
86CHECK(16, __builtin_strcat (buffer, local);                                      );
87CHECK(17, __builtin_strcat (buffer, heap);                                       );
88
89void mongoose(void)
90{
91  char buffer[1024]="";
92  sprintf (buffer, "%s", "1234567890abcdefghijklmnopqrstuvwxyz");;
93    if (__builtin_strcmp(buffer, heap) == 0) {
94        debug("Okay(%d):\n\t%s\n", -1, "sprintf (buffer, \"%s\", \"1234567890abcdefghijklmnopqrstuvwxyz\");");
95    }
96    else {
97        debug("Failed(%d):\n\t%s\n", -1, "sprintf (buffer, \"%s\", \"1234567890abcdefghijklmnopqrstuvwxyz\");");
98	failed++;
99    }
100}
101
102int main (int argc, char *argv[])
103{
104  test0();
105  test1();
106  test2();
107  test3();
108  test4();
109  test5();
110  test6();
111  test7();
112  test8();
113  test9();
114  test10();
115  test11();
116
117  // wtf, why are these different?!
118  test12();
119  mongoose();
120
121  test13();
122  test14();
123  test15();
124  test16();
125  test17();
126
127  if (failed)
128    abort ();
129
130  return 0;
131}
132