1*89a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
2*89a1d03eSRichard // RUN: -- -std=c++11 -I %S/Inputs/not-null-terminated-result
3*89a1d03eSRichard 
4*89a1d03eSRichard // FIXME: Something wrong with the APInt un/signed conversion on Windows:
5*89a1d03eSRichard // in 'wcsncmp(wcs6, L"string", 7);' it tries to inject '4294967302' as length.
6*89a1d03eSRichard 
7*89a1d03eSRichard // UNSUPPORTED: system-windows
8*89a1d03eSRichard 
9*89a1d03eSRichard #include "not-null-terminated-result-cxx.h"
10*89a1d03eSRichard 
11*89a1d03eSRichard #define __STDC_LIB_EXT1__ 1
12*89a1d03eSRichard #define __STDC_WANT_LIB_EXT1__ 1
13*89a1d03eSRichard 
bad_wmemchr_1(wchar_t * position,const wchar_t * src)14*89a1d03eSRichard void bad_wmemchr_1(wchar_t *position, const wchar_t *src) {
15*89a1d03eSRichard   position = (wchar_t *)wmemchr(src, L'\0', wcslen(src));
16*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
17*89a1d03eSRichard   // CHECK-FIXES: position = wcschr(src, L'\0');
18*89a1d03eSRichard }
19*89a1d03eSRichard 
good_wmemchr_1(wchar_t * pos,const wchar_t * src)20*89a1d03eSRichard void good_wmemchr_1(wchar_t *pos, const wchar_t *src) {
21*89a1d03eSRichard   pos = wcschr(src, L'\0');
22*89a1d03eSRichard }
23*89a1d03eSRichard 
bad_wmemchr_2(wchar_t * position)24*89a1d03eSRichard void bad_wmemchr_2(wchar_t *position) {
25*89a1d03eSRichard   position = (wchar_t *)wmemchr(L"foobar", L'\0', 6);
26*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:51: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
27*89a1d03eSRichard   // CHECK-FIXES: position = wcschr(L"foobar", L'\0');
28*89a1d03eSRichard }
29*89a1d03eSRichard 
good_wmemchr_2(wchar_t * pos)30*89a1d03eSRichard void good_wmemchr_2(wchar_t *pos) {
31*89a1d03eSRichard   pos = wcschr(L"foobar", L'\0');
32*89a1d03eSRichard }
33*89a1d03eSRichard 
34*89a1d03eSRichard 
bad_wmemmove(const wchar_t * src)35*89a1d03eSRichard void bad_wmemmove(const wchar_t *src) {
36*89a1d03eSRichard   wchar_t dest[13];
37*89a1d03eSRichard   wmemmove(dest, src, wcslen(src));
38*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemmove' is not null-terminated [bugprone-not-null-terminated-result]
39*89a1d03eSRichard   // CHECK-FIXES: wchar_t dest[14];
40*89a1d03eSRichard   // CHECK-FIXES-NEXT: wmemmove_s(dest, 14, src, wcslen(src) + 1);
41*89a1d03eSRichard }
42*89a1d03eSRichard 
good_wmemmove(const wchar_t * src)43*89a1d03eSRichard void good_wmemmove(const wchar_t *src) {
44*89a1d03eSRichard   wchar_t dst[14];
45*89a1d03eSRichard   wmemmove_s(dst, 13, src, wcslen(src) + 1);
46*89a1d03eSRichard }
47*89a1d03eSRichard 
bad_wmemmove_s(wchar_t * dest,const wchar_t * src)48*89a1d03eSRichard void bad_wmemmove_s(wchar_t *dest, const wchar_t *src) {
49*89a1d03eSRichard   wmemmove_s(dest, 13, src, wcslen(src));
50*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemmove_s' is not null-terminated [bugprone-not-null-terminated-result]
51*89a1d03eSRichard   // CHECK-FIXES: wmemmove_s(dest, 13, src, wcslen(src) + 1);
52*89a1d03eSRichard }
53*89a1d03eSRichard 
good_wmemmove_s_1(wchar_t * dest,const wchar_t * src)54*89a1d03eSRichard void good_wmemmove_s_1(wchar_t *dest, const wchar_t *src) {
55*89a1d03eSRichard   wmemmove_s(dest, 13, src, wcslen(src) + 1);
56*89a1d03eSRichard }
57*89a1d03eSRichard 
bad_wcsncmp_1(wchar_t * wcs0,const wchar_t * wcs1)58*89a1d03eSRichard int bad_wcsncmp_1(wchar_t *wcs0, const wchar_t *wcs1) {
59*89a1d03eSRichard   return wcsncmp(wcs0, wcs1, (wcslen(wcs0) + 1));
60*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
61*89a1d03eSRichard   // CHECK-FIXES: wcsncmp(wcs0, wcs1, (wcslen(wcs0)));
62*89a1d03eSRichard }
63*89a1d03eSRichard 
bad_wcsncmp_2(wchar_t * wcs2,const wchar_t * wcs3)64*89a1d03eSRichard int bad_wcsncmp_2(wchar_t *wcs2, const wchar_t *wcs3) {
65*89a1d03eSRichard   return wcsncmp(wcs2, wcs3, 1 + wcslen(wcs2));
66*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
67*89a1d03eSRichard   // CHECK-FIXES: wcsncmp(wcs2, wcs3, wcslen(wcs2));
68*89a1d03eSRichard }
69*89a1d03eSRichard 
good_wcsncmp_1_2(wchar_t * wcs4,const wchar_t * wcs5)70*89a1d03eSRichard int good_wcsncmp_1_2(wchar_t *wcs4, const wchar_t *wcs5) {
71*89a1d03eSRichard   return wcsncmp(wcs4, wcs5, wcslen(wcs4));
72*89a1d03eSRichard }
73*89a1d03eSRichard 
bad_wcsncmp_3(wchar_t * wcs6)74*89a1d03eSRichard int bad_wcsncmp_3(wchar_t *wcs6) {
75*89a1d03eSRichard   return wcsncmp(wcs6, L"string", 7);
76*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
77*89a1d03eSRichard   // CHECK-FIXES: wcsncmp(wcs6, L"string", 6);
78*89a1d03eSRichard }
79*89a1d03eSRichard 
good_wcsncmp_3(wchar_t * wcs7)80*89a1d03eSRichard int good_wcsncmp_3(wchar_t *wcs7) {
81*89a1d03eSRichard   return wcsncmp(wcs7, L"string", 6);
82*89a1d03eSRichard }
83*89a1d03eSRichard 
bad_wcsxfrm_1(const wchar_t * long_source_name)84*89a1d03eSRichard void bad_wcsxfrm_1(const wchar_t *long_source_name) {
85*89a1d03eSRichard   wchar_t long_destination_array_name[13];
86*89a1d03eSRichard   wcsxfrm(long_destination_array_name, long_source_name,
87*89a1d03eSRichard           wcslen(long_source_name));
88*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: the result from calling 'wcsxfrm' is not null-terminated [bugprone-not-null-terminated-result]
89*89a1d03eSRichard   // CHECK-FIXES: wchar_t long_destination_array_name[14];
90*89a1d03eSRichard   // CHECK-FIXES-NEXT: wcsxfrm(long_destination_array_name, long_source_name,
91*89a1d03eSRichard   // CHECK-FIXES-NEXT: wcslen(long_source_name) + 1);
92*89a1d03eSRichard }
93*89a1d03eSRichard 
good_wcsxfrm_1(const wchar_t * long_source_name)94*89a1d03eSRichard void good_wcsxfrm_1(const wchar_t *long_source_name) {
95*89a1d03eSRichard   wchar_t long_destination_array_name[14];
96*89a1d03eSRichard   wcsxfrm(long_destination_array_name, long_source_name,
97*89a1d03eSRichard           wcslen(long_source_name) + 1);
98*89a1d03eSRichard }
99*89a1d03eSRichard 
bad_wcsxfrm_2()100*89a1d03eSRichard void bad_wcsxfrm_2() {
101*89a1d03eSRichard   wchar_t long_destination_array_name1[16];
102*89a1d03eSRichard   wcsxfrm(long_destination_array_name1, L"long_source_name", 16);
103*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wcsxfrm' is not null-terminated [bugprone-not-null-terminated-result]
104*89a1d03eSRichard   // CHECK-FIXES: wchar_t long_destination_array_name1[17];
105*89a1d03eSRichard   // CHECK-FIXES: wcsxfrm(long_destination_array_name1, L"long_source_name", 17);
106*89a1d03eSRichard }
107*89a1d03eSRichard 
good_wcsxfrm_2()108*89a1d03eSRichard void good_wcsxfrm_2() {
109*89a1d03eSRichard   wchar_t long_destination_array_name2[17];
110*89a1d03eSRichard   wcsxfrm(long_destination_array_name2, L"long_source_name", 17);
111*89a1d03eSRichard }
112