]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/MyAlloc.c
BaseTools/C/Common: Avoid possible NULL pointer dereference
[mirror_edk2.git] / BaseTools / Source / C / Common / MyAlloc.c
CommitLineData
30fdf114 1/** @file\r
97fa0ee9 2File for memory allocation tracking functions.\r
30fdf114 3\r
2ff3293d 4Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
40d841f6 5This program and the accompanying materials \r
30fdf114
LG
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
30fdf114
LG
13**/\r
14\r
15#include "MyAlloc.h"\r
16\r
17#if USE_MYALLOC\r
18//\r
19// Get back to original alloc/free calls.\r
20//\r
21#undef malloc\r
22#undef calloc\r
23#undef realloc\r
24#undef free\r
25//\r
26// Start of allocation list.\r
27//\r
28STATIC MY_ALLOC_STRUCT *MyAllocData = NULL;\r
29\r
30//\r
31//\r
32//\r
33STATIC UINT32 MyAllocHeadMagik = MYALLOC_HEAD_MAGIK;\r
34STATIC UINT32 MyAllocTailMagik = MYALLOC_TAIL_MAGIK;\r
35\r
36//\r
37// ////////////////////////////////////////////////////////////////////////////\r
38//\r
39//\r
40VOID\r
41MyCheck (\r
42 BOOLEAN Final,\r
43 UINT8 File[],\r
44 UINTN Line\r
45 )\r
46// *++\r
47// Description:\r
48//\r
49// Check for corruptions in the allocated memory chain. If a corruption\r
50// is detection program operation stops w/ an exit(1) call.\r
51//\r
52// Parameters:\r
53//\r
54// Final := When FALSE, MyCheck() returns if the allocated memory chain\r
55// has not been corrupted. When TRUE, MyCheck() returns if there\r
56// are no un-freed allocations. If there are un-freed allocations,\r
57// they are displayed and exit(1) is called.\r
58//\r
59//\r
60// File := Set to __FILE__ by macro expansion.\r
61//\r
62// Line := Set to __LINE__ by macro expansion.\r
63//\r
64// Returns:\r
65//\r
66// n/a\r
67//\r
68// --*/\r
69//\r
70{\r
71 MY_ALLOC_STRUCT *Tmp;\r
72\r
73 //\r
74 // Check parameters.\r
75 //\r
2ff3293d
HW
76 if (File == NULL) {\r
77 printf (\r
78 "\nMyCheck(Final=%u, File=NULL, Line=%u)"\r
79 "Invalid parameter(s).\n",\r
80 Final,\r
81 (unsigned)Line\r
82 );\r
83\r
84 exit (1);\r
85 }\r
86\r
87 if (Line == 0) {\r
30fdf114
LG
88 printf (\r
89 "\nMyCheck(Final=%u, File=%s, Line=%u)"\r
90 "Invalid parameter(s).\n",\r
91 Final,\r
92 File,\r
fd171542 93 (unsigned)Line\r
30fdf114
LG
94 );\r
95\r
96 exit (1);\r
97 }\r
98\r
99 if (strlen ((CHAR8 *)File) == 0) {\r
100 printf (\r
101 "\nMyCheck(Final=%u, File=%s, Line=%u)"\r
102 "Invalid parameter.\n",\r
103 Final,\r
104 File,\r
fd171542 105 (unsigned)Line\r
30fdf114
LG
106 );\r
107\r
108 exit (1);\r
109 }\r
110 //\r
111 // Check structure contents.\r
112 //\r
113 for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {\r
114 if (memcmp(Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik) ||\r
115 memcmp(&Tmp->Buffer[Tmp->Size + sizeof(UINT32)], &MyAllocTailMagik, sizeof MyAllocTailMagik)) {\r
116 break;\r
117 }\r
118 }\r
119 //\r
120 // If Tmp is not NULL, the structure is corrupt.\r
121 //\r
122 if (Tmp != NULL) {\r
123 printf (\r
124 "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"\r
125 "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",\r
126 Final,\r
127 File,\r
fd171542 128 (unsigned)Line,\r
30fdf114 129 Tmp->File,\r
fd171542 130 (unsigned) Tmp->Line,\r
131 (unsigned) Tmp->Size,\r
132 (unsigned) *(UINT32 *) (Tmp->Buffer),\r
133 (unsigned) *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])\r
30fdf114
LG
134 );\r
135\r
136 exit (1);\r
137 }\r
138 //\r
139 // If Final is TRUE, display the state of the structure chain.\r
140 //\r
141 if (Final) {\r
142 if (MyAllocData != NULL) {\r
143 printf (\r
144 "\nMyCheck(Final=%u, File=%s, Line=%u)"\r
145 "\nSome allocated items have not been freed.\n",\r
146 Final,\r
147 File,\r
fd171542 148 (unsigned)Line\r
30fdf114
LG
149 );\r
150\r
151 for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {\r
152 printf (\r
153 "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",\r
154 Tmp->File,\r
fd171542 155 (unsigned) Tmp->Line,\r
156 (unsigned) Tmp->Size,\r
157 (unsigned) *(UINT32 *) (Tmp->Buffer),\r
158 (unsigned) *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])\r
30fdf114
LG
159 );\r
160 }\r
161 }\r
162 }\r
163}\r
164//\r
165// ////////////////////////////////////////////////////////////////////////////\r
166//\r
167//\r
168VOID *\r
169MyAlloc (\r
170 UINTN Size,\r
171 UINT8 File[],\r
172 UINTN Line\r
173 )\r
174// *++\r
175// Description:\r
176//\r
177// Allocate a new link in the allocation chain along with enough storage\r
178// for the File[] string, requested Size and alignment overhead. If\r
179// memory cannot be allocated or the allocation chain has been corrupted,\r
180// exit(1) will be called.\r
181//\r
182// Parameters:\r
183//\r
184// Size := Number of bytes (UINT8) requested by the called.\r
185// Size cannot be zero.\r
186//\r
187// File := Set to __FILE__ by macro expansion.\r
188//\r
189// Line := Set to __LINE__ by macro expansion.\r
190//\r
191// Returns:\r
192//\r
193// Pointer to the caller's buffer.\r
194//\r
195// --*/\r
196//\r
197{\r
198 MY_ALLOC_STRUCT *Tmp;\r
199 UINTN Len;\r
200\r
201 //\r
202 // Check for invalid parameters.\r
203 //\r
2ff3293d
HW
204 if (File == NULL) {\r
205 printf (\r
206 "\nMyAlloc(Size=%u, File=NULL, Line=%u)"\r
207 "\nInvalid parameter(s).\n",\r
208 (unsigned)Size,\r
209 (unsigned)Line\r
210 );\r
211\r
212 exit (1);\r
213 }\r
214\r
215 if (Size == 0 || Line == 0) {\r
30fdf114
LG
216 printf (\r
217 "\nMyAlloc(Size=%u, File=%s, Line=%u)"\r
218 "\nInvalid parameter(s).\n",\r
fd171542 219 (unsigned)Size,\r
30fdf114 220 File,\r
fd171542 221 (unsigned)Line\r
30fdf114
LG
222 );\r
223\r
224 exit (1);\r
225 }\r
226\r
227 Len = strlen ((CHAR8 *)File);\r
228 if (Len == 0) {\r
229 printf (\r
230 "\nMyAlloc(Size=%u, File=%s, Line=%u)"\r
231 "\nInvalid parameter.\n",\r
fd171542 232 (unsigned)Size,\r
30fdf114 233 File,\r
fd171542 234 (unsigned)Line\r
30fdf114
LG
235 );\r
236\r
237 exit (1);\r
238 }\r
239 //\r
240 // Check the allocation list for corruption.\r
241 //\r
242 MyCheck (0, (UINT8 *)__FILE__, __LINE__);\r
243\r
244 //\r
245 // Allocate a new entry.\r
246 //\r
247 Tmp = calloc (\r
248 1,\r
249 sizeof (MY_ALLOC_STRUCT) + Len + 1 + sizeof (UINT64) + Size + (sizeof MyAllocHeadMagik) + (sizeof MyAllocTailMagik)\r
250 );\r
251\r
252 if (Tmp == NULL) {\r
253 printf (\r
254 "\nMyAlloc(Size=%u, File=%s, Line=%u)"\r
255 "\nOut of memory.\n",\r
fd171542 256 (unsigned)Size,\r
30fdf114 257 File,\r
fd171542 258 (unsigned)Line\r
30fdf114
LG
259 );\r
260\r
261 exit (1);\r
262 }\r
263 //\r
264 // Fill in the new entry.\r
265 //\r
266 Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT);\r
267 strcpy ((CHAR8 *)Tmp->File, (CHAR8 *)File);\r
268 Tmp->Line = Line;\r
269 Tmp->Size = Size;\r
270 Tmp->Buffer = (UINT8 *) (((UINTN) Tmp + Len + 9) &~7);\r
271\r
272 memcpy (Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik);\r
273\r
274 memcpy (\r
275 &Tmp->Buffer[Size + sizeof (UINT32)],\r
276 &MyAllocTailMagik,\r
277 sizeof MyAllocTailMagik\r
278 );\r
279\r
280 Tmp->Next = MyAllocData;\r
281 Tmp->Cksum = (UINTN) Tmp + (UINTN) (Tmp->Next) + Tmp->Line + Tmp->Size + (UINTN) (Tmp->File) + (UINTN) (Tmp->Buffer);\r
282\r
283 MyAllocData = Tmp;\r
284\r
285 return Tmp->Buffer + sizeof (UINT32);\r
286}\r
287//\r
288// ////////////////////////////////////////////////////////////////////////////\r
289//\r
290//\r
291VOID *\r
292MyRealloc (\r
293 VOID *Ptr,\r
294 UINTN Size,\r
295 UINT8 File[],\r
296 UINTN Line\r
297 )\r
298// *++\r
299// Description:\r
300//\r
301// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization\r
302// for shrinking or expanding buffers. An invalid parameter will cause\r
303// MyRealloc() to fail with a call to exit(1).\r
304//\r
305// Parameters:\r
306//\r
307// Ptr := Pointer to the caller's buffer to be re-allocated.\r
308//\r
309// Size := Size of new buffer. Size cannot be zero.\r
310//\r
311// File := Set to __FILE__ by macro expansion.\r
312//\r
313// Line := Set to __LINE__ by macro expansion.\r
314//\r
315// Returns:\r
316//\r
317// Pointer to new caller's buffer.\r
318//\r
319// --*/\r
320//\r
321{\r
322 MY_ALLOC_STRUCT *Tmp;\r
323 VOID *Buffer;\r
324\r
325 //\r
326 // Check for invalid parameter(s).\r
327 //\r
2ff3293d
HW
328 if (File == NULL) {\r
329 printf (\r
330 "\nMyRealloc(Ptr=%p, Size=%u, File=NULL, Line=%u)"\r
331 "\nInvalid parameter(s).\n",\r
332 Ptr,\r
333 (unsigned)Size,\r
334 (unsigned)Line\r
335 );\r
336\r
337 exit (1);\r
338 }\r
339\r
340 if (Size == 0 || Line == 0) {\r
30fdf114
LG
341 printf (\r
342 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"\r
343 "\nInvalid parameter(s).\n",\r
344 Ptr,\r
fd171542 345 (unsigned)Size,\r
30fdf114 346 File,\r
fd171542 347 (unsigned)Line\r
30fdf114
LG
348 );\r
349\r
350 exit (1);\r
351 }\r
352\r
353 if (strlen ((CHAR8 *)File) == 0) {\r
354 printf (\r
355 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"\r
356 "\nInvalid parameter.\n",\r
357 Ptr,\r
fd171542 358 (unsigned)Size,\r
30fdf114 359 File,\r
fd171542 360 (unsigned)Line\r
30fdf114
LG
361 );\r
362\r
363 exit (1);\r
364 }\r
365 //\r
366 // Find existing buffer in allocation list.\r
367 //\r
368 if (Ptr == NULL) {\r
369 Tmp = NULL;\r
370 } else if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {\r
371 Tmp = MyAllocData;\r
372 } else {\r
373 for (Tmp = MyAllocData;; Tmp = Tmp->Next) {\r
374 if (Tmp->Next == NULL) {\r
375 printf (\r
376 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"\r
377 "\nCould not find buffer.\n",\r
378 Ptr,\r
fd171542 379 (unsigned)Size,\r
30fdf114 380 File,\r
fd171542 381 (unsigned)Line\r
30fdf114
LG
382 );\r
383\r
384 exit (1);\r
385 }\r
386\r
387 Tmp = Tmp->Next;\r
388 }\r
389 }\r
390 //\r
391 // Allocate new buffer, copy old data, free old buffer.\r
392 //\r
393 Buffer = MyAlloc (Size, File, Line);\r
394\r
395 if (Buffer != NULL && Tmp != NULL) {\r
396 memcpy (\r
397 Buffer,\r
398 &Tmp->Buffer[sizeof (UINT32)],\r
399 ((Size <= Tmp->Size) ? Size : Tmp->Size)\r
400 );\r
401\r
402 MyFree (Ptr, (UINT8 *)__FILE__, __LINE__);\r
403 }\r
404\r
405 return Buffer;\r
406}\r
407//\r
408// ////////////////////////////////////////////////////////////////////////////\r
409//\r
410//\r
411VOID\r
412MyFree (\r
413 VOID *Ptr,\r
414 UINT8 File[],\r
415 UINTN Line\r
416 )\r
417// *++\r
418// Description:\r
419//\r
420// Release a previously allocated buffer. Invalid parameters will cause\r
421// MyFree() to fail with an exit(1) call.\r
422//\r
423// Parameters:\r
424//\r
425// Ptr := Pointer to the caller's buffer to be freed.\r
426// A NULL pointer will be ignored.\r
427//\r
428// File := Set to __FILE__ by macro expansion.\r
429//\r
430// Line := Set to __LINE__ by macro expansion.\r
431//\r
432// Returns:\r
433//\r
434// n/a\r
435//\r
436// --*/\r
437//\r
438{\r
439 MY_ALLOC_STRUCT *Tmp;\r
440 MY_ALLOC_STRUCT *Tmp2;\r
441\r
442 //\r
443 // Check for invalid parameter(s).\r
444 //\r
2ff3293d
HW
445 if (File == NULL) {\r
446 printf (\r
447 "\nMyFree(Ptr=%p, File=NULL, Line=%u)"\r
448 "\nInvalid parameter(s).\n",\r
449 Ptr,\r
450 (unsigned)Line\r
451 );\r
452\r
453 exit (1);\r
454 }\r
455\r
456 if (Line == 0) {\r
30fdf114
LG
457 printf (\r
458 "\nMyFree(Ptr=%p, File=%s, Line=%u)"\r
459 "\nInvalid parameter(s).\n",\r
460 Ptr,\r
461 File,\r
fd171542 462 (unsigned)Line\r
30fdf114
LG
463 );\r
464\r
465 exit (1);\r
466 }\r
467\r
468 if (strlen ((CHAR8 *)File) == 0) {\r
469 printf (\r
470 "\nMyFree(Ptr=%p, File=%s, Line=%u)"\r
471 "\nInvalid parameter.\n",\r
472 Ptr,\r
473 File,\r
fd171542 474 (unsigned)Line\r
30fdf114
LG
475 );\r
476\r
477 exit (1);\r
478 }\r
479 //\r
480 // Freeing NULL is always valid.\r
481 //\r
482 if (Ptr == NULL) {\r
483 return ;\r
484 }\r
485 //\r
486 // Fail if nothing is allocated.\r
487 //\r
488 if (MyAllocData == NULL) {\r
489 printf (\r
490 "\nMyFree(Ptr=%p, File=%s, Line=%u)"\r
491 "\nCalled before memory allocated.\n",\r
492 Ptr,\r
493 File,\r
fd171542 494 (unsigned)Line\r
30fdf114
LG
495 );\r
496\r
497 exit (1);\r
498 }\r
499 //\r
500 // Check for corrupted allocation list.\r
501 //\r
502 MyCheck (0, (UINT8 *)__FILE__, __LINE__);\r
503\r
504 //\r
505 // Need special check for first item in list.\r
506 //\r
507 if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {\r
508 //\r
509 // Unlink first item in list.\r
510 //\r
511 Tmp = MyAllocData;\r
512 MyAllocData = MyAllocData->Next;\r
513 } else {\r
514 //\r
515 // Walk list looking for matching item.\r
516 //\r
517 for (Tmp = MyAllocData;; Tmp = Tmp->Next) {\r
518 //\r
519 // Fail if end of list is reached.\r
520 //\r
521 if (Tmp->Next == NULL) {\r
522 printf (\r
523 "\nMyFree(Ptr=%p, File=%s, Line=%u)\n"\r
524 "\nNot found.\n",\r
525 Ptr,\r
526 File,\r
fd171542 527 (unsigned)Line\r
30fdf114
LG
528 );\r
529\r
530 exit (1);\r
531 }\r
532 //\r
533 // Leave loop when match is found.\r
534 //\r
535 if (&Tmp->Next->Buffer[sizeof (UINT32)] == Ptr) {\r
536 break;\r
537 }\r
538 }\r
539 //\r
540 // Unlink item from list.\r
541 //\r
542 Tmp2 = Tmp->Next;\r
543 Tmp->Next = Tmp->Next->Next;\r
544 Tmp = Tmp2;\r
545 }\r
546 //\r
547 // Release item.\r
548 //\r
549 free (Tmp);\r
550}\r
551\r
552#endif /* USE_MYALLOC */\r
553\r
554/* eof - MyAlloc.c */\r