| 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 | |