From 404c96e2bb5e65324dd7447ea37ab7c3bb73261a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 23 Feb 2025 14:14:42 +0100 Subject: [PATCH] Avoid string copies for date/time format in firebird (#17902) --- ext/pdo_firebird/firebird_driver.c | 39 +++++++++++++++---------- ext/pdo_firebird/firebird_statement.c | 10 +++---- ext/pdo_firebird/php_pdo_firebird_int.h | 6 ++-- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 9d7cb20d2cd..0666057b66b 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -599,13 +599,13 @@ static void firebird_handle_closer(pdo_dbh_t *dbh) /* {{{ */ } if (H->date_format) { - efree(H->date_format); + zend_string_release_ex(H->date_format, false); } if (H->time_format) { - efree(H->time_format); + zend_string_release_ex(H->time_format, false); } if (H->timestamp_format) { - efree(H->timestamp_format); + zend_string_release_ex(H->timestamp_format, false); } if (H->einfo.errmsg) { @@ -1091,10 +1091,9 @@ static bool pdo_firebird_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val return false; } if (H->date_format) { - efree(H->date_format); + zend_string_release_ex(H->date_format, false); } - spprintf(&H->date_format, 0, "%s", ZSTR_VAL(str)); - zend_string_release_ex(str, 0); + H->date_format = str; } return true; @@ -1105,10 +1104,9 @@ static bool pdo_firebird_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val return false; } if (H->time_format) { - efree(H->time_format); + zend_string_release_ex(H->time_format, false); } - spprintf(&H->time_format, 0, "%s", ZSTR_VAL(str)); - zend_string_release_ex(str, 0); + H->time_format = str; } return true; @@ -1119,10 +1117,9 @@ static bool pdo_firebird_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val return false; } if (H->timestamp_format) { - efree(H->timestamp_format); + zend_string_release_ex(H->timestamp_format, false); } - spprintf(&H->timestamp_format, 0, "%s", ZSTR_VAL(str)); - zend_string_release_ex(str, 0); + H->timestamp_format = str; } return true; @@ -1243,15 +1240,27 @@ static int pdo_firebird_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) return 1; case PDO_FB_ATTR_DATE_FORMAT: - ZVAL_STRING(val, H->date_format ? H->date_format : PDO_FB_DEF_DATE_FMT); + if (H->date_format) { + ZVAL_STR_COPY(val, H->date_format); + } else { + ZVAL_STRING(val, PDO_FB_DEF_DATE_FMT); + } return 1; case PDO_FB_ATTR_TIME_FORMAT: - ZVAL_STRING(val, H->time_format ? H->time_format : PDO_FB_DEF_TIME_FMT); + if (H->time_format) { + ZVAL_STR_COPY(val, H->time_format); + } else { + ZVAL_STRING(val, PDO_FB_DEF_TIME_FMT); + } return 1; case PDO_FB_ATTR_TIMESTAMP_FORMAT: - ZVAL_STRING(val, H->timestamp_format ? H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT); + if (H->timestamp_format) { + ZVAL_STR_COPY(val, H->timestamp_format); + } else { + ZVAL_STRING(val, PDO_FB_DEF_TIMESTAMP_FMT); + } return 1; case PDO_FB_TRANSACTION_ISOLATION_LEVEL: diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 60a5e60e11b..4310269314c 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -93,7 +93,7 @@ static int get_formatted_time_tz(pdo_stmt_t *stmt, const ISC_TIME_TZ* timeTz, zv } time = fb_encode_time(hours, minutes, seconds, fractions); isc_decode_sql_time(&time, &t); - fmt = S->H->time_format ? S->H->time_format : PDO_FB_DEF_TIME_FMT; + fmt = S->H->time_format ? ZSTR_VAL(S->H->time_format) : PDO_FB_DEF_TIME_FMT; size_t len = strftime(timeBuf, sizeof(timeBuf), fmt, &t); if (len == 0) { @@ -123,7 +123,7 @@ static int get_formatted_timestamp_tz(pdo_stmt_t *stmt, const ISC_TIMESTAMP_TZ* ts.timestamp_time = fb_encode_time(hours, minutes, seconds, fractions); isc_decode_timestamp(&ts, &t); - fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT; + fmt = S->H->timestamp_format ? ZSTR_VAL(S->H->timestamp_format) : PDO_FB_DEF_TIMESTAMP_FMT; size_t len = strftime(timestampBuf, sizeof(timestampBuf), fmt, &t); if (len == 0) { @@ -546,18 +546,18 @@ static int pdo_firebird_stmt_get_col( break; case SQL_TYPE_DATE: isc_decode_sql_date((ISC_DATE*)var->sqldata, &t); - fmt = S->H->date_format ? S->H->date_format : PDO_FB_DEF_DATE_FMT; + fmt = S->H->date_format ? ZSTR_VAL(S->H->date_format) : PDO_FB_DEF_DATE_FMT; if (0) { case SQL_TYPE_TIME: isc_decode_sql_time((ISC_TIME*)var->sqldata, &t); - fmt = S->H->time_format ? S->H->time_format : PDO_FB_DEF_TIME_FMT; + fmt = S->H->time_format ? ZSTR_VAL(S->H->time_format) : PDO_FB_DEF_TIME_FMT; } else if (0) { case SQL_TIMESTAMP: { ISC_TIMESTAMP timestamp = php_get_isc_timestamp_from_sqldata(var->sqldata); isc_decode_timestamp(×tamp, &t); } - fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT; + fmt = S->H->timestamp_format ? ZSTR_VAL(S->H->timestamp_format) : PDO_FB_DEF_TIMESTAMP_FMT; } /* convert the timestamp into a string */ char buf[80]; diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h index a62c152ffab..1d58be1c4b7 100644 --- a/ext/pdo_firebird/php_pdo_firebird_int.h +++ b/ext/pdo_firebird/php_pdo_firebird_int.h @@ -73,9 +73,9 @@ typedef struct { zend_ulong txn_isolation_level; /* date and time format strings, can be set by the set_attribute method */ - char *date_format; - char *time_format; - char *timestamp_format; + zend_string *date_format; + zend_string *time_format; + zend_string *timestamp_format; unsigned sql_dialect:2;