1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*** |
6 | * mbusafecrt.c - implementaion of support functions and data for MBUSafeCRT |
7 | * |
8 | |
9 | * |
10 | * Purpose: |
11 | * This file contains the implementation of support functions and |
12 | * data for MBUSafeCRT declared in mbusafecrt.h and mbusafecrt_internal.h. |
13 | ****/ |
14 | |
15 | #include "pal/palinternal.h" |
16 | #include <string.h> |
17 | #include <errno.h> |
18 | #include <limits.h> |
19 | |
20 | #include "mbusafecrt_internal.h" |
21 | |
22 | /* global data */ |
23 | tSafeCRT_AssertFuncPtr sMBUSafeCRTAssertFunc = NULL; |
24 | |
25 | /*** |
26 | * MBUSafeCRTSetAssertFunc - Set the function called when an assert fails. |
27 | ****/ |
28 | |
29 | void MBUSafeCRTSetAssertFunc( tSafeCRT_AssertFuncPtr inAssertFuncPtr ) |
30 | { |
31 | /* set it */ |
32 | sMBUSafeCRTAssertFunc = inAssertFuncPtr; |
33 | } |
34 | |
35 | /*** |
36 | * _putc_nolock - putc for the miniFILE stream. |
37 | ****/ |
38 | |
39 | int _putc_nolock( char inChar, miniFILE* inStream ) |
40 | { |
41 | int returnValue = EOF; |
42 | |
43 | inStream->_cnt -= sizeof( char ); |
44 | |
45 | if ( ( inStream->_cnt ) >= 0 ) |
46 | { |
47 | *( inStream->_ptr ) = inChar; |
48 | inStream->_ptr += sizeof( char ); |
49 | returnValue = ( int )inChar; |
50 | } |
51 | |
52 | return returnValue; |
53 | } |
54 | |
55 | /*** |
56 | * _putwc_nolock - putwc for the miniFILE stream. |
57 | ****/ |
58 | |
59 | int _putwc_nolock( wchar_t inChar, miniFILE* inStream ) |
60 | { |
61 | int returnValue = WEOF; |
62 | |
63 | inStream->_cnt -= sizeof( wchar_t ); |
64 | |
65 | if ( ( inStream->_cnt ) >= 0 ) |
66 | { |
67 | *( ( wchar_t* )( inStream->_ptr ) ) = inChar; |
68 | inStream->_ptr += sizeof( wchar_t ); |
69 | returnValue = ( int )inChar; |
70 | } |
71 | |
72 | return returnValue; |
73 | } |
74 | |
75 | /*** |
76 | * _getc_nolock - getc for the miniFILE stream. |
77 | ****/ |
78 | |
79 | int _getc_nolock( miniFILE* inStream ) |
80 | { |
81 | int returnValue = EOF; |
82 | |
83 | if ( ( inStream->_cnt ) >= ( int )( sizeof( char ) ) ) |
84 | { |
85 | inStream->_cnt -= sizeof( char ); |
86 | returnValue = ( int )( *( inStream->_ptr ) ); |
87 | inStream->_ptr += sizeof( char ); |
88 | } |
89 | |
90 | return returnValue; |
91 | } |
92 | |
93 | /*** |
94 | * _getwc_nolock - getc for the miniFILE stream. |
95 | ****/ |
96 | |
97 | int _getwc_nolock( miniFILE* inStream ) |
98 | { |
99 | int returnValue = EOF; |
100 | |
101 | if ( ( inStream->_cnt ) >= ( int )( sizeof( wchar_t ) ) ) |
102 | { |
103 | inStream->_cnt -= sizeof( wchar_t ); |
104 | returnValue = ( int )( *( ( wchar_t* )( inStream->_ptr ) ) ); |
105 | inStream->_ptr += sizeof( wchar_t ); |
106 | } |
107 | |
108 | return returnValue; |
109 | } |
110 | |
111 | /*** |
112 | * _ungetc_nolock - ungetc for the miniFILE stream. |
113 | ****/ |
114 | |
115 | int _ungetc_nolock( char inChar, miniFILE* inStream ) |
116 | { |
117 | int returnValue = EOF; |
118 | |
119 | if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( char ) ) ) |
120 | { |
121 | inStream->_cnt += sizeof( char ); |
122 | inStream->_ptr -= sizeof( char ); |
123 | return ( int )inChar; |
124 | } |
125 | |
126 | return returnValue; |
127 | } |
128 | |
129 | /*** |
130 | * _ungetwc_nolock - ungetwc for the miniFILE stream. |
131 | ****/ |
132 | |
133 | int _ungetwc_nolock( wchar_t inChar, miniFILE* inStream ) |
134 | { |
135 | int returnValue = WEOF; |
136 | |
137 | if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( wchar_t ) ) ) |
138 | { |
139 | inStream->_cnt += sizeof( wchar_t ); |
140 | inStream->_ptr -= sizeof( wchar_t ); |
141 | returnValue = ( unsigned short )inChar; |
142 | } |
143 | |
144 | return returnValue; |
145 | } |
146 | |
147 | |
148 | /*** |
149 | * _safecrt_cfltcvt - convert a float to an ascii string. |
150 | ****/ |
151 | |
152 | /* routine used for floating-point output */ |
153 | #define FORMATSIZE 30 |
154 | |
155 | // taken from output.inl |
156 | #define FL_ALTERNATE 0x00080 /* alternate form requested */ |
157 | |
158 | errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type, int precision, int flags) |
159 | { |
160 | char format[FORMATSIZE]; |
161 | size_t formatlen = 0; |
162 | int retvalue; |
163 | |
164 | if (flags & 1) |
165 | { |
166 | type -= 'a' - 'A'; |
167 | } |
168 | formatlen = 0; |
169 | format[formatlen++] = '%'; |
170 | if (flags & FL_ALTERNATE) |
171 | { |
172 | format[formatlen++] = '#'; |
173 | } |
174 | format[formatlen++] = '.'; |
175 | _itoa_s(precision, format + formatlen, FORMATSIZE - formatlen, 10); |
176 | formatlen = strlen(format); |
177 | format[formatlen++] = (char)type; |
178 | format[formatlen] = 0; |
179 | |
180 | buffer[sizeInBytes - 1] = 0; |
181 | retvalue = snprintf(buffer, sizeInBytes, format, *arg); |
182 | if (buffer[sizeInBytes - 1] != 0 || retvalue <= 0) |
183 | { |
184 | buffer[0] = 0; |
185 | return EINVAL; |
186 | } |
187 | return 0; |
188 | } |
189 | |
190 | |
191 | /*** |
192 | * _safecrt_fassign - convert a string into a float or double. |
193 | ****/ |
194 | |
195 | void _safecrt_fassign(int flag, void* argument, char* number ) |
196 | { |
197 | if ( flag != 0 ) // double |
198 | { |
199 | double dblValue = strtod(number, NULL); |
200 | *( ( double* )argument ) = dblValue; |
201 | } |
202 | else // float |
203 | { |
204 | float fltValue = strtof(number, NULL); |
205 | *( ( float* )argument ) = fltValue; |
206 | } |
207 | } |
208 | |
209 | |
210 | /*** |
211 | * _safecrt_wfassign - convert a wchar_t string into a float or double. |
212 | ****/ |
213 | |
214 | void _safecrt_wfassign(int flag, void* argument, wchar_t* number ) |
215 | { |
216 | // We cannot use system functions for this - they |
217 | // assume that wchar_t is four bytes, while we assume |
218 | // two. So, we need to convert to a regular char string |
219 | // without using any system functions. To do this, |
220 | // we'll assume that the numbers are in the 0-9 range and |
221 | // do a simple conversion. |
222 | |
223 | char* numberAsChars = ( char* )number; |
224 | int position = 0; |
225 | |
226 | // do the convert |
227 | while ( number[ position ] != 0 ) |
228 | { |
229 | numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF ); |
230 | position++; |
231 | } |
232 | numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF ); |
233 | |
234 | // call the normal char version |
235 | _safecrt_fassign( flag, argument, numberAsChars ); |
236 | } |
237 | |
238 | |
239 | /*** |
240 | * _minimal_chartowchar - do a simple char to wchar conversion. |
241 | ****/ |
242 | |
243 | int _minimal_chartowchar( wchar_t* outWChar, const char* inChar ) |
244 | { |
245 | *outWChar = ( wchar_t )( ( unsigned short )( ( unsigned char )( *inChar ) ) ); |
246 | return 1; |
247 | } |
248 | |
249 | |
250 | |