Avoid string duplications in sqlite drivers (#17115)

These string duplications are necessary to unregister the callback
later. We can just keep using zend_string to avoid memory duplications.
This commit is contained in:
Niels Dossche 2024-12-18 17:32:11 +01:00 committed by GitHub
parent 4dc055506c
commit b2c891f88e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 39 additions and 45 deletions

View file

@ -30,7 +30,7 @@ struct pdo_sqlite_func {
struct pdo_sqlite_func *next; struct pdo_sqlite_func *next;
int argc; int argc;
const char *funcname; zend_string *funcname;
/* accelerated callback references */ /* accelerated callback references */
zend_fcall_info_cache func; zend_fcall_info_cache func;
@ -41,7 +41,7 @@ struct pdo_sqlite_func {
struct pdo_sqlite_collation { struct pdo_sqlite_collation {
struct pdo_sqlite_collation *next; struct pdo_sqlite_collation *next;
const char *name; zend_string *name;
zend_fcall_info_cache callback; zend_fcall_info_cache callback;
}; };

View file

@ -104,14 +104,14 @@ static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H)
if (H->db) { if (H->db) {
/* delete the function from the handle */ /* delete the function from the handle */
sqlite3_create_function(H->db, sqlite3_create_function(H->db,
func->funcname, ZSTR_VAL(func->funcname),
func->argc, func->argc,
SQLITE_UTF8, SQLITE_UTF8,
func, func,
NULL, NULL, NULL); NULL, NULL, NULL);
} }
efree((char*)func->funcname); zend_string_release(func->funcname);
if (ZEND_FCC_INITIALIZED(func->func)) { if (ZEND_FCC_INITIALIZED(func->func)) {
zend_fcc_dtor(&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) { if (H->db) {
/* delete the collation from the handle */ /* delete the collation from the handle */
sqlite3_create_collation(H->db, sqlite3_create_collation(H->db,
collation->name, ZSTR_VAL(collation->name),
SQLITE_UTF8, SQLITE_UTF8,
collation, collation,
NULL); NULL);
} }
efree((char*)collation->name); zend_string_release(collation->name);
if (ZEND_FCC_INITIALIZED(collation->callback)) { if (ZEND_FCC_INITIALIZED(collation->callback)) {
zend_fcc_dtor(&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; struct pdo_sqlite_func *func;
zend_fcall_info fci = empty_fcall_info; zend_fcall_info fci = empty_fcall_info;
zend_fcall_info_cache fcc = empty_fcall_info_cache; zend_fcall_info_cache fcc = empty_fcall_info_cache;
char *func_name; zend_string *func_name;
size_t func_name_len;
zend_long argc = -1; zend_long argc = -1;
zend_long flags = 0; zend_long flags = 0;
pdo_dbh_t *dbh; pdo_dbh_t *dbh;
@ -505,7 +504,7 @@ void pdo_sqlite_create_function_internal(INTERNAL_FUNCTION_PARAMETERS)
int ret; int ret;
ZEND_PARSE_PARAMETERS_START(2, 4) 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_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
Z_PARAM_OPTIONAL Z_PARAM_OPTIONAL
Z_PARAM_LONG(argc) 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)); 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) { if (ret == SQLITE_OK) {
func->funcname = estrdup(func_name); func->funcname = zend_string_copy(func_name);
zend_fcc_dup(&func->func, &fcc); 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 fini_fci = empty_fcall_info;
zend_fcall_info_cache step_fcc = empty_fcall_info_cache; zend_fcall_info_cache step_fcc = empty_fcall_info_cache;
zend_fcall_info_cache fini_fcc = empty_fcall_info_cache; zend_fcall_info_cache fini_fcc = empty_fcall_info_cache;
char *func_name; zend_string *func_name;
size_t func_name_len;
zend_long argc = -1; zend_long argc = -1;
pdo_dbh_t *dbh; pdo_dbh_t *dbh;
pdo_sqlite_db_handle *H; pdo_sqlite_db_handle *H;
int ret; int ret;
ZEND_PARSE_PARAMETERS_START(3, 4) 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(step_fci, step_fcc)
Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fini_fci, fini_fcc) Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fini_fci, fini_fcc)
Z_PARAM_OPTIONAL 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)); 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); php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
if (ret == SQLITE_OK) { 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->step, &step_fcc);
zend_fcc_dup(&func->fini, &fini_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; struct pdo_sqlite_collation *collation;
zend_fcall_info fci = empty_fcall_info; zend_fcall_info fci = empty_fcall_info;
zend_fcall_info_cache fcc = empty_fcall_info_cache; zend_fcall_info_cache fcc = empty_fcall_info_cache;
char *collation_name; zend_string *collation_name;
size_t collation_name_len;
pdo_dbh_t *dbh; pdo_dbh_t *dbh;
pdo_sqlite_db_handle *H; pdo_sqlite_db_handle *H;
int ret; int ret;
ZEND_PARSE_PARAMETERS_START(2, 2) 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) Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
ZEND_PARSE_PARAMETERS_END(); 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)); 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) { if (ret == SQLITE_OK) {
collation->name = estrdup(collation_name); collation->name = zend_string_copy(collation_name);
zend_fcc_dup(&collation->callback, &fcc); zend_fcc_dup(&collation->callback, &fcc);

View file

@ -44,7 +44,7 @@ struct php_sqlite3_bound_param {
typedef struct _php_sqlite3_func { typedef struct _php_sqlite3_func {
struct _php_sqlite3_func *next; struct _php_sqlite3_func *next;
const char *func_name; zend_string *func_name;
int argc; int argc;
zend_fcall_info_cache func; zend_fcall_info_cache func;
@ -56,7 +56,7 @@ typedef struct _php_sqlite3_func {
typedef struct _php_sqlite3_collation { typedef struct _php_sqlite3_collation {
struct _php_sqlite3_collation *next; struct _php_sqlite3_collation *next;
const char *collation_name; zend_string *collation_name;
zend_fcall_info_cache cmp_func; zend_fcall_info_cache cmp_func;
} php_sqlite3_collation; } php_sqlite3_collation;

View file

@ -940,22 +940,21 @@ PHP_METHOD(SQLite3, createFunction)
php_sqlite3_db_object *db_obj; php_sqlite3_db_object *db_obj;
zval *object = ZEND_THIS; zval *object = ZEND_THIS;
php_sqlite3_func *func; php_sqlite3_func *func;
char *sql_func; zend_string *sql_func;
size_t sql_func_len;
zend_fcall_info fci = empty_fcall_info; zend_fcall_info fci = empty_fcall_info;
zend_fcall_info_cache fcc = empty_fcall_info_cache; zend_fcall_info_cache fcc = empty_fcall_info_cache;
zend_long sql_func_num_args = -1; zend_long sql_func_num_args = -1;
zend_long flags = 0; zend_long flags = 0;
db_obj = Z_SQLITE3_DB_P(object); 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); zend_release_fcall_info_cache(&fcc);
RETURN_THROWS(); RETURN_THROWS();
} }
SQLITE3_CHECK_INITIALIZED_FREE_TRAMPOLINE(db_obj, db_obj->initialised, SQLite3, &fcc); 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? */ /* TODO Add warning/ValueError that name cannot be empty? */
zend_release_fcall_info_cache(&fcc); zend_release_fcall_info_cache(&fcc);
RETURN_FALSE; RETURN_FALSE;
@ -963,8 +962,8 @@ PHP_METHOD(SQLite3, createFunction)
func = (php_sqlite3_func *)ecalloc(1, sizeof(*func)); 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) { 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 = estrdup(sql_func); func->func_name = zend_string_copy(sql_func);
zend_fcc_dup(&func->func, &fcc); zend_fcc_dup(&func->func, &fcc);
func->argc = sql_func_num_args; func->argc = sql_func_num_args;
@ -986,8 +985,7 @@ PHP_METHOD(SQLite3, createAggregate)
php_sqlite3_db_object *db_obj; php_sqlite3_db_object *db_obj;
zval *object = ZEND_THIS; zval *object = ZEND_THIS;
php_sqlite3_func *func; php_sqlite3_func *func;
char *sql_func; zend_string *sql_func;
size_t sql_func_len;
zend_fcall_info step_fci = empty_fcall_info; zend_fcall_info step_fci = empty_fcall_info;
zend_fcall_info_cache step_fcc = empty_fcall_info_cache; zend_fcall_info_cache step_fcc = empty_fcall_info_cache;
zend_fcall_info fini_fci = empty_fcall_info; zend_fcall_info fini_fci = empty_fcall_info;
@ -995,7 +993,7 @@ PHP_METHOD(SQLite3, createAggregate)
zend_long sql_func_num_args = -1; zend_long sql_func_num_args = -1;
db_obj = Z_SQLITE3_DB_P(object); 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; goto error;
} }
@ -1005,15 +1003,15 @@ PHP_METHOD(SQLite3, createAggregate)
goto error; goto error;
} }
if (!sql_func_len) { if (!ZSTR_LEN(sql_func)) {
/* TODO Add warning/ValueError that name cannot be empty? */ /* TODO Add warning/ValueError that name cannot be empty? */
goto error; goto error;
} }
func = (php_sqlite3_func *)ecalloc(1, sizeof(*func)); 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) { 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 = estrdup(sql_func); func->func_name = zend_string_copy(sql_func);
zend_fcc_dup(&func->step, &step_fcc); zend_fcc_dup(&func->step, &step_fcc);
zend_fcc_dup(&func->fini, &fini_fcc); zend_fcc_dup(&func->fini, &fini_fcc);
@ -1040,27 +1038,26 @@ PHP_METHOD(SQLite3, createCollation)
php_sqlite3_db_object *db_obj; php_sqlite3_db_object *db_obj;
zval *object = ZEND_THIS; zval *object = ZEND_THIS;
php_sqlite3_collation *collation; php_sqlite3_collation *collation;
char *collation_name; zend_string *collation_name;
size_t collation_name_len;
zend_fcall_info fci = empty_fcall_info; zend_fcall_info fci = empty_fcall_info;
zend_fcall_info_cache fcc = empty_fcall_info_cache; zend_fcall_info_cache fcc = empty_fcall_info_cache;
db_obj = Z_SQLITE3_DB_P(object); 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(); RETURN_THROWS();
} }
SQLITE3_CHECK_INITIALIZED_FREE_TRAMPOLINE(db_obj, db_obj->initialised, SQLite3, &fcc); 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? */ /* TODO Add warning/ValueError that name cannot be empty? */
zend_release_fcall_info_cache(&fcc); zend_release_fcall_info_cache(&fcc);
RETURN_FALSE; RETURN_FALSE;
} }
collation = (php_sqlite3_collation *)ecalloc(1, sizeof(*collation)); 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) { if (sqlite3_create_collation(db_obj->db, ZSTR_VAL(collation_name), SQLITE_UTF8, collation, php_sqlite3_callback_compare) == SQLITE_OK) {
collation->collation_name = estrdup(collation_name); collation->collation_name = zend_string_copy(collation_name);
zend_fcc_dup(&collation->cmp_func, &fcc); zend_fcc_dup(&collation->cmp_func, &fcc);
@ -2193,10 +2190,10 @@ static void php_sqlite3_object_free_storage(zend_object *object) /* {{{ */
func = intern->funcs; func = intern->funcs;
intern->funcs = func->next; intern->funcs = func->next;
if (intern->initialised && intern->db) { 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)) { if (ZEND_FCC_INITIALIZED(func->func)) {
zend_fcc_dtor(&func->func); zend_fcc_dtor(&func->func);
@ -2214,9 +2211,9 @@ static void php_sqlite3_object_free_storage(zend_object *object) /* {{{ */
collation = intern->collations; collation = intern->collations;
intern->collations = collation->next; intern->collations = collation->next;
if (intern->initialised && intern->db){ 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)) { if (ZEND_FCC_INITIALIZED(collation->cmp_func)) {
zend_fcc_dtor(&collation->cmp_func); zend_fcc_dtor(&collation->cmp_func);
} }