FS2_Open
Open source remastering of the Freespace 2 engine
safe_strings_test.cpp
Go to the documentation of this file.
1 /* It is a condition of use that safe_strings.cpp, safe_strings.h, safe_strings_test.cpp remain together.
2  *
3  * Maintained by portej05 - contact via PM on www.hard-light.net/forums
4  * Why have we got this, what is it for?
5  * VC2005+ define some safe string functions which check buffer sizes before doing anything
6  * Unfortunately, GCC and MACOS do not provide these functions, therefore, we must!
7  * (if only to reduce the amount of noise the static analysis tools are spitting out)
8  * They are part of ISO/IEC TR 24731 and may find their way into the CRTs at some point, at which
9  * point these functions must be removed from the engine.
10  * While these functions do not add a huge amount of benefit for heap-allocated strings, they
11  * can protect against a class of buffer overruns in stack allocated situations.
12  *
13  */
14 
15 #ifdef SAFESTRINGS_TEST_APP
16 
17 #include <stdio.h>
18 #include <errno.h>
19 #include "safe_strings.h"
20 
21 int last_errno = 0;
22 void error_handler( int errnoValue, const char* errnoStr, const char* file, const char* function, int line )
23 {
24  last_errno = errnoValue;
25  (errnoStr);
26  (file);
27  (function);
28  (line);
29 }
30 
31 #define _RESET_ERRNO( ) last_errno = 0
32 
33 #define _EXPECTED_ERRNO( errnoVal ) if ( last_errno != errnoVal ) printf("errno value of %d not found: %d %s(%d)\n",errnoVal,last_errno,__FILE__,__LINE__)
34 #define _EXPECTED_LAST_ERRNO( errnoVal ) _EXPECTED_ERRNO( errnoVal )
35 #define _EXPECTED_RETURN( value, function ) if ( function != value ) printf("expected value not received: %s(%d)\n", __FILE__,__LINE__)
36 
37 #define _EXPECTED_STRING( str, value ) if ( !strcmp( str, value ) ) printf("strings do not match: %s(%d)\n", __FILE__, __LINE__)
38 #define _EXPECTED_VALUE( val, value ) if ( val != value ) printf("values do not match: %s(%d)\n", __FILE__, __LINE__ )
39 
40 /* Dumb memset (because we can't include string.h in this program) */
41 void dumb_memset( void* buf, char val, size_t bytes )
42 {
43  char* p = (char*)buf;
44 
45  while ( bytes-- )
46  {
47  *(p++) = val;
48  }
49 }
50 
51 bool strcmp( const char* str1, const char* str2 )
52 {
53  while ( *str1 && *str2 )
54  {
55  if ( *str1 != *str2 )
56  return false;
57  str1++;
58  str2++;
59  }
60 
61  return ( !*str1 && !*str2 );
62 }
63 
64 void test_strcpy_s( )
65 {
66 #define _RESET_STRINGS( ) dumb_memset( strSource, 0, 15 );\
67  dumb_memset( strDest, 0, 15 );
68 
69  char strSource[ 15 ];
70  char strDest[ 15 ];
71 
72  /* strcpy_s tests
73  * Must test both strcpy_s functions (even though one calls the other)
74  * 1) Copy string into larger buffer
75  * - Expecting buffer to contain string + NULL
76  * 2) Attempt to copy string into too small buffer
77  * - strDest[0] = NULL
78  * - calls __safe_strings_error_handler with ERANGE
79  * - returns ERANGE
80  * 3) strSource = NULL
81  * - returns EINVAL
82  * - calls __safe_strings_error_handler with EINVAL
83  * - strDest[0] = NULL
84  * 4) strDest = NULL
85  * - calls __safe_strings_error_handler with EINVAL
86  * - returns EINVAL
87  * 5) strSource = NULL, strDest = NULL
88  * - calls __safe_strings_error_handler with EINVAL
89  * - returns EINVAL
90  * 6) sizeInBytes = 0
91  * - calls __safe_strings_error_handler with ERANGE
92  * - returns ERANGE
93  * 7) A string with the size+NULL the same as the size of the buffer
94  * - returns 0
95  * - strDest should contain the string
96  */
97 
98  _RESET_ERRNO( );
99 
100  /* 1 */
101  _RESET_STRINGS( );
102  _EXPECTED_RETURN( 0, strcpy_s( strDest, "Hello World" ) );
103  _EXPECTED_LAST_ERRNO( 0 );
104  _EXPECTED_STRING( strDest, "Hello World" );
105 
106  _RESET_STRINGS( );
107  _EXPECTED_RETURN( 0, strcpy_s( strDest, 15, "Hello World" ) );
108  _EXPECTED_LAST_ERRNO( 0 );
109  _EXPECTED_STRING( strDest, "Hello World" );
110 
111 
112  /* 2 */
113  _RESET_STRINGS( );
114  _EXPECTED_RETURN( ERANGE, strcpy_s( strDest, "Hello World, this is a test" ) );
115  _EXPECTED_ERRNO( ERANGE );
116  _EXPECTED_VALUE( strDest[ 0 ], NULL );
117 
118  _RESET_STRINGS( );
119  _EXPECTED_RETURN( ERANGE, strcpy_s( strDest, 15, "Hello World, this is a test" ) );
120  _EXPECTED_ERRNO( ERANGE );
121  _EXPECTED_VALUE( strDest[ 0 ], NULL );
122 
123  /* 3 */
124  _RESET_STRINGS( );
125  _EXPECTED_RETURN( EINVAL, strcpy_s( strDest, NULL ) );
126  _EXPECTED_ERRNO( EINVAL );
127 
128  _RESET_STRINGS( );
129  _EXPECTED_RETURN( EINVAL, strcpy_s( strDest, 15, NULL ) );
130  _EXPECTED_ERRNO( EINVAL );
131 
132  /* 4 - can't be done on template version */
133  _RESET_STRINGS( );
134  _EXPECTED_RETURN( EINVAL, strcpy_s( NULL, 15, "Hello World" ) );
135  _EXPECTED_ERRNO( EINVAL );
136 
137  /* 5 - can't be done on template version */
138  _RESET_STRINGS( );
139  _EXPECTED_RETURN( EINVAL, strcpy_s( NULL, 15, NULL ) );
140  _EXPECTED_ERRNO( EINVAL );
141 
142  /* 6 - can't be done on strcpy_s template version */
143  _RESET_STRINGS( );
144  _EXPECTED_RETURN( ERANGE, strcpy_s( strDest, 0, "Hello World") );
145  _EXPECTED_ERRNO( ERANGE );
146 
147  /* 7 */
148  _RESET_STRINGS( );
149  _EXPECTED_RETURN( 0, strcpy_s( strDest, "Hello World th" ) );
150  _EXPECTED_LAST_ERRNO( ERANGE );
151 
152 #undef _RESET_STRINGS
153 }
154 
155 void test_strcat_s( )
156 {
157 #define _RESET_STRINGS( ) dumb_memset( strSource, 0, 15 );\
158  dumb_memset( strDest, 0, 15 );
159 
160  char strSource[ 15 ];
161  char strDest[ 15 ];
162 
163  /* Test cases for strcat_s
164  * 1) Normal concatenation where total string size < buffersize -1
165  * - No change in errno (i.e. handler is not called)
166  * - returns 0
167  * 2) strSource = NULL, sizeInBytes != 0, strDest != NULL
168  * - errno now EINVAL
169  * - strDest[ 0 ] == NULL
170  * - returns EINVAL
171  * 3) strSource != NULL, sizeInBytes != 0, strDest == NULL
172  * - errno now EINVAL
173  * - returns EINVAL
174  * 4) sizeInBytes = 0
175  * - errno now ERANGE
176  * - returns ERANGE
177  * 5) final string that is 15 chars+null
178  * - returns 0
179  * - no change in errno
180  */
181 
182  _RESET_ERRNO( );
183 
184  /* 1 */
185  _RESET_STRINGS( );
186  _EXPECTED_RETURN( 0, strcpy_s( strDest, "Hello " ) );
187  _EXPECTED_LAST_ERRNO( 0 );
188  _EXPECTED_RETURN( 0, strcat_s( strDest, "World" ) );
189  _EXPECTED_LAST_ERRNO( 0 );
190 
191  _RESET_STRINGS( );
192  _EXPECTED_RETURN( 0, strcpy_s( strDest, 15, "Hello " ) );
193  _EXPECTED_LAST_ERRNO( 0 );
194  _EXPECTED_RETURN( 0, strcat_s( strDest, 15, "World" ) );
195  _EXPECTED_LAST_ERRNO( 0 );
196 
197  /* 2 */
198  _RESET_STRINGS( );
199  _EXPECTED_RETURN( 0, strcpy_s( strDest, "World" ) );
200  _EXPECTED_LAST_ERRNO( 0);
201  _EXPECTED_RETURN( EINVAL, strcat_s( strDest, NULL ) );
202  _EXPECTED_ERRNO( EINVAL );
203  _EXPECTED_VALUE( strDest[ 0 ], NULL );
204 
205  _RESET_STRINGS( );
206  _EXPECTED_RETURN( 0, strcpy_s( strDest, "World" ) );
207  _EXPECTED_LAST_ERRNO( EINVAL );
208  _EXPECTED_RETURN( EINVAL, strcat_s( strDest, 15, NULL ) );
209  _EXPECTED_ERRNO( EINVAL );
210  _EXPECTED_VALUE( strDest[ 0 ], NULL );
211 
212  /* 3 - can't be done with templated version */
213  _RESET_STRINGS( );
214  _EXPECTED_RETURN( 0, strcpy_s( strSource, "Hello " ) );
215  _EXPECTED_LAST_ERRNO( EINVAL );
216  _EXPECTED_RETURN( EINVAL, strcat_s( NULL, 15, strSource ) );
217  _EXPECTED_ERRNO( EINVAL );
218 
219  /* 4 - can't be done with templated version*/
220  _RESET_STRINGS( );
221  _EXPECTED_RETURN( 0, strcpy_s( strDest, 15, "Hello " ) );
222  _EXPECTED_LAST_ERRNO( EINVAL );
223  _EXPECTED_RETURN( ERANGE, strcat_s( strDest, 0, "World" ) );
224  _EXPECTED_ERRNO( ERANGE );
225 
226  /* 5 */
227  _RESET_STRINGS( );
228  _EXPECTED_RETURN( 0, strcpy_s( strDest, "Hello " ) );
229  _EXPECTED_LAST_ERRNO( ERANGE );
230  _EXPECTED_RETURN( 0, strcpy_s( strDest, "World th" ) );
231  _EXPECTED_LAST_ERRNO( ERANGE );
232 
233  _RESET_STRINGS( );
234  _EXPECTED_RETURN( 0, strcpy_s( strDest, 15, "Hello " ) );
235  _EXPECTED_LAST_ERRNO( ERANGE );
236  _EXPECTED_RETURN( 0, strcpy_s( strDest, 15, "World th" ) );
237  _EXPECTED_LAST_ERRNO( ERANGE );
238 
239 #undef _RESET_STRINGS
240 }
241 
242 int main(int argc, char* argv[])
243 {
244  (argc);
245  (argv);
246 
247  test_strcpy_s( );
248  test_strcat_s( );
249 
250  printf("done.\n");
251 
252  return 0;
253 }
254 
255 #endif
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
GLuint GLfloat * val
Definition: Glext.h:6741
int main(int argc, char *argv[])
#define strcat_s(...)
Definition: safe_strings.h:68
GLfloat GLfloat p
Definition: Glext.h:8373
#define strcpy_s(...)
Definition: safe_strings.h:67