This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[metze/samba/wip.git] / source3 / include / safe_string.h
1 /* 
2    Unix SMB/CIFS implementation.
3    Safe string handling routines.
4    Copyright (C) Andrew Tridgell 1994-1998
5    
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.
10    
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.
15    
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.
19 */
20
21 #ifndef _SAFE_STRING_H
22 #define _SAFE_STRING_H
23
24 #ifndef _SPLINT_ /* http://www.splint.org */
25
26 /* Some macros to ensure people don't use buffer overflow vulnerable string
27    functions. */
28
29 #ifdef bcopy
30 #undef bcopy
31 #endif /* bcopy */
32 #define bcopy(src,dest,size) __ERROR__XX__NEVER_USE_BCOPY___;
33
34 #ifdef strcpy
35 #undef strcpy
36 #endif /* strcpy */
37 #define strcpy(dest,src) __ERROR__XX__NEVER_USE_STRCPY___;
38
39 #ifdef strcat
40 #undef strcat
41 #endif /* strcat */
42 #define strcat(dest,src) __ERROR__XX__NEVER_USE_STRCAT___;
43
44 #ifdef sprintf
45 #undef sprintf
46 #endif /* sprintf */
47 #define sprintf __ERROR__XX__NEVER_USE_SPRINTF__;
48
49 #endif /* !_SPLINT_ */
50
51 /* We need a number of different prototypes for our 
52    non-existant fuctions */
53 char * __unsafe_string_function_usage_here__(void);
54
55 size_t __unsafe_string_function_usage_here_size_t__(void);
56
57 size_t __unsafe_string_function_usage_here_char__(void);
58
59 #ifdef HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS
60
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). */
64
65 #define CHECK_STRING_SIZE(d, len) (sizeof(d) != (len) && sizeof(d) != sizeof(char *))
66
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'))
73
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)))
86
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))
91
92 #else /* HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS */
93
94 #define fstrterminate(d) (((d)[sizeof(fstring)-1]) = '\0')
95 #define pstrterminate(d) (((d)[sizeof(pstring)-1]) = '\0')
96
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))
101
102 #define push_pstring_base(dest, src, pstring_base) \
103     push_ascii(dest, src, sizeof(pstring)-PTR_DIFF(dest,pstring_base)-1, STR_TERMINATE)
104
105 #endif /* HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS */
106
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)
112
113 #define safe_strcpy_base(dest, src, base, size) \
114     safe_strcpy(dest, src, size-PTR_DIFF(dest,base)-1)
115
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
118    that string */
119
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)
124
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)
130
131
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
135
136    But only for developers */
137
138 #ifdef DEVELOPER
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)
146
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)
149
150 #else
151
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)
159
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 */
163
164
165 #ifdef HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS
166
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). */
170
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)))
175
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)))
180
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))
185
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))
190
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))
195
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))
200
201 #else
202
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
209
210 #endif
211
212 /* replace some string functions with multi-byte
213    versions */
214 #define strlower(s) strlower_m(s)
215 #define strupper(s) strupper_m(s)
216
217 #define safe_strcpy_base(dest, src, base, size) \
218     safe_strcpy(dest, src, size-PTR_DIFF(dest,base)-1)
219
220 #endif