File: safe_strings.cpp

package info (click to toggle)
freespace2 3.7.0%2Brepack-2
  • links: PTS, VCS
  • area: non-free
  • in suites: jessie, jessie-kfreebsd
  • size: 22,848 kB
  • ctags: 41,897
  • sloc: cpp: 369,931; makefile: 1,060; xml: 129; sh: 112
file content (119 lines) | stat: -rw-r--r-- 2,882 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "pstypes.h"

/* It is a condition of use that safe_strings.cpp, safe_strings.h, safe_strings_test.cpp remain together.
 *
 * Maintained by portej05 - contact via PM on www.hard-light.net/forums
 * Why have we got this, what is it for?
 * VC2005+ define some safe string functions which check buffer sizes before doing anything
 * Unfortunately, GCC (on Linux and Mac OS X) does not yet provide these functions, therefore, we must!
 * (if only to reduce the amount of noise the static analysis tools are spitting out)
 * They are part of ISO/IEC TR 24731 and may find their way into the CRTs at some point, at which
 * point these functions must be removed from the engine.
 * While these functions do not add a huge amount of benefit for heap-allocated strings, they
 * can protect against a class of buffer overruns in stack allocated situations.
 *
 */

/* There is no safe strings below VS2005
 * scp safe_strings are used in VS2005+ DEBUG because they give more info
 */



#if !defined(NO_SAFE_STRINGS) && ( !defined( _MSC_VER ) || ( defined( _MSC_VER ) && _MSC_VER >= 1400 /* && !defined(NDEBUG) */ ))

/* We don't have this here - no standard library stuff included */
#ifndef NULL
#define NULL 0
#endif

/* An implementation of strcpy_s 
 * We're not going to actually fully behave like the MS debug version.
 */
errno_t scp_strcpy_s( const char* file, int line, char* strDest, size_t sizeInBytes, const char* strSource )
{
	char* pDest;
	const char* pSource;
	size_t bufferLeft = sizeInBytes;
	
	if ( !strDest || !strSource )
	{
		if ( strDest )
			*strDest = NULL;
		__safe_strings_error_handler( EINVAL );
		return EINVAL;
	}

	if ( sizeInBytes == 0 )
	{
		*strDest = NULL;
		__safe_strings_error_handler( ERANGE );
		return ERANGE;
	}

	pDest = strDest;
	pSource = strSource;
	
	while ((*pDest++ = *pSource++) != 0 && --bufferLeft > 0);

	if ( bufferLeft == 0 )
	{
		*strDest = NULL;
		__safe_strings_error_handler( ERANGE );
		return ERANGE;
	}

	return 0;
}

errno_t scp_strcat_s( const char* file, int line, char* strDest, size_t sizeInBytes, const char* strSource )
{
	char* pDest;
	const char* pSource;
	size_t bufferLeft = sizeInBytes;

	if ( !strDest || !strSource )
	{
		if ( strDest )
			*strDest = NULL;
		__safe_strings_error_handler( EINVAL );
		return EINVAL;
	}

	if ( bufferLeft == 0 )
	{
		*strDest = NULL;
		__safe_strings_error_handler( ERANGE );
		return ERANGE;
	}

	/* Find the terminating NULL of the input string */
	pDest = strDest;
	pSource = strSource;
	while ( *pDest )
	{
		pDest++;
		bufferLeft--;
	}

	if ( bufferLeft == 0 )
	{
		*strDest = NULL;
		__safe_strings_error_handler( ERANGE );
		return ERANGE;
	}

	/* Concatenate the strings */
	while ((*pDest++ = *pSource++) != 0 && --bufferLeft > 0);

	if ( bufferLeft == 0 )
	{
		*strDest = NULL;
		__safe_strings_error_handler( ERANGE );
		return ERANGE;
	}

	return 0;
}

#endif