xref: /reactos/sdk/lib/runtmchk/rtcapi.c (revision 8a978a17)
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)
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)
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 #endif
33 
34 int
35 __cdecl
36 _RTC_DefaultErrorFuncW(
37     int errType,
38     const wchar_t *file,
39     int line,
40     const wchar_t *module,
41     const wchar_t *format,
42     ...)
43 {
44     /* Simple fallback function */
45     __debugbreak();
46     return 0;
47 }
48 
49 _RTC_error_fnW _RTC_pErrorFuncW = _RTC_DefaultErrorFuncW;
50 
51 /*
52     Default CRT RTC init, if we don't link to CRT
53 */
54 _RTC_error_fnW
55 __cdecl
56 _CRT_RTC_INITW0(
57     void *_Res0,
58     void **_Res1,
59     int _Res2,
60     int _Res3,
61     int _Res4)
62 {
63     return &_RTC_DefaultErrorFuncW;
64 }
65 
66 void
67 __cdecl
68 _RTC_InitBase(void)
69 {
70     static char initialized = 0;
71     _RTC_error_fnW errorFunc;
72 
73     if (!initialized)
74     {
75         errorFunc = _CRT_RTC_INITW(0, 0, 0, 1, 0);
76         _RTC_SetErrorFuncW(errorFunc);
77         initialized = 1;
78     }
79 }
80 
81 void
82 __cdecl
83 _RTC_Shutdown(void)
84 {
85     __debugbreak();
86 }
87 
88 void
89 __cdecl
90 _RTC_Initialize(void)
91 {
92     /* Usually this function would walk an array of function pointers and call
93        each of these, like done with global ctors, but since these are currently
94        only _RTC_InitBase, we simply call that function once. */
95     _RTC_InitBase();
96 }
97 
98 void
99 __cdecl
100 _RTC_Failure(
101     void* retaddr,
102     int errnum)
103 {
104     _RTC_pErrorFuncW(errnum,
105                      L"unknown file",
106                      -1,
107                      L"unknown module",
108                      L"Invalid stack pointer value caught at %p, error %d\n",
109                      retaddr,
110                      errnum);
111 }
112 
113 void
114 __cdecl
115 _RTC_UninitUse(
116     const char *_Varname)
117 {
118     _RTC_pErrorFuncW(_RTC_UNINIT_LOCAL_USE,
119                      L"unknown file",
120                      -1,
121                      L"unknown module",
122                      L"Use of uninitialized variable %S!\n",
123                      _Varname);
124 }
125 
126 void
127 __fastcall
128 _RTC_CheckStackVars(
129     void *_Esp,
130     _RTC_framedesc *_Fd)
131 {
132     int i, *guard1, *guard2;
133 
134     /* Loop all variables in the descriptor */
135     for (i = 0; i < _Fd->varCount; i++)
136     {
137         /* Get the 2 guards below and above the variable */
138         guard1 = (int*)((char*)_Esp + _Fd->variables[i].addr - sizeof(*guard1));
139         guard2 = (int*)((char*)_Esp + _Fd->variables[i].addr +_Fd->variables[i].size);
140 
141         /* Check if they contain the guard bytes */
142         if ((*guard1 != 0xCCCCCCCC) || (*guard2 != 0xCCCCCCCC))
143         {
144             _RTC_pErrorFuncW(_RTC_CORRUPT_STACK,
145                              L"unknown file",
146                              -1,
147                              L"unknown module",
148                              L"Stack corruption near '%s'\n",
149                              _Fd->variables[i].name);
150         }
151     }
152 }
153 
154 void
155 __fastcall
156 _RTC_CheckStackVars2(
157     void *_Esp,
158     _RTC_framedesc *_Fd,
159     _RTC_ALLOCA_NODE *_AllocaList)
160 {
161     _RTC_ALLOCA_NODE *current;
162     int *guard;
163 
164     /* Process normal variables */
165     _RTC_CheckStackVars(_Esp, _Fd);
166 
167     /* Process the alloca list */
168     for (current = _AllocaList; current != 0; current = current->next)
169     {
170         /* Get the upper guard */
171         guard = (int*)((char*)current + current->allocaSize - sizeof(*guard));
172 
173         /* Check if all guard locations are still ok */
174         if ((current->guard1 != 0xCCCCCCCC) ||
175             (current->guard2[0] != 0xCCCCCCCC) ||
176             (current->guard2[1] != 0xCCCCCCCC) ||
177             (current->guard2[2] != 0xCCCCCCCC) ||
178             (*guard != 0xCCCCCCCC))
179         {
180             _RTC_pErrorFuncW(_RTC_CORRUPTED_ALLOCA,
181                              L"unknown file",
182                              -1,
183                              L"unknown module",
184                              L"Stack corruption in alloca frame\n");
185         }
186     }
187 }
188 
189 void
190 __fastcall
191 _RTC_AllocaHelper(
192     _RTC_ALLOCA_NODE *_PAllocaBase,
193     size_t _CbSize,
194     _RTC_ALLOCA_NODE **_PAllocaInfoList)
195 {
196     unsigned long i;
197 
198     /* Check if we got any allocation */
199     if ((_PAllocaBase != 0) &&
200         (_CbSize != 0) &&
201         (_PAllocaInfoList != 0))
202     {
203         /* Mark the whole range */
204         char *guard = (char*)_PAllocaBase;
205         for (i = 0; i < _CbSize; i++)
206         {
207             guard[i] = 0xCC;
208         }
209 
210         /* Initialize the alloca base frame */
211         _PAllocaBase->allocaSize = _CbSize;
212 
213         /* Insert this frame into the alloca list */
214         _PAllocaBase->next = *_PAllocaInfoList;
215         *_PAllocaInfoList = _PAllocaBase;
216     }
217 }
218 
219