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 | /* AllocaCheck */ |
6 | /*********************************************************************/ |
7 | |
8 | /* check for alloca overruns (which otherwise are hard to track down |
9 | and often only repro on optimized builds). |
10 | |
11 | USAGE: |
12 | |
13 | void foo() { |
14 | ALLOCA_CHECK(); // Declare at function level scope |
15 | |
16 | .... |
17 | void* mem = ALLOCA(size); // does an alloca, |
18 | |
19 | } // destructor of ALLOCA_CHECK for buffer overruns. |
20 | */ |
21 | |
22 | /* */ |
23 | /*********************************************************************/ |
24 | |
25 | #ifndef AllocaCheck_h |
26 | #define AllocaCheck_h |
27 | #include <malloc.h> // for alloca itself |
28 | |
29 | #if defined(assert) && !defined(_ASSERTE) |
30 | #define _ASSERTE assert |
31 | #endif |
32 | |
33 | #if defined(_DEBUG) || defined(DEBUG) |
34 | |
35 | /*********************************************************************/ |
36 | class AllocaCheck { |
37 | public: |
38 | enum { CheckBytes = 0xCCCDCECF, |
39 | }; |
40 | |
41 | struct AllocaSentinal { |
42 | int check; |
43 | AllocaSentinal* next; |
44 | }; |
45 | |
46 | public: |
47 | /***************************************************/ |
48 | AllocaCheck() { |
49 | sentinals = 0; |
50 | } |
51 | |
52 | ~AllocaCheck() { |
53 | AllocaSentinal* ptr = sentinals; |
54 | while (ptr != 0) { |
55 | if (ptr->check != (int)CheckBytes) |
56 | _ASSERTE(!"alloca buffer overrun" ); |
57 | ptr = ptr->next; |
58 | } |
59 | } |
60 | |
61 | void* add(void* allocaBuff, unsigned size) { |
62 | AllocaSentinal* newSentinal = (AllocaSentinal*) ((char*) allocaBuff + size); |
63 | newSentinal->check = CheckBytes; |
64 | newSentinal->next = sentinals; |
65 | sentinals = newSentinal; |
66 | memset(allocaBuff, 0xDD, size); |
67 | return allocaBuff; |
68 | } |
69 | |
70 | private: |
71 | AllocaSentinal* sentinals; |
72 | }; |
73 | |
74 | #define ALLOCA_CHECK() AllocaCheck __allocaChecker |
75 | #define ALLOCA(size) __allocaChecker.add(_alloca(size+sizeof(AllocaCheck::AllocaSentinal)), size); |
76 | |
77 | #else |
78 | |
79 | #define ALLOCA_CHECK() |
80 | #define ALLOCA(size) _alloca(size) |
81 | |
82 | #endif |
83 | |
84 | #endif |
85 | |