From 27adee421b0667973e7d3f55e19894d2dada03cc Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 10 Dec 2024 22:01:24 +0100 Subject: [PATCH] Avoid string duplications in sqlite drivers These string duplications are necessary to unregister the callback later. We can just keep using zend_string to avoid memory duplications. --- ext/pdo_sqlite/php_pdo_sqlite_int.h | 4 +-- ext/pdo_sqlite/sqlite_driver.c | 35 +++++++++++------------- ext/sqlite3/php_sqlite3_structs.h | 4 +-- ext/sqlite3/sqlite3.c | 41 +++++++++++++---------------- 4 files changed, 39 insertions(+), 45 deletions(-) diff --git a/ext/pdo_sqlite/php_pdo_sqlite_int.h b/ext/pdo_sqlite/php_pdo_sqlite_int.h index 43a07345ed6b3..08d5f877ad520 100644 --- a/ext/pdo_sqlite/php_pdo_sqlite_int.h +++ b/ext/pdo_sqlite/php_pdo_sqlite_int.h @@ -30,7 +30,7 @@ struct pdo_sqlite_func { struct pdo_sqlite_func *next; int argc; - const char *funcname; + zend_string *funcname; /* accelerated callback references */ zend_fcall_info_cache func; @@ -41,7 +41,7 @@ struct pdo_sqlite_func { struct pdo_sqlite_collation { struct pdo_sqlite_collation *next; - const char *name; + zend_string *name; zend_fcall_info_cache callback; }; diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 3c2b4efde16fb..708abe444c829 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -104,14 +104,14 @@ static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H) if (H->db) { /* delete the function from the handle */ sqlite3_create_function(H->db, - func->funcname, + ZSTR_VAL(func->funcname), func->argc, SQLITE_UTF8, func, NULL, NULL, NULL); } - efree((char*)func->funcname); + zend_string_release(func->funcname); if (ZEND_FCC_INITIALIZED(func->func)) { zend_fcc_dtor(&func->func); } @@ -132,13 +132,13 @@ static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H) if (H->db) { /* delete the collation from the handle */ sqlite3_create_collation(H->db, - collation->name, + ZSTR_VAL(collation->name), SQLITE_UTF8, collation, NULL); } - efree((char*)collation->name); + zend_string_release(collation->name); if (ZEND_FCC_INITIALIZED(collation->callback)) { zend_fcc_dtor(&collation->callback); } @@ -496,8 +496,7 @@ void pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS) struct pdo_sqlite_func *func; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; - char *func_name; - size_t func_name_len; + zend_string *func_name; zend_long argc = -1; zend_long flags = 0; pdo_dbh_t *dbh; @@ -505,7 +504,7 @@ void pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS) int ret; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_STRING(func_name, func_name_len) + Z_PARAM_STR(func_name) Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc) Z_PARAM_OPTIONAL Z_PARAM_LONG(argc) @@ -519,9 +518,9 @@ void pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS) func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func)); - ret = sqlite3_create_function(H->db, func_name, argc, flags | SQLITE_UTF8, func, php_sqlite3_func_callback, NULL, NULL); + ret = sqlite3_create_function(H->db, ZSTR_VAL(func_name), argc, flags | SQLITE_UTF8, func, php_sqlite3_func_callback, NULL, NULL); if (ret == SQLITE_OK) { - func->funcname = estrdup(func_name); + func->funcname = zend_string_copy(func_name); zend_fcc_dup(&func->func, &fcc); @@ -555,15 +554,14 @@ void pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS) zend_fcall_info fini_fci = empty_fcall_info; zend_fcall_info_cache step_fcc = empty_fcall_info_cache; zend_fcall_info_cache fini_fcc = empty_fcall_info_cache; - char *func_name; - size_t func_name_len; + zend_string *func_name; zend_long argc = -1; pdo_dbh_t *dbh; pdo_sqlite_db_handle *H; int ret; ZEND_PARSE_PARAMETERS_START(3, 4) - Z_PARAM_STRING(func_name, func_name_len) + Z_PARAM_STR(func_name) Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(step_fci, step_fcc) Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fini_fci, fini_fcc) Z_PARAM_OPTIONAL @@ -577,10 +575,10 @@ void pdo_sqlite_create_aggregate_internal(INTERNAL_FUNCTION_PARAMETERS) func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func)); - ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8, func, NULL, + ret = sqlite3_create_function(H->db, ZSTR_VAL(func_name), argc, SQLITE_UTF8, func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback); if (ret == SQLITE_OK) { - func->funcname = estrdup(func_name); + func->funcname = zend_string_copy(func_name); zend_fcc_dup(&func->step, &step_fcc); zend_fcc_dup(&func->fini, &fini_fcc); @@ -631,14 +629,13 @@ void pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS, pdo_sqli struct pdo_sqlite_collation *collation; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; - char *collation_name; - size_t collation_name_len; + zend_string *collation_name; pdo_dbh_t *dbh; pdo_sqlite_db_handle *H; int ret; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STRING(collation_name, collation_name_len) + Z_PARAM_STR(collation_name) Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc) ZEND_PARSE_PARAMETERS_END(); @@ -649,9 +646,9 @@ void pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAMETERS, pdo_sqli collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation)); - ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, callback); + ret = sqlite3_create_collation(H->db, ZSTR_VAL(collation_name), SQLITE_UTF8, collation, callback); if (ret == SQLITE_OK) { - collation->name = estrdup(collation_name); + collation->name = zend_string_copy(collation_name); zend_fcc_dup(&collation->callback, &fcc); diff --git a/ext/sqlite3/php_sqlite3_structs.h b/ext/sqlite3/php_sqlite3_structs.h index 6d445d6642dbf..59dcd8b6ee72b 100644 --- a/ext/sqlite3/php_sqlite3_structs.h +++ b/ext/sqlite3/php_sqlite3_structs.h @@ -44,7 +44,7 @@ struct php_sqlite3_bound_param { typedef struct _php_sqlite3_func { struct _php_sqlite3_func *next; - const char *func_name; + zend_string *func_name; int argc; zend_fcall_info_cache func; @@ -56,7 +56,7 @@ typedef struct _php_sqlite3_func { typedef struct _php_sqlite3_collation { struct _php_sqlite3_collation *next; - const char *collation_name; + zend_string *collation_name; zend_fcall_info_cache cmp_func; } php_sqlite3_collation; diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 01b8af435b633..2037bb677dff3 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -940,22 +940,21 @@ PHP_METHOD(SQLite3, createFunction) php_sqlite3_db_object *db_obj; zval *object = ZEND_THIS; php_sqlite3_func *func; - char *sql_func; - size_t sql_func_len; + zend_string *sql_func; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; zend_long sql_func_num_args = -1; zend_long flags = 0; db_obj = Z_SQLITE3_DB_P(object); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sF|ll", &sql_func, &sql_func_len, &fci, &fcc, &sql_func_num_args, &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SF|ll", &sql_func, &fci, &fcc, &sql_func_num_args, &flags) == FAILURE) { zend_release_fcall_info_cache(&fcc); RETURN_THROWS(); } SQLITE3_CHECK_INITIALIZED_FREE_TRAMPOLINE(db_obj, db_obj->initialised, SQLite3, &fcc); - if (!sql_func_len) { + if (!ZSTR_LEN(sql_func)) { /* TODO Add warning/ValueError that name cannot be empty? */ zend_release_fcall_info_cache(&fcc); RETURN_FALSE; @@ -963,8 +962,8 @@ PHP_METHOD(SQLite3, createFunction) func = (php_sqlite3_func *)ecalloc(1, sizeof(*func)); - if (sqlite3_create_function(db_obj->db, sql_func, sql_func_num_args, flags | SQLITE_UTF8, func, php_sqlite3_callback_func, NULL, NULL) == SQLITE_OK) { - func->func_name = estrdup(sql_func); + if (sqlite3_create_function(db_obj->db, ZSTR_VAL(sql_func), sql_func_num_args, flags | SQLITE_UTF8, func, php_sqlite3_callback_func, NULL, NULL) == SQLITE_OK) { + func->func_name = zend_string_copy(sql_func); zend_fcc_dup(&func->func, &fcc); func->argc = sql_func_num_args; @@ -986,8 +985,7 @@ PHP_METHOD(SQLite3, createAggregate) php_sqlite3_db_object *db_obj; zval *object = ZEND_THIS; php_sqlite3_func *func; - char *sql_func; - size_t sql_func_len; + zend_string *sql_func; zend_fcall_info step_fci = empty_fcall_info; zend_fcall_info_cache step_fcc = empty_fcall_info_cache; zend_fcall_info fini_fci = empty_fcall_info; @@ -995,7 +993,7 @@ PHP_METHOD(SQLite3, createAggregate) zend_long sql_func_num_args = -1; db_obj = Z_SQLITE3_DB_P(object); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sFF|l", &sql_func, &sql_func_len, &step_fci, &step_fcc, &fini_fci, &fini_fcc, &sql_func_num_args) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SFF|l", &sql_func, &step_fci, &step_fcc, &fini_fci, &fini_fcc, &sql_func_num_args) == FAILURE) { goto error; } @@ -1005,15 +1003,15 @@ PHP_METHOD(SQLite3, createAggregate) goto error; } - if (!sql_func_len) { + if (!ZSTR_LEN(sql_func)) { /* TODO Add warning/ValueError that name cannot be empty? */ goto error; } func = (php_sqlite3_func *)ecalloc(1, sizeof(*func)); - if (sqlite3_create_function(db_obj->db, sql_func, sql_func_num_args, SQLITE_UTF8, func, NULL, php_sqlite3_callback_step, php_sqlite3_callback_final) == SQLITE_OK) { - func->func_name = estrdup(sql_func); + if (sqlite3_create_function(db_obj->db, ZSTR_VAL(sql_func), sql_func_num_args, SQLITE_UTF8, func, NULL, php_sqlite3_callback_step, php_sqlite3_callback_final) == SQLITE_OK) { + func->func_name = zend_string_copy(sql_func); zend_fcc_dup(&func->step, &step_fcc); zend_fcc_dup(&func->fini, &fini_fcc); @@ -1040,27 +1038,26 @@ PHP_METHOD(SQLite3, createCollation) php_sqlite3_db_object *db_obj; zval *object = ZEND_THIS; php_sqlite3_collation *collation; - char *collation_name; - size_t collation_name_len; + zend_string *collation_name; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fcc = empty_fcall_info_cache; db_obj = Z_SQLITE3_DB_P(object); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sF", &collation_name, &collation_name_len, &fci, &fcc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SF", &collation_name, &fci, &fcc) == FAILURE) { RETURN_THROWS(); } SQLITE3_CHECK_INITIALIZED_FREE_TRAMPOLINE(db_obj, db_obj->initialised, SQLite3, &fcc); - if (!collation_name_len) { + if (!ZSTR_LEN(collation_name)) { /* TODO Add warning/ValueError that name cannot be empty? */ zend_release_fcall_info_cache(&fcc); RETURN_FALSE; } collation = (php_sqlite3_collation *)ecalloc(1, sizeof(*collation)); - if (sqlite3_create_collation(db_obj->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_callback_compare) == SQLITE_OK) { - collation->collation_name = estrdup(collation_name); + if (sqlite3_create_collation(db_obj->db, ZSTR_VAL(collation_name), SQLITE_UTF8, collation, php_sqlite3_callback_compare) == SQLITE_OK) { + collation->collation_name = zend_string_copy(collation_name); zend_fcc_dup(&collation->cmp_func, &fcc); @@ -2193,10 +2190,10 @@ static void php_sqlite3_object_free_storage(zend_object *object) /* {{{ */ func = intern->funcs; intern->funcs = func->next; if (intern->initialised && intern->db) { - sqlite3_create_function(intern->db, func->func_name, func->argc, SQLITE_UTF8, func, NULL, NULL, NULL); + sqlite3_create_function(intern->db, ZSTR_VAL(func->func_name), func->argc, SQLITE_UTF8, func, NULL, NULL, NULL); } - efree((char*)func->func_name); + zend_string_release(func->func_name); if (ZEND_FCC_INITIALIZED(func->func)) { zend_fcc_dtor(&func->func); @@ -2214,9 +2211,9 @@ static void php_sqlite3_object_free_storage(zend_object *object) /* {{{ */ collation = intern->collations; intern->collations = collation->next; if (intern->initialised && intern->db){ - sqlite3_create_collation(intern->db, collation->collation_name, SQLITE_UTF8, NULL, NULL); + sqlite3_create_collation(intern->db, ZSTR_VAL(collation->collation_name), SQLITE_UTF8, NULL, NULL); } - efree((char*)collation->collation_name); + zend_string_release(collation->collation_name); if (ZEND_FCC_INITIALIZED(collation->cmp_func)) { zend_fcc_dtor(&collation->cmp_func); }