Skip to content

Commit 1de7c4b

Browse files
committed
Fix memory leaks in browscap parsing
Also make the interning a bit more efficient, no need to check for a "real" interned string every time, we can also store that in the HT.
1 parent f781c8f commit 1de7c4b

File tree

1 file changed

+13
-26
lines changed

1 file changed

+13
-26
lines changed

ext/standard/browscap.c

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,15 @@ typedef struct _browscap_parser_ctx {
223223
} browscap_parser_ctx;
224224

225225
static zend_string *browscap_intern_str(
226-
browscap_parser_ctx *ctx, zend_string *str) {
226+
browscap_parser_ctx *ctx, zend_string *str, zend_bool persistent) {
227227
zend_string *interned = zend_hash_find_ptr(&ctx->str_interned, str);
228228
if (interned) {
229229
zend_string_addref(interned);
230230
} else {
231231
interned = zend_string_copy(str);
232+
if (persistent) {
233+
interned = zend_new_interned_string(str);
234+
}
232235
zend_hash_add_new_ptr(&ctx->str_interned, interned, interned);
233236
}
234237

@@ -249,6 +252,9 @@ static zend_string *browscap_intern_str_ci(
249252
zend_string_addref(interned);
250253
} else {
251254
interned = zend_string_dup(lcname, persistent);
255+
if (persistent) {
256+
interned = zend_new_interned_string(interned);
257+
}
252258
zend_hash_add_new_ptr(&ctx->str_interned, interned, interned);
253259
}
254260

@@ -322,18 +328,7 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb
322328
) {
323329
new_value = ZSTR_EMPTY_ALLOC();
324330
} else { /* Other than true/false setting */
325-
new_value = browscap_intern_str(ctx, Z_STR_P(arg2));
326-
327-
if (persistent) {
328-
new_value = zend_new_interned_string(zend_string_copy(new_value));
329-
if (ZSTR_IS_INTERNED(new_value)) {
330-
if (new_value == Z_STR_P(arg2)) {
331-
Z_TYPE_FLAGS_P(arg2) = 0;
332-
}
333-
} else {
334-
zend_string_release(new_value);
335-
}
336-
}
331+
new_value = browscap_intern_str(ctx, Z_STR_P(arg2), persistent);
337332
}
338333

339334
if (!strcasecmp(Z_STRVAL_P(arg1), "parent")) {
@@ -354,18 +349,6 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb
354349
ctx->current_entry->parent = new_value;
355350
} else {
356351
new_key = browscap_intern_str_ci(ctx, Z_STR_P(arg1), persistent);
357-
358-
if (persistent) {
359-
new_key = zend_new_interned_string(zend_string_copy(new_key));
360-
if (ZSTR_IS_INTERNED(new_key)) {
361-
if (new_key == Z_STR_P(arg1)) {
362-
Z_TYPE_FLAGS_P(arg1) = 0;
363-
}
364-
} else {
365-
zend_string_release(new_key);
366-
}
367-
}
368-
369352
browscap_add_kv(bdata, new_key, new_value, persistent);
370353
ctx->current_entry->kv_end = bdata->kv_used;
371354
}
@@ -417,6 +400,10 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb
417400
}
418401
/* }}} */
419402

403+
static void str_interned_dtor(zval *zv) {
404+
zend_string_release(Z_STR_P(zv));
405+
}
406+
420407
static int browscap_read_file(char *filename, browser_data *browdata, int persistent) /* {{{ */
421408
{
422409
zend_file_handle fh;
@@ -449,7 +436,7 @@ static int browscap_read_file(char *filename, browser_data *browdata, int persis
449436
ctx.bdata = browdata;
450437
ctx.current_entry = NULL;
451438
ctx.current_section_name = NULL;
452-
zend_hash_init(&ctx.str_interned, 8, NULL, NULL, persistent);
439+
zend_hash_init(&ctx.str_interned, 8, NULL, str_interned_dtor, persistent);
453440

454441
zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_RAW,
455442
(zend_ini_parser_cb_t) php_browscap_parser_cb, &ctx);

0 commit comments

Comments
 (0)