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#ifndef CHECK_INL_
6#define CHECK_INL_
7
8#include "check.h"
9#include "clrhost.h"
10#include "debugmacros.h"
11#include "clrtypes.h"
12
13inline LONG *CHECK::InitTls()
14{
15#pragma push_macro("HeapAlloc")
16#pragma push_macro("GetProcessHeap")
17#undef HeapAlloc
18#undef GetProcessHeap
19
20 LONG *pCount = (LONG *)::HeapAlloc(GetProcessHeap(), 0, sizeof(LONG));
21 if (pCount)
22 *pCount = 0;
23
24#pragma pop_macro("HeapAlloc")
25#pragma pop_macro("GetProcessHeap")
26 ClrFlsSetValue(TlsIdx_Check, pCount);
27 ClrFlsAssociateCallback(TlsIdx_Check, ReleaseCheckTls);
28 return pCount;
29}
30
31inline void CHECK::ReleaseTls(void* pCountTLS)
32{
33#pragma push_macro("HeapFree")
34#pragma push_macro("GetProcessHeap")
35#undef HeapFree
36#undef GetProcessHeap
37 LONG* pCount = (LONG*) pCountTLS;
38 if (pCount)
39 ::HeapFree(GetProcessHeap(), 0, pCount);
40
41#pragma pop_macro("HeapFree")
42#pragma pop_macro("GetProcessHeap")
43}
44
45FORCEINLINE BOOL CHECK::EnterAssert()
46{
47 if (s_neverEnforceAsserts)
48 return FALSE;
49
50#ifdef _DEBUG_IMPL
51 m_pCount = (LONG *)ClrFlsGetValue(TlsIdx_Check);
52 if (!m_pCount)
53 {
54 m_pCount = InitTls();
55 if (!m_pCount)
56 return FALSE;
57 }
58
59 if (!*m_pCount)
60 {
61 *m_pCount = 1;
62 return TRUE;
63 }
64 else
65 return FALSE;
66#else
67 // Don't bother doing recursive checks on a free build, since checks should
68 // be extremely isolated
69 return TRUE;
70#endif
71}
72
73FORCEINLINE void CHECK::LeaveAssert()
74{
75#ifdef _DEBUG_IMPL
76 *m_pCount = 0;
77#endif
78}
79
80FORCEINLINE BOOL CHECK::IsInAssert()
81{
82#ifdef _DEBUG_IMPL
83 if (!m_pCount)
84 m_pCount = (LONG *)ClrFlsGetValue(TlsIdx_Check);
85
86 if (!m_pCount)
87 return FALSE;
88 else
89 return *m_pCount;
90#else
91 return FALSE;
92#endif
93}
94
95FORCEINLINE BOOL CHECK::EnforceAssert()
96{
97 if (s_neverEnforceAsserts)
98 return FALSE;
99 else
100 {
101 CHECK chk;
102 return !chk.IsInAssert();
103 }
104}
105
106FORCEINLINE void CHECK::ResetAssert()
107{
108 CHECK chk;
109 if (chk.IsInAssert())
110 chk.LeaveAssert();
111}
112
113inline void CHECK::SetAssertEnforcement(BOOL value)
114{
115 s_neverEnforceAsserts = !value;
116}
117
118// Fail records the result of a condition check. Can take either a
119// boolean value or another check result
120FORCEINLINE BOOL CHECK::Fail(BOOL condition)
121{
122#ifdef _DEBUG
123 if (!condition)
124 {
125 m_condition = NULL;
126 m_file = NULL;
127 m_line = 0;
128 }
129#endif
130 return !condition;
131}
132
133FORCEINLINE BOOL CHECK::Fail(const CHECK &check)
134{
135 m_message = check.m_message;
136#ifdef _DEBUG
137 if (m_message != NULL)
138 {
139 m_condition = check.m_condition;
140 m_file = check.m_file;
141 m_line = check.m_line;
142 }
143#endif
144 return m_message != NULL;
145}
146
147#ifndef _DEBUG
148FORCEINLINE void CHECK::Setup(LPCSTR message)
149{
150 m_message = message;
151}
152
153FORCEINLINE LPCSTR CHECK::FormatMessage(LPCSTR messageFormat, ...)
154{
155 return messageFormat;
156}
157#endif
158
159FORCEINLINE CHECK::operator BOOL ()
160{
161 return m_message == NULL;
162}
163
164FORCEINLINE BOOL CHECK::operator!()
165{
166 return m_message != NULL;
167}
168
169inline CHECK CheckAlignment(UINT alignment)
170{
171 STATIC_CONTRACT_WRAPPER;
172 CHECK((alignment & (alignment-1)) == 0);
173 CHECK_OK;
174}
175
176inline CHECK CheckAligned(UINT value, UINT alignment)
177{
178 STATIC_CONTRACT_WRAPPER;
179 CHECK(AlignmentTrim(value, alignment) == 0);
180 CHECK_OK;
181}
182
183#ifndef PLATFORM_UNIX
184// For Unix this and the previous function get the same types.
185// So, exclude this one.
186inline CHECK CheckAligned(ULONG value, UINT alignment)
187{
188 STATIC_CONTRACT_WRAPPER;
189 CHECK(AlignmentTrim(value, alignment) == 0);
190 CHECK_OK;
191}
192#endif // PLATFORM_UNIX
193
194inline CHECK CheckAligned(UINT64 value, UINT alignment)
195{
196 STATIC_CONTRACT_WRAPPER;
197 CHECK(AlignmentTrim(value, alignment) == 0);
198 CHECK_OK;
199}
200
201inline CHECK CheckAligned(const void *address, UINT alignment)
202{
203 STATIC_CONTRACT_WRAPPER;
204 CHECK(AlignmentTrim((SIZE_T)address, alignment) == 0);
205 CHECK_OK;
206}
207
208inline CHECK CheckOverflow(UINT value1, UINT value2)
209{
210 CHECK(value1 + value2 >= value1);
211 CHECK_OK;
212}
213
214#if defined(_MSC_VER)
215inline CHECK CheckOverflow(ULONG value1, ULONG value2)
216{
217 CHECK(value1 + value2 >= value1);
218 CHECK_OK;
219}
220#endif
221
222inline CHECK CheckOverflow(UINT64 value1, UINT64 value2)
223{
224 CHECK(value1 + value2 >= value1);
225 CHECK_OK;
226}
227
228inline CHECK CheckOverflow(PTR_CVOID address, UINT offset)
229{
230 TADDR targetAddr = dac_cast<TADDR>(address);
231#if POINTER_BITS == 32
232 CHECK((UINT) (SIZE_T)(targetAddr) + offset >= (UINT) (SIZE_T) (targetAddr));
233#else
234 CHECK((UINT64) targetAddr + offset >= (UINT64) targetAddr);
235#endif
236
237 CHECK_OK;
238}
239
240#if defined(_MSC_VER)
241inline CHECK CheckOverflow(const void *address, ULONG offset)
242{
243#if POINTER_BITS == 32
244 CHECK((ULONG) (SIZE_T) address + offset >= (ULONG) (SIZE_T) address);
245#else
246 CHECK((UINT64) address + offset >= (UINT64) address);
247#endif
248
249 CHECK_OK;
250}
251#endif
252
253inline CHECK CheckOverflow(const void *address, UINT64 offset)
254{
255#if POINTER_BITS == 32
256 CHECK(offset >> 32 == 0);
257 CHECK((UINT) (SIZE_T) address + (UINT) offset >= (UINT) (SIZE_T) address);
258#else
259 CHECK((UINT64) address + offset >= (UINT64) address);
260#endif
261
262 CHECK_OK;
263}
264
265
266inline CHECK CheckUnderflow(UINT value1, UINT value2)
267{
268 CHECK(value1 - value2 <= value1);
269
270 CHECK_OK;
271}
272
273#ifndef PLATFORM_UNIX
274// For Unix this and the previous function get the same types.
275// So, exclude this one.
276inline CHECK CheckUnderflow(ULONG value1, ULONG value2)
277{
278 CHECK(value1 - value2 <= value1);
279
280 CHECK_OK;
281}
282#endif // PLATFORM_UNIX
283
284inline CHECK CheckUnderflow(UINT64 value1, UINT64 value2)
285{
286 CHECK(value1 - value2 <= value1);
287
288 CHECK_OK;
289}
290
291inline CHECK CheckUnderflow(const void *address, UINT offset)
292{
293#if POINTER_BITS == 32
294 CHECK((UINT) (SIZE_T) address - offset <= (UINT) (SIZE_T) address);
295#else
296 CHECK((UINT64) address - offset <= (UINT64) address);
297#endif
298
299 CHECK_OK;
300}
301
302#if defined(_MSC_VER)
303inline CHECK CheckUnderflow(const void *address, ULONG offset)
304{
305#if POINTER_BITS == 32
306 CHECK((ULONG) (SIZE_T) address - offset <= (ULONG) (SIZE_T) address);
307#else
308 CHECK((UINT64) address - offset <= (UINT64) address);
309#endif
310
311 CHECK_OK;
312}
313#endif
314
315inline CHECK CheckUnderflow(const void *address, UINT64 offset)
316{
317#if POINTER_BITS == 32
318 CHECK(offset >> 32 == 0);
319 CHECK((UINT) (SIZE_T) address - (UINT) offset <= (UINT) (SIZE_T) address);
320#else
321 CHECK((UINT64) address - offset <= (UINT64) address);
322#endif
323
324 CHECK_OK;
325}
326
327inline CHECK CheckUnderflow(const void *address, void *address2)
328{
329#if POINTER_BITS == 32
330 CHECK((UINT) (SIZE_T) address - (UINT) (SIZE_T) address2 <= (UINT) (SIZE_T) address);
331#else
332 CHECK((UINT64) address - (UINT64) address2 <= (UINT64) address);
333#endif
334
335 CHECK_OK;
336}
337
338inline CHECK CheckZeroedMemory(const void *memory, SIZE_T size)
339{
340 CHECK(CheckOverflow(memory, size));
341
342 BYTE *p = (BYTE *) memory;
343 BYTE *pEnd = p + size;
344
345 while (p < pEnd)
346 CHECK(*p++ == 0);
347
348 CHECK_OK;
349}
350
351inline CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset)
352{
353 CHECK(CheckOverflow(dac_cast<PTR_CVOID>(rangeBase), rangeSize));
354 CHECK(offset <= rangeSize);
355 CHECK_OK;
356}
357
358inline CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, UINT32 size)
359{
360 CHECK(CheckOverflow(dac_cast<PTR_CVOID>(rangeBase), rangeSize));
361 CHECK(CheckOverflow(offset, size));
362 CHECK(offset + size <= rangeSize);
363 CHECK_OK;
364}
365
366#endif // CHECK_INL_
367
368