Skip to content

Commit 573ad18

Browse files
committed
Handle memory limit error during string reallocation correctly
Do not decrement the refcount before allocating the new string, as the allocation operation may bail out and cause a use-after-free lateron. We can only decrement the refcount once the allocation has succeeded. Fixes oss-fuzz #25384.
1 parent 54dbd3e commit 573ad18

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

Zend/zend_string.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,13 @@ static zend_always_inline zend_string *zend_string_realloc(zend_string *s, size_
186186
ZSTR_LEN(ret) = len;
187187
zend_string_forget_hash_val(ret);
188188
return ret;
189-
} else {
190-
GC_DELREF(s);
191189
}
192190
}
193191
ret = zend_string_alloc(len, persistent);
194192
memcpy(ZSTR_VAL(ret), ZSTR_VAL(s), MIN(len, ZSTR_LEN(s)) + 1);
193+
if (!ZSTR_IS_INTERNED(s)) {
194+
GC_DELREF(s);
195+
}
195196
return ret;
196197
}
197198

@@ -206,12 +207,13 @@ static zend_always_inline zend_string *zend_string_extend(zend_string *s, size_t
206207
ZSTR_LEN(ret) = len;
207208
zend_string_forget_hash_val(ret);
208209
return ret;
209-
} else {
210-
GC_DELREF(s);
211210
}
212211
}
213212
ret = zend_string_alloc(len, persistent);
214213
memcpy(ZSTR_VAL(ret), ZSTR_VAL(s), ZSTR_LEN(s) + 1);
214+
if (!ZSTR_IS_INTERNED(s)) {
215+
GC_DELREF(s);
216+
}
215217
return ret;
216218
}
217219

@@ -226,12 +228,13 @@ static zend_always_inline zend_string *zend_string_truncate(zend_string *s, size
226228
ZSTR_LEN(ret) = len;
227229
zend_string_forget_hash_val(ret);
228230
return ret;
229-
} else {
230-
GC_DELREF(s);
231231
}
232232
}
233233
ret = zend_string_alloc(len, persistent);
234234
memcpy(ZSTR_VAL(ret), ZSTR_VAL(s), len + 1);
235+
if (!ZSTR_IS_INTERNED(s)) {
236+
GC_DELREF(s);
237+
}
235238
return ret;
236239
}
237240

@@ -245,12 +248,13 @@ static zend_always_inline zend_string *zend_string_safe_realloc(zend_string *s,
245248
ZSTR_LEN(ret) = (n * m) + l;
246249
zend_string_forget_hash_val(ret);
247250
return ret;
248-
} else {
249-
GC_DELREF(s);
250251
}
251252
}
252253
ret = zend_string_safe_alloc(n, m, l, persistent);
253254
memcpy(ZSTR_VAL(ret), ZSTR_VAL(s), MIN((n * m) + l, ZSTR_LEN(s)) + 1);
255+
if (!ZSTR_IS_INTERNED(s)) {
256+
GC_DELREF(s);
257+
}
254258
return ret;
255259
}
256260

0 commit comments

Comments
 (0)