1*89a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
2*89a1d03eSRichard // RUN: -- -std=c11 -I %S/Inputs/not-null-terminated-result
3*89a1d03eSRichard 
4*89a1d03eSRichard #include "not-null-terminated-result-c.h"
5*89a1d03eSRichard 
path_sensitive_unknown_length(char * position,const char * src)6*89a1d03eSRichard void path_sensitive_unknown_length(char *position, const char *src) {
7*89a1d03eSRichard   int length;
8*89a1d03eSRichard   length = strlen(src);
9*89a1d03eSRichard   position = (char *)memchr(src, '\0', length);
10*89a1d03eSRichard }
11*89a1d03eSRichard 
bad_memchr(char * position,const char * src)12*89a1d03eSRichard void bad_memchr(char *position, const char *src) {
13*89a1d03eSRichard   int length = strlen(src);
14*89a1d03eSRichard   position = (char *)memchr(src, '\0', length);
15*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
16*89a1d03eSRichard   // CHECK-FIXES: position = strchr(src, '\0');
17*89a1d03eSRichard }
18*89a1d03eSRichard 
good_memchr(char * pos,const char * src)19*89a1d03eSRichard void good_memchr(char *pos, const char *src) {
20*89a1d03eSRichard   pos = strchr(src, '\0');
21*89a1d03eSRichard }
22*89a1d03eSRichard 
bad_strerror_s(int errno)23*89a1d03eSRichard void bad_strerror_s(int errno) {
24*89a1d03eSRichard   char dest[13];
25*89a1d03eSRichard   int length = strlen(strerror(errno));
26*89a1d03eSRichard   strerror_s(dest, length, errno);
27*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'strerror_s' is not null-terminated and missing the last character of the error message [bugprone-not-null-terminated-result]
28*89a1d03eSRichard   // CHECK-FIXES: char dest[14];
29*89a1d03eSRichard   // CHECK-FIXES-NEXT: int length = strlen(strerror(errno));
30*89a1d03eSRichard   // CHECK-FIXES-NEXT: strerror_s(dest, length + 1, errno);
31*89a1d03eSRichard }
32*89a1d03eSRichard 
good_strerror_s(int errno)33*89a1d03eSRichard void good_strerror_s(int errno) {
34*89a1d03eSRichard   char dst[14];
35*89a1d03eSRichard   int length = strlen(strerror(errno));
36*89a1d03eSRichard   strerror_s(dst, length + 1, errno);
37*89a1d03eSRichard }
38*89a1d03eSRichard 
bad_strncmp_1(char * str1,const char * str2)39*89a1d03eSRichard int bad_strncmp_1(char *str1, const char *str2) {
40*89a1d03eSRichard   int length = strlen(str1) + 1;
41*89a1d03eSRichard   return strncmp(str1, str2, length);
42*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
43*89a1d03eSRichard   // CHECK-FIXES: strncmp(str1, str2, length - 1);
44*89a1d03eSRichard }
45*89a1d03eSRichard 
good_strncmp_1(char * str1,const char * str2)46*89a1d03eSRichard int good_strncmp_1(char *str1, const char *str2) {
47*89a1d03eSRichard   int length = strlen(str1) + 1;
48*89a1d03eSRichard   return strncmp(str1, str2, length - 1);
49*89a1d03eSRichard }
50*89a1d03eSRichard 
bad_strncmp_2(char * str2)51*89a1d03eSRichard int bad_strncmp_2(char *str2) {
52*89a1d03eSRichard   return strncmp(str2, "foobar", (strlen("foobar") + 1));
53*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
54*89a1d03eSRichard   // CHECK-FIXES: strncmp(str2, "foobar", (strlen("foobar")));
55*89a1d03eSRichard }
56*89a1d03eSRichard 
bad_strncmp_3(char * str3)57*89a1d03eSRichard int bad_strncmp_3(char *str3) {
58*89a1d03eSRichard   return strncmp(str3, "foobar", 1 + strlen("foobar"));
59*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
60*89a1d03eSRichard   // CHECK-FIXES: strncmp(str3, "foobar", strlen("foobar"));
61*89a1d03eSRichard }
62*89a1d03eSRichard 
good_strncmp_2_3(char * str)63*89a1d03eSRichard int good_strncmp_2_3(char *str) {
64*89a1d03eSRichard   return strncmp(str, "foobar", strlen("foobar"));
65*89a1d03eSRichard }
66*89a1d03eSRichard 
bad_strxfrm(const char * long_source_name)67*89a1d03eSRichard void bad_strxfrm(const char *long_source_name) {
68*89a1d03eSRichard   char long_destination_name[13];
69*89a1d03eSRichard   int very_long_length_definition_name = strlen(long_source_name);
70*89a1d03eSRichard   strxfrm(long_destination_name, long_source_name,
71*89a1d03eSRichard           very_long_length_definition_name);
72*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
73*89a1d03eSRichard   // CHECK-FIXES: char long_destination_name[14];
74*89a1d03eSRichard   // CHECK-FIXES-NEXT: int very_long_length_definition_name = strlen(long_source_name);
75*89a1d03eSRichard   // CHECK-FIXES-NEXT: strxfrm(long_destination_name, long_source_name,
76*89a1d03eSRichard   // CHECK-FIXES-NEXT: very_long_length_definition_name + 1);
77*89a1d03eSRichard }
78*89a1d03eSRichard 
good_strxfrm(const char * long_source_name)79*89a1d03eSRichard void good_strxfrm(const char *long_source_name) {
80*89a1d03eSRichard   char long_destination_name[14];
81*89a1d03eSRichard   int very_long_length_definition_name = strlen(long_source_name);
82*89a1d03eSRichard   strxfrm(long_destination_name, long_source_name,
83*89a1d03eSRichard           very_long_length_definition_name + 1);
84*89a1d03eSRichard }
85