/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.c

https://bitbucket.org/pizzafactory/pf-gcc · C · 227 lines · 182 code · 23 blank · 22 comment · 82 complexity · 0fd5c2176dbd9f550afed5295cde3e6c MD5 · raw file

  1. /* Copyright (C) 2004, 2005 Free Software Foundation.
  2. Ensure builtin __strncpy_chk performs correctly. */
  3. extern void abort (void);
  4. typedef __SIZE_TYPE__ size_t;
  5. extern size_t strlen(const char *);
  6. extern void *memcpy (void *, const void *, size_t);
  7. extern char *strncpy (char *, const char *, size_t);
  8. extern int memcmp (const void *, const void *, size_t);
  9. extern int strcmp (const char *, const char *);
  10. extern int strncmp (const char *, const char *, size_t);
  11. extern void *memset (void *, int, size_t);
  12. #include "chk.h"
  13. const char s1[] = "123";
  14. char p[32] = "";
  15. char * volatile s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */
  16. char * volatile s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */
  17. char *s4;
  18. volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */
  19. int i;
  20. void
  21. __attribute__((noinline))
  22. test1 (void)
  23. {
  24. const char *const src = "hello world";
  25. const char *src2;
  26. char dst[64], *dst2;
  27. strncpy_disallowed = 1;
  28. chk_calls = 0;
  29. memset (dst, 0, sizeof (dst));
  30. if (strncpy (dst, src, 4) != dst || strncmp (dst, src, 4))
  31. abort();
  32. memset (dst, 0, sizeof (dst));
  33. if (strncpy (dst+16, src, 4) != dst+16 || strncmp (dst+16, src, 4))
  34. abort();
  35. memset (dst, 0, sizeof (dst));
  36. if (strncpy (dst+32, src+5, 4) != dst+32 || strncmp (dst+32, src+5, 4))
  37. abort();
  38. memset (dst, 0, sizeof (dst));
  39. dst2 = dst;
  40. if (strncpy (++dst2, src+5, 4) != dst+1 || strncmp (dst2, src+5, 4)
  41. || dst2 != dst+1)
  42. abort();
  43. memset (dst, 0, sizeof (dst));
  44. if (strncpy (dst, src, 0) != dst || strcmp (dst, ""))
  45. abort();
  46. memset (dst, 0, sizeof (dst));
  47. dst2 = dst; src2 = src;
  48. if (strncpy (++dst2, ++src2, 0) != dst+1 || strcmp (dst2, "")
  49. || dst2 != dst+1 || src2 != src+1)
  50. abort();
  51. memset (dst, 0, sizeof (dst));
  52. dst2 = dst; src2 = src;
  53. if (strncpy (++dst2+5, ++src2+5, 0) != dst+6 || strcmp (dst2+5, "")
  54. || dst2 != dst+1 || src2 != src+1)
  55. abort();
  56. memset (dst, 0, sizeof (dst));
  57. if (strncpy (dst, src, 12) != dst || strcmp (dst, src))
  58. abort();
  59. /* Test at least one instance of the __builtin_ style. We do this
  60. to ensure that it works and that the prototype is correct. */
  61. memset (dst, 0, sizeof (dst));
  62. if (__builtin_strncpy (dst, src, 4) != dst || strncmp (dst, src, 4))
  63. abort();
  64. memset (dst, 0, sizeof (dst));
  65. if (strncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst
  66. || strcmp (dst, "bar")
  67. || i != 1)
  68. abort ();
  69. if (chk_calls)
  70. abort ();
  71. strncpy_disallowed = 0;
  72. }
  73. void
  74. __attribute__((noinline))
  75. test2 (void)
  76. {
  77. chk_calls = 0;
  78. /* No runtime checking should be done here, both destination
  79. and length are unknown. */
  80. strncpy (s4, "abcd", l1 + 1);
  81. if (chk_calls)
  82. abort ();
  83. }
  84. /* Test whether compile time checking is done where it should
  85. and so is runtime object size checking. */
  86. void
  87. __attribute__((noinline))
  88. test3 (void)
  89. {
  90. struct A { char buf1[10]; char buf2[10]; } a;
  91. char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
  92. char buf3[20];
  93. int i;
  94. const char *l;
  95. size_t l2;
  96. /* The following calls should do runtime checking
  97. - source length is not known, but destination is. */
  98. chk_calls = 0;
  99. strncpy (a.buf1 + 2, s3 + 3, l1);
  100. strncpy (r, s3 + 2, l1 + 2);
  101. r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
  102. strncpy (r, s2 + 2, l1 + 2);
  103. strncpy (r + 2, s3 + 3, l1);
  104. r = buf3;
  105. for (i = 0; i < 4; ++i)
  106. {
  107. if (i == l1 - 1)
  108. r = &a.buf1[1];
  109. else if (i == l1)
  110. r = &a.buf2[7];
  111. else if (i == l1 + 1)
  112. r = &buf3[5];
  113. else if (i == l1 + 2)
  114. r = &a.buf1[9];
  115. }
  116. strncpy (r, s2 + 4, l1);
  117. if (chk_calls != 5)
  118. abort ();
  119. /* Following have known destination and known length,
  120. so if optimizing certainly shouldn't result in the checking
  121. variants. */
  122. chk_calls = 0;
  123. strncpy (a.buf1 + 2, "", 3);
  124. strncpy (a.buf1 + 2, "", 0);
  125. strncpy (r, "a", 1);
  126. strncpy (r, "a", 3);
  127. r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
  128. strncpy (r, s1 + 1, 3);
  129. strncpy (r, s1 + 1, 2);
  130. r = buf3;
  131. l = "abc";
  132. l2 = 4;
  133. for (i = 0; i < 4; ++i)
  134. {
  135. if (i == l1 - 1)
  136. r = &a.buf1[1], l = "e", l2 = 2;
  137. else if (i == l1)
  138. r = &a.buf2[7], l = "gh", l2 = 3;
  139. else if (i == l1 + 1)
  140. r = &buf3[5], l = "jkl", l2 = 4;
  141. else if (i == l1 + 2)
  142. r = &a.buf1[9], l = "", l2 = 1;
  143. }
  144. strncpy (r, "", 1);
  145. /* Here, strlen (l) + 1 is known to be at most 4 and
  146. __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
  147. runtime checking. */
  148. strncpy (&buf3[16], l, l2);
  149. strncpy (&buf3[15], "abc", l2);
  150. strncpy (&buf3[10], "fghij", l2);
  151. if (chk_calls)
  152. abort ();
  153. chk_calls = 0;
  154. }
  155. /* Test whether runtime and/or compile time checking catches
  156. buffer overflows. */
  157. void
  158. __attribute__((noinline))
  159. test4 (void)
  160. {
  161. struct A { char buf1[10]; char buf2[10]; } a;
  162. char buf3[20];
  163. chk_fail_allowed = 1;
  164. /* Runtime checks. */
  165. if (__builtin_setjmp (chk_fail_buf) == 0)
  166. {
  167. strncpy (&a.buf2[9], s2 + 4, l1 + 1);
  168. abort ();
  169. }
  170. if (__builtin_setjmp (chk_fail_buf) == 0)
  171. {
  172. strncpy (&a.buf2[7], s3, l1 + 4);
  173. abort ();
  174. }
  175. /* This should be detectable at compile time already. */
  176. if (__builtin_setjmp (chk_fail_buf) == 0)
  177. {
  178. strncpy (&buf3[19], "abc", 2);
  179. abort ();
  180. }
  181. if (__builtin_setjmp (chk_fail_buf) == 0)
  182. {
  183. strncpy (&buf3[18], "", 3);
  184. abort ();
  185. }
  186. chk_fail_allowed = 0;
  187. }
  188. void
  189. main_test (void)
  190. {
  191. #ifndef __OPTIMIZE__
  192. /* Object size checking is only intended for -O[s123]. */
  193. return;
  194. #endif
  195. __asm ("" : "=r" (s2) : "0" (s2));
  196. __asm ("" : "=r" (s3) : "0" (s3));
  197. __asm ("" : "=r" (l1) : "0" (l1));
  198. test1 ();
  199. s4 = p;
  200. test2 ();
  201. test3 ();
  202. test4 ();
  203. }