xref: /reactos/sdk/lib/runtmchk/rtcapi.c (revision 4363e74d)
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