mirror of
https://github.com/php/php-src.git
synced 2025-01-25 21:23:45 +08:00
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.
This commit is contained in:
parent
f781c8f110
commit
1de7c4b919
@ -223,12 +223,15 @@ typedef struct _browscap_parser_ctx {
|
||||
} browscap_parser_ctx;
|
||||
|
||||
static zend_string *browscap_intern_str(
|
||||
browscap_parser_ctx *ctx, zend_string *str) {
|
||||
browscap_parser_ctx *ctx, zend_string *str, zend_bool persistent) {
|
||||
zend_string *interned = zend_hash_find_ptr(&ctx->str_interned, str);
|
||||
if (interned) {
|
||||
zend_string_addref(interned);
|
||||
} else {
|
||||
interned = zend_string_copy(str);
|
||||
if (persistent) {
|
||||
interned = zend_new_interned_string(str);
|
||||
}
|
||||
zend_hash_add_new_ptr(&ctx->str_interned, interned, interned);
|
||||
}
|
||||
|
||||
@ -249,6 +252,9 @@ static zend_string *browscap_intern_str_ci(
|
||||
zend_string_addref(interned);
|
||||
} else {
|
||||
interned = zend_string_dup(lcname, persistent);
|
||||
if (persistent) {
|
||||
interned = zend_new_interned_string(interned);
|
||||
}
|
||||
zend_hash_add_new_ptr(&ctx->str_interned, interned, interned);
|
||||
}
|
||||
|
||||
@ -322,18 +328,7 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb
|
||||
) {
|
||||
new_value = ZSTR_EMPTY_ALLOC();
|
||||
} else { /* Other than true/false setting */
|
||||
new_value = browscap_intern_str(ctx, Z_STR_P(arg2));
|
||||
|
||||
if (persistent) {
|
||||
new_value = zend_new_interned_string(zend_string_copy(new_value));
|
||||
if (ZSTR_IS_INTERNED(new_value)) {
|
||||
if (new_value == Z_STR_P(arg2)) {
|
||||
Z_TYPE_FLAGS_P(arg2) = 0;
|
||||
}
|
||||
} else {
|
||||
zend_string_release(new_value);
|
||||
}
|
||||
}
|
||||
new_value = browscap_intern_str(ctx, Z_STR_P(arg2), persistent);
|
||||
}
|
||||
|
||||
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
|
||||
ctx->current_entry->parent = new_value;
|
||||
} else {
|
||||
new_key = browscap_intern_str_ci(ctx, Z_STR_P(arg1), persistent);
|
||||
|
||||
if (persistent) {
|
||||
new_key = zend_new_interned_string(zend_string_copy(new_key));
|
||||
if (ZSTR_IS_INTERNED(new_key)) {
|
||||
if (new_key == Z_STR_P(arg1)) {
|
||||
Z_TYPE_FLAGS_P(arg1) = 0;
|
||||
}
|
||||
} else {
|
||||
zend_string_release(new_key);
|
||||
}
|
||||
}
|
||||
|
||||
browscap_add_kv(bdata, new_key, new_value, persistent);
|
||||
ctx->current_entry->kv_end = bdata->kv_used;
|
||||
}
|
||||
@ -417,6 +400,10 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void str_interned_dtor(zval *zv) {
|
||||
zend_string_release(Z_STR_P(zv));
|
||||
}
|
||||
|
||||
static int browscap_read_file(char *filename, browser_data *browdata, int persistent) /* {{{ */
|
||||
{
|
||||
zend_file_handle fh;
|
||||
@ -449,7 +436,7 @@ static int browscap_read_file(char *filename, browser_data *browdata, int persis
|
||||
ctx.bdata = browdata;
|
||||
ctx.current_entry = NULL;
|
||||
ctx.current_section_name = NULL;
|
||||
zend_hash_init(&ctx.str_interned, 8, NULL, NULL, persistent);
|
||||
zend_hash_init(&ctx.str_interned, 8, NULL, str_interned_dtor, persistent);
|
||||
|
||||
zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_RAW,
|
||||
(zend_ini_parser_cb_t) php_browscap_parser_cb, &ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user