2 Unix SMB/CIFS implementation.
3 Safe string handling routines.
4 Copyright (C) Andrew Tridgell 1994-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #ifndef _SAFE_STRING_H
22 #define _SAFE_STRING_H
24 #ifndef _SPLINT_ /* http://www.splint.org */
26 /* Some macros to ensure people don't use buffer overflow vulnerable string
32 #define bcopy(src,dest,size) __ERROR__XX__NEVER_USE_BCOPY___;
37 #define strcpy(dest,src) __ERROR__XX__NEVER_USE_STRCPY___;
42 #define strcat(dest,src) __ERROR__XX__NEVER_USE_STRCAT___;
47 #define sprintf __ERROR__XX__NEVER_USE_SPRINTF__;
49 #endif /* !_SPLINT_ */
51 /* We need a number of different prototypes for our
52 non-existant fuctions */
53 char * __unsafe_string_function_usage_here__(void);
55 size_t __unsafe_string_function_usage_here_size_t__(void);
57 size_t __unsafe_string_function_usage_here_char__(void);
59 #ifdef HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS
61 /* if the compiler will optimize out function calls, then use this to tell if we are
62 have the correct types (this works only where sizeof() returns the size of the buffer, not
63 the size of the pointer). */
65 #define CHECK_STRING_SIZE(d, len) (sizeof(d) != (len) && sizeof(d) != sizeof(char *))
67 #define fstrterminate(d) (CHECK_STRING_SIZE(d, sizeof(fstring)) \
68 ? __unsafe_string_function_usage_here_char__() \
69 : (((d)[sizeof(fstring)-1]) = '\0'))
70 #define pstrterminate(d) (CHECK_STRING_SIZE(d, sizeof(pstring)) \
71 ? __unsafe_string_function_usage_here_char__() \
72 : (((d)[sizeof(pstring)-1]) = '\0'))
74 #define wpstrcpy(d,s) ((sizeof(d) != sizeof(wpstring) && sizeof(d) != sizeof(smb_ucs2_t *)) \
75 ? __unsafe_string_function_usage_here__() \
76 : safe_strcpy_w((d),(s),sizeof(wpstring)))
77 #define wpstrcat(d,s) ((sizeof(d) != sizeof(wpstring) && sizeof(d) != sizeof(smb_ucs2_t *)) \
78 ? __unsafe_string_function_usage_here__() \
79 : safe_strcat_w((d),(s),sizeof(wpstring)))
80 #define wfstrcpy(d,s) ((sizeof(d) != sizeof(wfstring) && sizeof(d) != sizeof(smb_ucs2_t *)) \
81 ? __unsafe_string_function_usage_here__() \
82 : safe_strcpy_w((d),(s),sizeof(wfstring)))
83 #define wfstrcat(d,s) ((sizeof(d) != sizeof(wfstring) && sizeof(d) != sizeof(smb_ucs2_t *)) \
84 ? __unsafe_string_function_usage_here__() \
85 : safe_strcat_w((d),(s),sizeof(wfstring)))
87 #define push_pstring_base(dest, src, pstring_base) \
88 (CHECK_STRING_SIZE(pstring_base, sizeof(pstring)) \
89 ? __unsafe_string_function_usage_here_size_t__() \
90 : push_ascii(dest, src, sizeof(pstring)-PTR_DIFF(dest,pstring_base)-1, STR_TERMINATE))
92 #else /* HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS */
94 #define fstrterminate(d) (((d)[sizeof(fstring)-1]) = '\0')
95 #define pstrterminate(d) (((d)[sizeof(pstring)-1]) = '\0')
97 #define wpstrcpy(d,s) safe_strcpy_w((d),(s),sizeof(wpstring))
98 #define wpstrcat(d,s) safe_strcat_w((d),(s),sizeof(wpstring))
99 #define wfstrcpy(d,s) safe_strcpy_w((d),(s),sizeof(wfstring))
100 #define wfstrcat(d,s) safe_strcat_w((d),(s),sizeof(wfstring))
102 #define push_pstring_base(dest, src, pstring_base) \
103 push_ascii(dest, src, sizeof(pstring)-PTR_DIFF(dest,pstring_base)-1, STR_TERMINATE)
105 #endif /* HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS */
107 /* the addition of the DEVELOPER checks in safe_strcpy means we must
108 * update a lot of code. To make this a little easier here are some
109 * functions that provide the lengths with less pain */
110 #define pstrcpy_base(dest, src, pstring_base) \
111 safe_strcpy(dest, src, sizeof(pstring)-PTR_DIFF(dest,pstring_base)-1)
113 #define safe_strcpy_base(dest, src, base, size) \
114 safe_strcpy(dest, src, size-PTR_DIFF(dest,base)-1)
116 /* String copy functions - macro hell below adds 'type checking' (limited, but the best we can
117 do in C) and may tag with function name/number to record the last 'clobber region' on
120 #define pstrcpy(d,s) safe_strcpy((d), (s),sizeof(pstring)-1)
121 #define pstrcat(d,s) safe_strcat((d), (s),sizeof(pstring)-1)
122 #define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1)
123 #define fstrcat(d,s) safe_strcat((d),(s),sizeof(fstring)-1)
125 /* the addition of the DEVELOPER checks in safe_strcpy means we must
126 * update a lot of code. To make this a little easier here are some
127 * functions that provide the lengths with less pain */
128 #define pstrcpy_base(dest, src, pstring_base) \
129 safe_strcpy(dest, src, sizeof(pstring)-PTR_DIFF(dest,pstring_base)-1)
132 /* inside the _fn varients of these is a call to 'clobber_region' - which might
133 destory the stack on a buggy function. Help the debugging process by putting
134 the function and line it was last called from into a static buffer
136 But only for developers */
139 #define overmalloc_safe_strcpy(dest,src,maxlength) safe_strcpy_fn(__FUNCTION__,__LINE__,dest,src,maxlength)
140 #define safe_strcpy(dest,src,maxlength) safe_strcpy_fn2(__FUNCTION__,__LINE__,dest,src,maxlength)
141 #define safe_strcat(dest,src,maxlength) safe_strcat_fn2(__FUNCTION__,__LINE__,dest,src,maxlength)
142 #define push_string(base_ptr, dest, src, dest_len, flags) push_string_fn2(__FUNCTION__, __LINE__, base_ptr, dest, src, dest_len, flags)
143 #define pull_string(base_ptr, dest, src, dest_len, src_len, flags) pull_string_fn2(__FUNCTION__, __LINE__, base_ptr, dest, src, dest_len, src_len, flags)
144 #define clistr_push(cli, dest, src, dest_len, flags) clistr_push_fn2(__FUNCTION__, __LINE__, cli, dest, src, dest_len, flags)
145 #define clistr_pull(cli, dest, src, dest_len, src_len, flags) clistr_pull_fn2(__FUNCTION__, __LINE__, cli, dest, src, dest_len, src_len, flags)
147 #define alpha_strcpy(dest,src,other_safe_chars,maxlength) alpha_strcpy_fn(__FUNCTION__,__LINE__,dest,src,other_safe_chars,maxlength)
148 #define StrnCpy(dest,src,n) StrnCpy_fn(__FUNCTION__,__LINE__,dest,src,n)
152 #define overmalloc_safe_strcpy(dest,src,maxlength) safe_strcpy_fn(NULL,0,dest,src,maxlength)
153 #define safe_strcpy(dest,src,maxlength) safe_strcpy_fn2(NULL,0,dest,src,maxlength)
154 #define safe_strcat(dest,src,maxlength) safe_strcat_fn2(NULL,0,dest,src,maxlength)
155 #define push_string(base_ptr, dest, src, dest_len, flags) push_string_fn2(NULL, 0, base_ptr, dest, src, dest_len, flags)
156 #define pull_string(base_ptr, dest, src, dest_len, src_len, flags) pull_string_fn2(NULL, 0, base_ptr, dest, src, dest_len, src_len, flags)
157 #define clistr_push(cli, dest, src, dest_len, flags) clistr_push_fn2(NULL, 0, cli, dest, src, dest_len, flags)
158 #define clistr_pull(cli, dest, src, dest_len, src_len, flags) clistr_pull_fn2(NULL, 0, cli, dest, src, dest_len, src_len, flags)
160 #define alpha_strcpy(dest,src,other_safe_chars,maxlength) alpha_strcpy_fn(NULL,0,dest,src,other_safe_chars,maxlength)
161 #define StrnCpy(dest,src,n) StrnCpy_fn(NULL,0,dest,src,n)
162 #endif /* DEVELOPER */
165 #ifdef HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS
167 /* if the compiler will optimize out function calls, then use this to tell if we are
168 have the correct types (this works only where sizeof() returns the size of the buffer, not
169 the size of the pointer). */
171 #define safe_strcpy_fn2(fn_name, fn_line, d, s, max_len) \
172 (CHECK_STRING_SIZE(d, max_len+1) \
173 ? __unsafe_string_function_usage_here__() \
174 : safe_strcpy_fn(fn_name, fn_line, (d), (s), (max_len)))
176 #define safe_strcat_fn2(fn_name, fn_line, d, s, max_len) \
177 (CHECK_STRING_SIZE(d, max_len+1) \
178 ? __unsafe_string_function_usage_here__() \
179 : safe_strcat_fn(fn_name, fn_line, (d), (s), (max_len)))
181 #define push_string_fn2(fn_name, fn_line, base_ptr, dest, src, dest_len, flags) \
182 (CHECK_STRING_SIZE(dest, dest_len) \
183 ? __unsafe_string_function_usage_here_size_t__() \
184 : push_string_fn(fn_name, fn_line, base_ptr, dest, src, dest_len, flags))
186 #define pull_string_fn2(fn_name, fn_line, base_ptr, dest, src, dest_len, src_len, flags) \
187 (CHECK_STRING_SIZE(dest, dest_len) \
188 ? __unsafe_string_function_usage_here_size_t__() \
189 : pull_string_fn(fn_name, fn_line, base_ptr, dest, src, dest_len, src_len, flags))
191 #define clistr_push_fn2(fn_name, fn_line, cli, dest, src, dest_len, flags) \
192 (CHECK_STRING_SIZE(dest, dest_len) \
193 ? __unsafe_string_function_usage_here_size_t__() \
194 : clistr_push_fn(fn_name, fn_line, cli, dest, src, dest_len, flags))
196 #define clistr_pull_fn2(fn_name, fn_line, cli, dest, src, dest_len, srclen, flags) \
197 (CHECK_STRING_SIZE(dest, dest_len) \
198 ? __unsafe_string_function_usage_here_size_t__() \
199 : clistr_pull_fn(fn_name, fn_line, cli, dest, src, dest_len, srclen, flags))
203 #define safe_strcpy_fn2 safe_strcpy_fn
204 #define safe_strcat_fn2 safe_strcat_fn
205 #define push_string_fn2 push_string_fn
206 #define pull_string_fn2 pull_string_fn
207 #define clistr_push_fn2 clistr_push_fn
208 #define clistr_pull_fn2 clistr_pull_fn
212 /* replace some string functions with multi-byte
214 #define strlower(s) strlower_m(s)
215 #define strupper(s) strupper_m(s)
217 #define safe_strcpy_base(dest, src, base, size) \
218 safe_strcpy(dest, src, size-PTR_DIFF(dest,base)-1)