1*89a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-misplaced-operator-in-strlen-in-alloc %t
2*89a1d03eSRichard 
3*89a1d03eSRichard typedef __typeof(sizeof(int)) size_t;
4*89a1d03eSRichard void *malloc(size_t);
5*89a1d03eSRichard void *alloca(size_t);
6*89a1d03eSRichard void *calloc(size_t, size_t);
7*89a1d03eSRichard void *realloc(void *, size_t);
8*89a1d03eSRichard 
9*89a1d03eSRichard size_t strlen(const char *);
10*89a1d03eSRichard size_t strnlen(const char *, size_t);
11*89a1d03eSRichard size_t strnlen_s(const char *, size_t);
12*89a1d03eSRichard 
13*89a1d03eSRichard typedef unsigned wchar_t;
14*89a1d03eSRichard 
15*89a1d03eSRichard size_t wcslen(const wchar_t *);
16*89a1d03eSRichard size_t wcsnlen(const wchar_t *, size_t);
17*89a1d03eSRichard size_t wcsnlen_s(const wchar_t *, size_t);
18*89a1d03eSRichard 
bad_malloc(char * name)19*89a1d03eSRichard void bad_malloc(char *name) {
20*89a1d03eSRichard   char *new_name = (char *)malloc(strlen(name + 1));
21*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
22*89a1d03eSRichard   // CHECK-FIXES: {{^  char \*new_name = \(char \*\)malloc\(}}strlen(name) + 1{{\);$}}
23*89a1d03eSRichard   new_name = (char *)malloc(strnlen(name + 1, 10));
24*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: addition operator is applied to the argument of strnlen
25*89a1d03eSRichard   // CHECK-FIXES: {{^  new_name = \(char \*\)malloc\(}}strnlen(name, 10) + 1{{\);$}}
26*89a1d03eSRichard   new_name = (char *)malloc(strnlen_s(name + 1, 10));
27*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: addition operator is applied to the argument of strnlen_s
28*89a1d03eSRichard   // CHECK-FIXES: {{^  new_name = \(char \*\)malloc\(}}strnlen_s(name, 10) + 1{{\);$}}
29*89a1d03eSRichard }
30*89a1d03eSRichard 
bad_malloc_wide(wchar_t * name)31*89a1d03eSRichard void bad_malloc_wide(wchar_t *name) {
32*89a1d03eSRichard   wchar_t *new_name = (wchar_t *)malloc(wcslen(name + 1));
33*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: addition operator is applied to the argument of wcslen
34*89a1d03eSRichard   // CHECK-FIXES: {{^  wchar_t \*new_name = \(wchar_t \*\)malloc\(}}wcslen(name) + 1{{\);$}}
35*89a1d03eSRichard   new_name = (wchar_t *)malloc(wcsnlen(name + 1, 10));
36*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: addition operator is applied to the argument of wcsnlen
37*89a1d03eSRichard   // CHECK-FIXES: {{^  new_name = \(wchar_t \*\)malloc\(}}wcsnlen(name, 10) + 1{{\);$}}
38*89a1d03eSRichard   new_name = (wchar_t *)malloc(wcsnlen_s(name + 1, 10));
39*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: addition operator is applied to the argument of wcsnlen_s
40*89a1d03eSRichard   // CHECK-FIXES: {{^  new_name = \(wchar_t \*\)malloc\(}}wcsnlen_s(name, 10) + 1{{\);$}}
41*89a1d03eSRichard }
42*89a1d03eSRichard 
bad_alloca(char * name)43*89a1d03eSRichard void bad_alloca(char *name) {
44*89a1d03eSRichard   char *new_name = (char *)alloca(strlen(name + 1));
45*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
46*89a1d03eSRichard   // CHECK-FIXES: {{^  char \*new_name = \(char \*\)alloca\(}}strlen(name) + 1{{\);$}}
47*89a1d03eSRichard }
48*89a1d03eSRichard 
bad_calloc(char * name)49*89a1d03eSRichard void bad_calloc(char *name) {
50*89a1d03eSRichard   char *new_names = (char *)calloc(2, strlen(name + 1));
51*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: addition operator is applied to the argument of strlen
52*89a1d03eSRichard   // CHECK-FIXES: {{^  char \*new_names = \(char \*\)calloc\(2, }}strlen(name) + 1{{\);$}}
53*89a1d03eSRichard }
54*89a1d03eSRichard 
bad_realloc(char * old_name,char * name)55*89a1d03eSRichard void bad_realloc(char *old_name, char *name) {
56*89a1d03eSRichard   char *new_name = (char *)realloc(old_name, strlen(name + 1));
57*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
58*89a1d03eSRichard   // CHECK-FIXES: {{^  char \*new_name = \(char \*\)realloc\(old_name, }}strlen(name) + 1{{\);$}}
59*89a1d03eSRichard }
60*89a1d03eSRichard 
intentional1(char * name)61*89a1d03eSRichard void intentional1(char *name) {
62*89a1d03eSRichard   char *new_name = (char *)malloc(strlen(name + 1) + 1);
63*89a1d03eSRichard   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
64*89a1d03eSRichard   // We have + 1 outside as well so we assume this is intentional
65*89a1d03eSRichard }
66*89a1d03eSRichard 
intentional2(char * name)67*89a1d03eSRichard void intentional2(char *name) {
68*89a1d03eSRichard   char *new_name = (char *)malloc(strlen(name + 2));
69*89a1d03eSRichard   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
70*89a1d03eSRichard   // Only give warning for + 1, not + 2
71*89a1d03eSRichard }
72*89a1d03eSRichard 
intentional3(char * name)73*89a1d03eSRichard void intentional3(char *name) {
74*89a1d03eSRichard   char *new_name = (char *)malloc(strlen((name + 1)));
75*89a1d03eSRichard   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
76*89a1d03eSRichard   // If expression is in extra parentheses, consider it as intentional
77*89a1d03eSRichard }
78*89a1d03eSRichard 
79*89a1d03eSRichard void (*(*const alloc_ptr)(size_t)) = malloc;
80*89a1d03eSRichard 
bad_indirect_alloc(char * name)81*89a1d03eSRichard void bad_indirect_alloc(char *name) {
82*89a1d03eSRichard   char *new_name = (char *)alloc_ptr(strlen(name + 1));
83*89a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: addition operator is applied to the argument of strlen
84*89a1d03eSRichard   // CHECK-FIXES: {{^  char \*new_name = \(char \*\)alloc_ptr\(}}strlen(name) + 1{{\);$}}
85*89a1d03eSRichard }
86