1 /*
2 * PROJECT: MSVC runtime check support library
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * PURPOSE: Provides support functions for MSVC runtime checks
5 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
6 */
7
8 #include <rtcapi.h>
9
10 #if defined(_M_IX86)
11 #pragma comment(linker, "/alternatename:__CRT_RTC_INITW=__CRT_RTC_INITW0")
12 #elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM) || defined(_M_ARM64)
13 #pragma comment(linker, "/alternatename:_CRT_RTC_INITW=_CRT_RTC_INITW0")
14 #else
15 #error Unsupported platform
16 #endif
17
18 // Provide a fallback memset for libraries like kbdrost.dll
19 #if defined(_M_ARM) || defined(_M_ARM64)
memset_fallback(void * src,int val,size_t count)20 void* __cdecl memset_fallback(void* src, int val, size_t count)
21 {
22 char *char_src = (char *)src;
23 while(count > 0)
24 {
25 *char_src = val;
26 char_src++;
27 count--;
28 }
29 return src;
30 }
31 #pragma comment(linker, "/alternatename:memset=memset_fallback")
32 #pragma comment(linker, "/alternatename:__RTC_memset=memset_fallback")
33 #endif
34
35 int
36 __cdecl
_RTC_DefaultErrorFuncW(int errType,const wchar_t * file,int line,const wchar_t * module,const wchar_t * format,...)37 _RTC_DefaultErrorFuncW(
38 int errType,
39 const wchar_t *file,
40 int line,
41 const wchar_t *module,
42 const wchar_t *format,
43 ...)
44 {
45 /* Simple fallback function */
46 __debugbreak();
47 return 0;
48 }
49
50 _RTC_error_fnW _RTC_pErrorFuncW = _RTC_DefaultErrorFuncW;
51
52 /*
53 Default CRT RTC init, if we don't link to CRT
54 */
55 _RTC_error_fnW
56 __cdecl
_CRT_RTC_INITW0(void * _Res0,void ** _Res1,int _Res2,int _Res3,int _Res4)57 _CRT_RTC_INITW0(
58 void *_Res0,
59 void **_Res1,
60 int _Res2,
61 int _Res3,
62 int _Res4)
63 {
64 return &_RTC_DefaultErrorFuncW;
65 }
66
67 void
68 __cdecl
_RTC_InitBase(void)69 _RTC_InitBase(void)
70 {
71 static char initialized = 0;
72 _RTC_error_fnW errorFunc;
73
74 if (!initialized)
75 {
76 errorFunc = _CRT_RTC_INITW(0, 0, 0, 1, 0);
77 _RTC_SetErrorFuncW(errorFunc);
78 initialized = 1;
79 }
80 }
81
82 void
83 __cdecl
_RTC_Shutdown(void)84 _RTC_Shutdown(void)
85 {
86 __debugbreak();
87 }
88
89 void
90 __cdecl
_RTC_Initialize(void)91 _RTC_Initialize(void)
92 {
93 /* Usually this function would walk an array of function pointers and call
94 each of these, like done with global ctors, but since these are currently
95 only _RTC_InitBase, we simply call that function once. */
96 _RTC_InitBase();
97 }
98
99 void
100 __cdecl
_RTC_Failure(void * retaddr,int errnum)101 _RTC_Failure(
102 void* retaddr,
103 int errnum)
104 {
105 _RTC_pErrorFuncW(errnum,
106 L"unknown file",
107 -1,
108 L"unknown module",
109 L"Invalid stack pointer value caught at %p, error %d\n",
110 retaddr,
111 errnum);
112 }
113
114 void
115 __cdecl
_RTC_UninitUse(const char * _Varname)116 _RTC_UninitUse(
117 const char *_Varname)
118 {
119 _RTC_pErrorFuncW(_RTC_UNINIT_LOCAL_USE,
120 L"unknown file",
121 -1,
122 L"unknown module",
123 L"Use of uninitialized variable %S!\n",
124 _Varname);
125 }
126
127 void
128 __fastcall
_RTC_CheckStackVars(void * _Esp,_RTC_framedesc * _Fd)129 _RTC_CheckStackVars(
130 void *_Esp,
131 _RTC_framedesc *_Fd)
132 {
133 int i, *guard1, *guard2;
134
135 /* Loop all variables in the descriptor */
136 for (i = 0; i < _Fd->varCount; i++)
137 {
138 /* Get the 2 guards below and above the variable */
139 guard1 = (int*)((char*)_Esp + _Fd->variables[i].addr - sizeof(*guard1));
140 guard2 = (int*)((char*)_Esp + _Fd->variables[i].addr +_Fd->variables[i].size);
141
142 /* Check if they contain the guard bytes */
143 if ((*guard1 != 0xCCCCCCCC) || (*guard2 != 0xCCCCCCCC))
144 {
145 _RTC_pErrorFuncW(_RTC_CORRUPT_STACK,
146 L"unknown file",
147 -1,
148 L"unknown module",
149 L"Stack corruption near '%s'\n",
150 _Fd->variables[i].name);
151 }
152 }
153 }
154
155 void
156 __fastcall
_RTC_CheckStackVars2(void * _Esp,_RTC_framedesc * _Fd,_RTC_ALLOCA_NODE * _AllocaList)157 _RTC_CheckStackVars2(
158 void *_Esp,
159 _RTC_framedesc *_Fd,
160 _RTC_ALLOCA_NODE *_AllocaList)
161 {
162 _RTC_ALLOCA_NODE *current;
163 int *guard;
164
165 /* Process normal variables */
166 _RTC_CheckStackVars(_Esp, _Fd);
167
168 /* Process the alloca list */
169 for (current = _AllocaList; current != 0; current = current->next)
170 {
171 /* Get the upper guard */
172 guard = (int*)((char*)current + current->allocaSize - sizeof(*guard));
173
174 /* Check if all guard locations are still ok */
175 if ((current->guard1 != 0xCCCCCCCC) ||
176 (current->guard2[0] != 0xCCCCCCCC) ||
177 (current->guard2[1] != 0xCCCCCCCC) ||
178 (current->guard2[2] != 0xCCCCCCCC) ||
179 (*guard != 0xCCCCCCCC))
180 {
181 _RTC_pErrorFuncW(_RTC_CORRUPTED_ALLOCA,
182 L"unknown file",
183 -1,
184 L"unknown module",
185 L"Stack corruption in alloca frame\n");
186 }
187 }
188 }
189
190 void
191 __fastcall
_RTC_AllocaHelper(_RTC_ALLOCA_NODE * _PAllocaBase,size_t _CbSize,_RTC_ALLOCA_NODE ** _PAllocaInfoList)192 _RTC_AllocaHelper(
193 _RTC_ALLOCA_NODE *_PAllocaBase,
194 size_t _CbSize,
195 _RTC_ALLOCA_NODE **_PAllocaInfoList)
196 {
197 unsigned long i;
198
199 /* Check if we got any allocation */
200 if ((_PAllocaBase != 0) &&
201 (_CbSize != 0) &&
202 (_PAllocaInfoList != 0))
203 {
204 /* Mark the whole range */
205 char *guard = (char*)_PAllocaBase;
206 for (i = 0; i < _CbSize; i++)
207 {
208 guard[i] = 0xCC;
209 }
210
211 /* Initialize the alloca base frame */
212 _PAllocaBase->allocaSize = _CbSize;
213
214 /* Insert this frame into the alloca list */
215 _PAllocaBase->next = *_PAllocaInfoList;
216 *_PAllocaInfoList = _PAllocaBase;
217 }
218 }
219
220