1 // RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
2 // RUN: -- -std=c11 -I %S/Inputs/bugprone-not-null-terminated-result
3 
4 // FIXME: Something wrong with the APInt un/signed conversion on Windows:
5 // in 'strncmp(str6, "string", 7);' it tries to inject '4294967302' as length.
6 
7 // UNSUPPORTED: system-windows
8 
9 #include "not-null-terminated-result-c.h"
10 
11 #define __STDC_LIB_EXT1__ 1
12 #define __STDC_WANT_LIB_EXT1__ 1
13 
bad_memchr_1(char * position,const char * src)14 void bad_memchr_1(char *position, const char *src) {
15   position = (char *)memchr(src, '\0', strlen(src));
16   // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
17   // CHECK-FIXES: position = strchr(src, '\0');
18 }
19 
good_memchr_1(char * pos,const char * src)20 void good_memchr_1(char *pos, const char *src) {
21   pos = strchr(src, '\0');
22 }
23 
bad_memchr_2(char * position)24 void bad_memchr_2(char *position) {
25   position = (char *)memchr("foobar", '\0', 6);
26   // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
27   // CHECK-FIXES: position = strchr("foobar", '\0');
28 }
29 
good_memchr_2(char * pos)30 void good_memchr_2(char *pos) {
31   pos = strchr("foobar", '\0');
32 }
33 
bad_memmove(const char * src)34 void bad_memmove(const char *src) {
35   char dest[13];
36   memmove(dest, src, strlen(src));
37   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memmove' is not null-terminated [bugprone-not-null-terminated-result]
38   // CHECK-FIXES: char dest[14];
39   // CHECK-FIXES-NEXT: memmove_s(dest, 14, src, strlen(src) + 1);
40 }
41 
good_memmove(const char * src)42 void good_memmove(const char *src) {
43   char dst[14];
44   memmove_s(dst, 13, src, strlen(src) + 1);
45 }
46 
bad_memmove_s(char * dest,const char * src)47 void bad_memmove_s(char *dest, const char *src) {
48   memmove_s(dest, 13, src, strlen(src));
49   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memmove_s' is not null-terminated [bugprone-not-null-terminated-result]
50   // CHECK-FIXES: memmove_s(dest, 13, src, strlen(src) + 1);
51 }
52 
good_memmove_s_1(char * dest,const char * src)53 void good_memmove_s_1(char *dest, const char *src) {
54   memmove_s(dest, 13, src, strlen(src) + 1);
55 }
56 
bad_strerror_s(int errno)57 void bad_strerror_s(int errno) {
58   char dest[13];
59   strerror_s(dest, strlen(strerror(errno)), errno);
60   // 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]
61   // CHECK-FIXES: char dest[14];
62   // CHECK-FIXES-NEXT: strerror_s(dest, strlen(strerror(errno)) + 1, errno);
63 }
64 
good_strerror_s(int errno)65 void good_strerror_s(int errno) {
66   char dst[14];
67   strerror_s(dst, strlen(strerror(errno)) + 1, errno);
68 }
69 
bad_strncmp_1(char * str0,const char * str1)70 int bad_strncmp_1(char *str0, const char *str1) {
71   return strncmp(str0, str1, (strlen(str0) + 1));
72   // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
73   // CHECK-FIXES: strncmp(str0, str1, (strlen(str0)));
74 }
75 
bad_strncmp_2(char * str2,const char * str3)76 int bad_strncmp_2(char *str2, const char *str3) {
77   return strncmp(str2, str3, 1 + strlen(str2));
78   // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
79   // CHECK-FIXES: strncmp(str2, str3, strlen(str2));
80 }
81 
good_strncmp_1_2(char * str4,const char * str5)82 int good_strncmp_1_2(char *str4, const char *str5) {
83   return strncmp(str4, str5, strlen(str4));
84 }
85 
bad_strncmp_3(char * str6)86 int bad_strncmp_3(char *str6) {
87   return strncmp(str6, "string", 7);
88   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
89   // CHECK-FIXES: strncmp(str6, "string", 6);
90 }
91 
good_strncmp_3(char * str7)92 int good_strncmp_3(char *str7) {
93   return strncmp(str7, "string", 6);
94 }
95 
bad_strxfrm_1(const char * long_source_name)96 void bad_strxfrm_1(const char *long_source_name) {
97   char long_destination_array_name[13];
98   strxfrm(long_destination_array_name, long_source_name,
99           strlen(long_source_name));
100   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
101   // CHECK-FIXES: char long_destination_array_name[14];
102   // CHECK-FIXES-NEXT: strxfrm(long_destination_array_name, long_source_name,
103   // CHECK-FIXES-NEXT: strlen(long_source_name) + 1);
104 }
105 
good_strxfrm_1(const char * long_source_name)106 void good_strxfrm_1(const char *long_source_name) {
107   char long_destination_array_name[14];
108   strxfrm(long_destination_array_name, long_source_name,
109           strlen(long_source_name) + 1);
110 }
111 
bad_strxfrm_2()112 void bad_strxfrm_2() {
113   char long_destination_array_name1[16];
114   strxfrm(long_destination_array_name1, "long_source_name", 16);
115   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
116   // CHECK-FIXES: char long_destination_array_name1[17];
117   // CHECK-FIXES: strxfrm(long_destination_array_name1, "long_source_name", 17);
118 }
119 
good_strxfrm_2()120 void good_strxfrm_2() {
121   char long_destination_array_name2[17];
122   strxfrm(long_destination_array_name2, "long_source_name", 17);
123 }
124