1 /* See e.g. https://en.cppreference.com/w/c/string/byte/strncpy */
3 /* { dg-additional-options "-Wno-stringop-overflow" } */
4 /* { dg-additional-options "-fpermissive" { target c++ } } */
6 #include "../../gcc.dg/analyzer/analyzer-decls.h"
8 typedef __SIZE_TYPE__
size_t;
10 extern char *strncpy (char *dst
, const char *src
, size_t count
);
13 test_passthrough (char *dst
, const char *src
, size_t count
)
15 char *result
= strncpy (dst
, src
, count
);
16 __analyzer_eval (result
== dst
); /* { dg-warning "TRUE" } */
21 test_null_dst (const char *src
, size_t count
)
23 return strncpy (NULL
, src
, count
); /* { dg-warning "use of NULL where non-null expected" } */
27 test_null_src (char *dst
, size_t count
)
29 return strncpy (dst
, NULL
, count
); /* { dg-warning "use of NULL where non-null expected" } */
33 test_zero_fill (char *dst
)
36 __analyzer_eval (dst
[0] == '\0'); /* { dg-warning "TRUE" "correct" { xfail *-*-* } } */
37 /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
38 __analyzer_eval (dst
[1] == '\0'); /* { dg-warning "TRUE" "correct" { xfail *-*-* } } */
39 /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
40 __analyzer_eval (dst
[2] == '\0'); /* { dg-warning "TRUE" "correct" { xfail *-*-* } } */
41 /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
42 __analyzer_eval (dst
[3] == '\0'); /* { dg-warning "TRUE" "correct" { xfail *-*-* } } */
43 /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
44 __analyzer_eval (dst
[4] == '\0'); /* { dg-warning "TRUE" "correct" { xfail *-*-* } } */
45 /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
46 __analyzer_eval (__analyzer_get_strlen (dst
) == 0); /* { dg-warning "TRUE" } */
47 __analyzer_eval (__analyzer_get_strlen (dst
+ 1) == 0); /* { dg-warning "TRUE" "correct" { xfail *-*-* } } */
48 /* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
51 char *test_unterminated_concrete_a (char *dst
)
53 char buf
[3] = "abc"; /* { dg-warning "initializer-string for '\[^\n\]*' is too long" "" { target c++ } } */
54 /* Should be OK to copy nothing. */
55 return strncpy (dst
, buf
, 0); /* { dg-bogus "" } */
58 char *test_unterminated_concrete_b (char *dst
)
60 char buf
[3] = "abc"; /* { dg-warning "initializer-string for '\[^\n\]*' is too long" "" { target c++ } } */
61 /* Should be OK as the count limits the accesses to valid
62 locations within src buf. */
63 return strncpy (dst
, buf
, 3); /* { dg-bogus "" } */
66 char *test_unterminated_concrete_c (char *dst
)
68 char buf
[3] = "abc"; /* { dg-warning "initializer-string for '\[^\n\]*' is too long" "" { target c++ } } */
69 /* Should warn: the count is one too high to limit the accesses
71 return strncpy (dst
, buf
, 4); /* { dg-warning "stack-based buffer over-read" } */
74 char *test_terminated_concrete_d (char *dst
)
77 __builtin_memset (buf
, 'a', 3);
78 __builtin_memset (buf
+ 3, 'b', 3);
81 return strncpy (dst
, buf
, 6); /* { dg-bogus "" } */
84 char *test_unterminated_concrete_e (char *dst
)
87 __builtin_memset (buf
, 'a', 3);
88 __builtin_memset (buf
+ 3, 'b', 3);
91 return strncpy (dst
, buf
, 7); /* { dg-warning "stack-based buffer over-read" } */
94 char *test_unterminated_symbolic (char *dst
, size_t count
)
96 char buf
[3] = "abc"; /* { dg-warning "initializer-string for '\[^\n\]*' is too long" "" { target c++ } } */
97 return strncpy (dst
, buf
, count
);
100 char *test_terminated_symbolic (char *dst
, size_t count
)
102 const char *src
= "abc";
103 return strncpy (dst
, src
, count
); /* { dg-bogus "" } */
106 char *test_uninitialized_concrete_a (char *dst
)
109 return strncpy (dst
, buf
, 0); /* { dg-bogus "" } */
112 char *test_uninitialized_concrete_b (char *dst
)
115 return strncpy (dst
, buf
, 1); /* { dg-warning "use of uninitialized value" } */
118 char *test_initialized_concrete_c (char *dst
)
122 return strncpy (dst
, buf
, 1); /* { dg-bogus "" } */
125 char *test_uninitialized_symbolic (char *dst
, size_t count
)
128 return strncpy (dst
, buf
, count
); /* { dg-warning "use of uninitialized value" } */
131 void test_truncation_1 (const char *src
)
134 strncpy (buf
, src
, 16);
135 /* buf might not be terminated (when strlen(src) > 16). */
136 __analyzer_get_strlen (buf
); /* { dg-warning "stack-based buffer over-read" "" { xfail *-*-* } } */
139 void test_truncation_2 (size_t count
)
142 strncpy (buf
, "abc", count
);
143 /* buf might not be terminated (when count <= 3). */
144 __analyzer_get_strlen (buf
); /* { dg-warning "stack-based buffer over-read" "" { xfail *-*-* } } */
147 void test_too_big_concrete (void)
150 strncpy (buf
, "abc", 128); /* { dg-warning "stack-based buffer overflow" } */
153 void test_too_big_symbolic (const char *src
)
156 strncpy (buf
, src
, 128); /* { dg-warning "stack-based buffer overflow" } */