History

Merge pull request #312 from doctashay/fix-realloc-leak

Wolfgang Thaller committed 3 months ago

Commit f99ecb52 parents 335fa54 17407693 files · +138 −13Browse files

Unified · Split

3 files
  1. AutomatedTests/CMakeLists.txt +2 −0
  2. AutomatedTests/Realloc.c +120 −0
  3. libretro/malloc.c +16 −13
AutomatedTests/CMakeLists.txt+2−0
@@ -59,6 +59,8 @@ test(Empty.c) · 58 unmodified lines
59 59
60test(File.c PROPERTIES PASS_REGULAR_EXPRESSION "OK")60test(File.c PROPERTIES PASS_REGULAR_EXPRESSION "OK")
61 61
62test(Realloc.c PROPERTIES PASS_REGULAR_EXPRESSION "OK")
63
62#test(Timeout.c PROPERTIES PASS_REGULAR_EXPRESSION "One" DISABLED TRUE)64#test(Timeout.c PROPERTIES PASS_REGULAR_EXPRESSION "One" DISABLED TRUE)
63 65
64test(Log.c PROPERTIES PASS_REGULAR_EXPRESSION "One\nTwo\nThree")66test(Log.c PROPERTIES PASS_REGULAR_EXPRESSION "One\nTwo\nThree")
AutomatedTests/Realloc.c+120−0
@@ -0,0 +1,120 @@
1#include "Test.h"
2
3#include <MacMemory.h>
4#include <stdlib.h>
5#include <string.h>
6
7enum
8{
9 initialSize = 64 * 1024,
10 grownSize = 128 * 1024,
11 blockerSize = 8 * 1024,
12 blockerCount = 96,
13 releasedBlockers = (grownSize / blockerSize) + 4,
14 freeMemoryTolerance = 1024
15};
16
17int main(void)
18{
19 Size freeBefore = FreeMem();
20 unsigned char *allocation = malloc(initialSize);
21 void *blockers[blockerCount];
22 unsigned char *grown;
23 Size freeAfter;
24 int failure = 0;
25 int numBlockers = 0;
26 int ok = allocation != NULL;
27 int i;
28
29 memset(blockers, 0, sizeof(blockers));
30
31 if(!ok)
32 failure = 1;
33
34 if(ok)
35 {
36 for(i = 0; i < initialSize; ++i)
37 allocation[i] = (unsigned char)(i * 37 + 11);
38
39 while(numBlockers < blockerCount &&
40 (blockers[numBlockers] = malloc(blockerSize)) != NULL)
41 {
42 memset(blockers[numBlockers], 0x5a, blockerSize);
43 ++numBlockers;
44 }
45
46 if(numBlockers <= releasedBlockers)
47 {
48 ok = 0;
49 failure = 6;
50 }
51
52 for(i = numBlockers - releasedBlockers; i < numBlockers; ++i)
53 {
54 if(i >= 0)
55 {
56 free(blockers[i]);
57 blockers[i] = NULL;
58 }
59 }
60
61 grown = realloc(allocation, grownSize);
62 if(!grown)
63 {
64 ok = 0;
65 failure = 2;
66 }
67 else if(grown == allocation)
68 {
69 ok = 0;
70 failure = 3;
71 }
72
73 if(grown)
74 {
75 for(i = 0; ok && i < initialSize; ++i)
76 {
77 if(grown[i] != (unsigned char)(i * 37 + 11))
78 {
79 ok = 0;
80 failure = 4;
81 }
82 }
83 free(grown);
84 }
85 else
86 {
87 free(allocation);
88 }
89
90 }
91 else
92 {
93 free(allocation);
94 }
95
96 for(i = 0; i < numBlockers; ++i)
97 free(blockers[i]);
98
99 freeAfter = FreeMem();
100 if(ok && freeAfter + freeMemoryTolerance < freeBefore)
101 {
102 ok = 0;
103 failure = 5;
104 }
105
106 if(ok)
107 {
108 TEST_LOG_OK();
109 }
110 else
111 {
112 char result[3];
113 result[0] = 'N';
114 result[1] = (char)('0' + failure);
115 result[2] = '\0';
116 TEST_LOG_SIZED(result, 2);
117 }
118
119 return ok ? 0 : 1;
120}
libretro/malloc.c+16−13
@@ -69,27 +69,30 @@ void *_realloc_r(struct _reent *reent_ptr, void *ptr, size_t sz) · 68 unmodified lines
69 }69 }
70 else70 else
71 {71 {
72 if(sz == 0)
73 {
74 DisposePtr(ptr);
75 return NULL;
76 }
77
78 /* Save this now in case the block has to be moved. */
79 size_t oldSz = GetPtrSize(ptr);
80
72 MemError();81 MemError();
73 SetPtrSize(ptr, sz);82 SetPtrSize(ptr, sz);
74 if(MemError())83 if(MemError())
75 {84 {
76 size_t oldSz = GetPtrSize(ptr);85 void *newPtr = NewPtr(sz);
77 if(sz > oldSz)86 if(!newPtr)
78 {
79 void *newPtr = NewPtr(sz);
80 if(!newPtr)
81 {
82 reent_ptr->_errno = ENOMEM;
83 return NULL;
84 }
85 memcpy(newPtr, ptr, oldSz);
86 return newPtr;
87 }
88 else
89 {87 {
90 reent_ptr->_errno = ENOMEM;88 reent_ptr->_errno = ENOMEM;
91 return NULL;89 return NULL;
92 }90 }
91
92 memcpy(newPtr, ptr, sz < oldSz ? sz : oldSz);
93 /* The new block owns the data, so the old one can be released. */
94 DisposePtr(ptr);
95 return newPtr;
93 }96 }
94 else97 else
95 return ptr;98 return ptr;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t