Skip to content

Commit 99a2085

Browse files
DimitryAndricnikic
authored andcommitted
Fix bug #81068: Fix possible use-after-free in realpath_cache_clean()
If ZTS is enabled, this can cause cwd_globals_ctor() to be called multiple times, each with a freshly allocated virtual_cwd_globals instance. At shutdown time however, cwd_globals_dtor() will call realpath_cache_clean(), which then possibly cleans up the same realpath_cache instance more than once. Using AddressSanitzer, this shows up as a heap use-after-free. To avoid this, add a helper function to do the actual work on one instance of a realpath_cache, and call it both from cwd_globals_dtor() and realpath_cache_clean(). The former uses the virtual_cwd_globals parameter passed in via the destructor, the latter uses the CWDG() macro.
1 parent 59522ba commit 99a2085

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 7.4.21
44

5+
- Core:
6+
. Fixed bug #81068 (Double free in realpath_cache_clean()). (Dimitry Andric)
7+
58
- Standard:
69
. Fixed bug #81048 (phpinfo(INFO_VARIABLES) "Array to string conversion").
710
(cmb)

Zend/zend_virtual_cwd.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,25 @@ static void cwd_globals_ctor(virtual_cwd_globals *cwd_g) /* {{{ */
156156
}
157157
/* }}} */
158158

159+
static void realpath_cache_clean_helper(uint32_t max_entries, realpath_cache_bucket **cache, zend_long *cache_size)
160+
{
161+
uint32_t i;
162+
163+
for (i = 0; i < max_entries; i++) {
164+
realpath_cache_bucket *p = cache[i];
165+
while (p != NULL) {
166+
realpath_cache_bucket *r = p;
167+
p = p->next;
168+
free(r);
169+
}
170+
cache[i] = NULL;
171+
}
172+
*cache_size = 0;
173+
}
174+
159175
static void cwd_globals_dtor(virtual_cwd_globals *cwd_g) /* {{{ */
160176
{
161-
realpath_cache_clean();
177+
realpath_cache_clean_helper(sizeof(cwd_g->realpath_cache)/sizeof(cwd_g->realpath_cache[0]), cwd_g->realpath_cache, &cwd_g->realpath_cache_size);
162178
}
163179
/* }}} */
164180

@@ -346,18 +362,7 @@ static inline zend_ulong realpath_cache_key(const char *path, size_t path_len) /
346362

347363
CWD_API void realpath_cache_clean(void) /* {{{ */
348364
{
349-
uint32_t i;
350-
351-
for (i = 0; i < sizeof(CWDG(realpath_cache))/sizeof(CWDG(realpath_cache)[0]); i++) {
352-
realpath_cache_bucket *p = CWDG(realpath_cache)[i];
353-
while (p != NULL) {
354-
realpath_cache_bucket *r = p;
355-
p = p->next;
356-
free(r);
357-
}
358-
CWDG(realpath_cache)[i] = NULL;
359-
}
360-
CWDG(realpath_cache_size) = 0;
365+
realpath_cache_clean_helper(sizeof(CWDG(realpath_cache))/sizeof(CWDG(realpath_cache)[0]), CWDG(realpath_cache), &CWDG(realpath_cache_size));
361366
}
362367
/* }}} */
363368

0 commit comments

Comments
 (0)