summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorGeorge Peter Banyard <girgias@php.net>2020-12-23 15:58:10 +0100
committerGeorge Peter Banyard <girgias@php.net>2021-01-07 15:53:48 +0000
commit63cda0fea83d19d17d19df18d712328372e7891c (patch)
tree805c6ddfeeb5fd2de0920bf976e091702e41e9cf /ext
parentdf0fa5b1787c6b26b6abfb721d7b5a00b77a1fb6 (diff)
downloadphp-git-63cda0fea83d19d17d19df18d712328372e7891c.tar.gz
Refactor PDO's quoter handler to return a zend_string
Closes GH-6547
Diffstat (limited to 'ext')
-rw-r--r--ext/pdo/pdo_dbh.c19
-rw-r--r--ext/pdo/pdo_sql_parser.re35
-rw-r--r--ext/pdo/php_pdo_driver.h2
-rw-r--r--ext/pdo_dblib/dblib_driver.c32
-rw-r--r--ext/pdo_firebird/firebird_driver.c29
-rw-r--r--ext/pdo_mysql/mysql_driver.c32
-rw-r--r--ext/pdo_oci/oci_driver.c30
-rw-r--r--ext/pdo_pgsql/pgsql_driver.c36
-rw-r--r--ext/pdo_sqlite/sqlite_driver.c12
9 files changed, 119 insertions, 108 deletions
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index a53c9f052d..5a2c25e232 100644
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -1119,18 +1119,17 @@ PHP_METHOD(PDO, query)
}
/* }}} */
-/* {{{ quotes string for use in a query. The optional paramtype acts as a hint for drivers that have alternate quoting styles. The default value is PDO_PARAM_STR */
+/* {{{ quotes string for use in a query.
+ * The optional paramtype acts as a hint for drivers that have alternate quoting styles.
+ * The default value is PDO_PARAM_STR */
PHP_METHOD(PDO, quote)
{
pdo_dbh_t *dbh = Z_PDO_DBH_P(ZEND_THIS);
- char *str;
- size_t str_len;
+ zend_string *str;
zend_long paramtype = PDO_PARAM_STR;
- char *qstr;
- size_t qlen;
ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_STRING(str, str_len)
+ Z_PARAM_STR(str)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(paramtype)
ZEND_PARSE_PARAMETERS_END();
@@ -1143,13 +1142,7 @@ PHP_METHOD(PDO, quote)
RETURN_FALSE;
}
- if (dbh->methods->quoter(dbh, str, str_len, &qstr, &qlen, paramtype)) {
- RETVAL_STRINGL(qstr, qlen);
- efree(qstr);
- return;
- }
- PDO_HANDLE_DBH_ERR();
- RETURN_FALSE;
+ RETURN_STR(dbh->methods->quoter(dbh, str, paramtype));
}
/* }}} */
diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re
index 29e99bfd9b..089a03f0a7 100644
--- a/ext/pdo/pdo_sql_parser.re
+++ b/ext/pdo/pdo_sql_parser.re
@@ -235,21 +235,18 @@ safe:
php_stream_from_zval_no_verify(stm, parameter);
if (stm) {
zend_string *buf;
+ zend_string *quoted_buf;
buf = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
if (!buf) {
buf = ZSTR_EMPTY_ALLOC();
}
- if (!stmt->dbh->methods->quoter(stmt->dbh, ZSTR_VAL(buf), ZSTR_LEN(buf), &plc->quoted, &plc->qlen,
- param->param_type)) {
- /* bork */
- ret = -1;
- strncpy(stmt->error_code, stmt->dbh->error_code, 6);
- if (buf) {
- zend_string_release_ex(buf, 0);
- }
- goto clean_up;
- }
+
+ quoted_buf = stmt->dbh->methods->quoter(stmt->dbh, buf, param->param_type);
+ plc->quoted = estrndup(ZSTR_VAL(quoted_buf), ZSTR_LEN(quoted_buf));
+ plc->qlen = ZSTR_LEN(quoted_buf);
+ zend_string_release_ex(quoted_buf, 0);
+
if (buf) {
zend_string_release_ex(buf, 0);
}
@@ -289,21 +286,29 @@ safe:
plc->freeq = 0;
break;
- default:
+ default: {
+ zend_string *quoted_buf;
+
+ /* TODO Should this be zval_try_get_string_func() ? */
buf = zval_get_string(parameter);
- if (EG(exception) ||
- !stmt->dbh->methods->quoter(stmt->dbh, ZSTR_VAL(buf),
- ZSTR_LEN(buf), &plc->quoted, &plc->qlen,
- param_type)) {
+ /* TODO Check when this can occur? */
+ if (EG(exception)) {
/* bork */
ret = -1;
strncpy(stmt->error_code, stmt->dbh->error_code, 6);
+ /* TODO Is this dead code now? */
if (buf) {
zend_string_release_ex(buf, 0);
}
goto clean_up;
}
+
+ quoted_buf = stmt->dbh->methods->quoter(stmt->dbh, buf, param_type);
+ plc->quoted = estrndup(ZSTR_VAL(quoted_buf), ZSTR_LEN(quoted_buf));
+ plc->qlen = ZSTR_LEN(quoted_buf);
plc->freeq = 1;
+ zend_string_release_ex(quoted_buf, 0);
+ }
}
if (buf) {
diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h
index c6bdf49f8e..e31ea7ed1d 100644
--- a/ext/pdo/php_pdo_driver.h
+++ b/ext/pdo/php_pdo_driver.h
@@ -236,7 +236,7 @@ typedef bool (*pdo_dbh_prepare_func)(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_
typedef zend_long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, size_t sql_len);
/* quote a string */
-typedef bool (*pdo_dbh_quote_func)(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype);
+typedef zend_string* (*pdo_dbh_quote_func)(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype);
/* transaction related (beingTransaction(), commit, rollBack, inTransaction)
* Return true if currently inside a transaction, false otherwise. */
diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
index 00ba5308fc..5017d0cd41 100644
--- a/ext/pdo_dblib/dblib_driver.c
+++ b/ext/pdo_dblib/dblib_driver.c
@@ -142,14 +142,14 @@ static zend_long dblib_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_l
return DBCOUNT(H->link);
}
-static bool dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype)
+static zend_string* dblib_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
{
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
zend_bool use_national_character_set = 0;
-
size_t i;
- char * q;
- *quotedlen = 0;
+ char *q;
+ size_t quotedlen = 0;
+ zend_string *quoted_str;
if (H->assume_national_character_set_strings) {
use_national_character_set = 1;
@@ -162,34 +162,34 @@ static bool dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unq
}
/* Detect quoted length, adding extra char for doubled single quotes */
- for (i = 0; i < unquotedlen; i++) {
- if (unquoted[i] == '\'') ++*quotedlen;
- ++*quotedlen;
+ for (i = 0; i < ZSTR_LEN(unquoted); i++) {
+ if (ZSTR_VAL(unquoted)[i] == '\'') ++quotedlen;
+ ++quotedlen;
}
- *quotedlen += 2; /* +2 for opening, closing quotes */
+ quotedlen += 2; /* +2 for opening, closing quotes */
if (use_national_character_set) {
- ++*quotedlen; /* N prefix */
+ ++quotedlen; /* N prefix */
}
- q = *quoted = emalloc(*quotedlen + 1); /* Add byte for terminal null */
+ quoted_str = zend_string_alloc(quotedlen, 0);
+ q = ZSTR_VAL(quoted_str);
if (use_national_character_set) {
*q++ = 'N';
}
*q++ = '\'';
- for (i = 0; i < unquotedlen; i++) {
- if (unquoted[i] == '\'') {
+ for (i = 0; i < ZSTR_LEN(unquoted); i++) {
+ if (ZSTR_VAL(unquoted)[i] == '\'') {
*q++ = '\'';
*q++ = '\'';
} else {
- *q++ = unquoted[i];
+ *q++ = ZSTR_VAL(unquoted)[i];
}
}
*q++ = '\'';
+ *q = '\0';
- *q = 0;
-
- return true;
+ return quoted_str;
}
static bool pdo_dblib_transaction_cmd(const char *cmd, pdo_dbh_t *dbh)
diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
index d51ca61eff..858cf53035 100644
--- a/ext/pdo_firebird/firebird_driver.c
+++ b/ext/pdo_firebird/firebird_driver.c
@@ -649,30 +649,29 @@ free_statement:
/* }}} */
/* called by the PDO SQL parser to add quotes to values that are copied into SQL */
-static bool firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, /* {{{ */
- char **quoted, size_t *quotedlen, enum pdo_param_type paramtype)
+static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
{
int qcount = 0;
char const *co, *l, *r;
char *c;
+ size_t quotedlen;
+ zend_string *quoted_str;
- if (!unquotedlen) {
- *quotedlen = 2;
- *quoted = emalloc(*quotedlen+1);
- strcpy(*quoted, "''");
- return true;
+ if (ZSTR_LEN(unquoted) == 0) {
+ return zend_string_init("''", 2, 0);
}
/* Firebird only requires single quotes to be doubled if string lengths are used */
/* count the number of ' characters */
- for (co = unquoted; (co = strchr(co,'\'')); qcount++, co++);
+ for (co = ZSTR_VAL(unquoted); (co = strchr(co,'\'')); qcount++, co++);
- *quotedlen = unquotedlen + qcount + 2;
- *quoted = c = emalloc(*quotedlen+1);
+ quotedlen = ZSTR_LEN(unquoted) + qcount + 2;
+ quoted_str = zend_string_alloc(quotedlen, 0);
+ c = ZSTR_VAL(quoted_str);
*c++ = '\'';
/* foreach (chunk that ends in a quote) */
- for (l = unquoted; (r = strchr(l,'\'')); l = r+1) {
+ for (l = ZSTR_VAL(unquoted); (r = strchr(l,'\'')); l = r+1) {
strncpy(c, l, r-l+1);
c += (r-l+1);
/* add the second quote */
@@ -680,11 +679,11 @@ static bool firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t
}
/* copy the remainder */
- strncpy(c, l, *quotedlen-(c-*quoted)-1);
- (*quoted)[*quotedlen-1] = '\'';
- (*quoted)[*quotedlen] = '\0';
+ strncpy(c, l, quotedlen-(c-ZSTR_VAL(quoted_str))-1);
+ ZSTR_VAL(quoted_str)[quotedlen-1] = '\'';
+ ZSTR_VAL(quoted_str)[quotedlen] = '\0';
- return true;
+ return quoted_str;
}
/* }}} */
diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c
index 70ca64a3e0..1c60dd5989 100644
--- a/ext/pdo_mysql/mysql_driver.c
+++ b/ext/pdo_mysql/mysql_driver.c
@@ -301,10 +301,13 @@ static char *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *
#endif
/* {{{ mysql_handle_quoter */
-static bool mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype )
+static zend_string* mysql_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype )
{
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
zend_bool use_national_character_set = 0;
+ char *quoted;
+ size_t quotedlen;
+ zend_string *quoted_str;
if (H->assume_national_character_set_strings) {
use_national_character_set = 1;
@@ -318,24 +321,27 @@ static bool mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unq
PDO_DBG_ENTER("mysql_handle_quoter");
PDO_DBG_INF_FMT("dbh=%p", dbh);
- PDO_DBG_INF_FMT("unquoted=%.*s", (int)unquotedlen, unquoted);
- *quoted = safe_emalloc(2, unquotedlen, 3 + (use_national_character_set ? 1 : 0));
+ PDO_DBG_INF_FMT("unquoted=%.*s", (int)ZSTR_LEN(unquoted), ZSTR_VAL(unquoted));
+ quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3 + (use_national_character_set ? 1 : 0));
if (use_national_character_set) {
- *quotedlen = mysql_real_escape_string_quote(H->server, *quoted + 2, unquoted, unquotedlen, '\'');
- (*quoted)[0] = 'N';
- (*quoted)[1] = '\'';
+ quotedlen = mysql_real_escape_string_quote(H->server, quoted + 2, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), '\'');
+ quoted[0] = 'N';
+ quoted[1] = '\'';
- ++*quotedlen; /* N prefix */
+ ++quotedlen; /* N prefix */
} else {
- *quotedlen = mysql_real_escape_string_quote(H->server, *quoted + 1, unquoted, unquotedlen, '\'');
- (*quoted)[0] = '\'';
+ quotedlen = mysql_real_escape_string_quote(H->server, quoted + 1, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), '\'');
+ quoted[0] = '\'';
}
- (*quoted)[++*quotedlen] = '\'';
- (*quoted)[++*quotedlen] = '\0';
- PDO_DBG_INF_FMT("quoted=%.*s", (int)*quotedlen, *quoted);
- PDO_DBG_RETURN(true);
+ quoted[++quotedlen] = '\'';
+ quoted[++quotedlen] = '\0';
+ PDO_DBG_INF_FMT("quoted=%.*s", (int)quotedlen, quoted);
+
+ quoted_str = zend_string_init(quoted, quotedlen, 0);
+ efree(quoted);
+ PDO_DBG_RETURN(quoted_str);
}
/* }}} */
diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c
index fbe70a5df8..415af87c66 100644
--- a/ext/pdo_oci/oci_driver.c
+++ b/ext/pdo_oci/oci_driver.c
@@ -350,40 +350,40 @@ static zend_long oci_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
}
/* }}} */
-static bool oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype ) /* {{{ */
+static zend_string* oci_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype ) /* {{{ */
{
int qcount = 0;
char const *cu, *l, *r;
- char *c;
+ char *c, *quoted;
+ zend_string *quoted_str;
- if (!unquotedlen) {
- *quotedlen = 2;
- *quoted = emalloc(*quotedlen+1);
- strcpy(*quoted, "''");
- return true;
+ if (ZSTR_LEN(unquoted) == 0) {
+ return zend_string_init("''", 2, 0);
}
/* count single quotes */
- for (cu = unquoted; (cu = strchr(cu,'\'')); qcount++, cu++)
+ for (cu = ZSTR_VAL(unquoted); (cu = strchr(cu,'\'')); qcount++, cu++)
; /* empty loop */
- *quotedlen = unquotedlen + qcount + 2;
- *quoted = c = emalloc(*quotedlen+1);
+ quotedlen = ZSTR_LEN(unquoted) + qcount + 2;
+ quoted = c = emalloc(quotedlen+1);
*c++ = '\'';
/* foreach (chunk that ends in a quote) */
- for (l = unquoted; (r = strchr(l,'\'')); l = r+1) {
+ for (l = ZSTR_VAL(unquoted); (r = strchr(l,'\'')); l = r+1) {
strncpy(c, l, r-l+1);
c += (r-l+1);
*c++ = '\''; /* add second quote */
}
/* Copy remainder and add enclosing quote */
- strncpy(c, l, *quotedlen-(c-*quoted)-1);
- (*quoted)[*quotedlen-1] = '\'';
- (*quoted)[*quotedlen] = '\0';
+ strncpy(c, l, quotedlen-(c-quoted)-1);
+ quoted[quotedlen-1] = '\'';
+ quoted[quotedlen] = '\0';
- return true;
+ quoted_str = zend_string_init(quoted, quotedlen, 0);
+ efree(quoted);
+ return quoted_str;
}
/* }}} */
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c
index c7f9d46f7f..1377f70969 100644
--- a/ext/pdo_pgsql/pgsql_driver.c
+++ b/ext/pdo_pgsql/pgsql_driver.c
@@ -317,33 +317,39 @@ static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_l
return ret;
}
-static bool pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype)
+static zend_string* pgsql_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
{
unsigned char *escaped;
+ char *quoted;
+ size_t quotedlen;
+ zend_string *quoted_str;
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
size_t tmp_len;
switch (paramtype) {
case PDO_PARAM_LOB:
/* escapedlen returned by PQescapeBytea() accounts for trailing 0 */
- escaped = PQescapeByteaConn(H->server, (unsigned char *)unquoted, unquotedlen, &tmp_len);
- *quotedlen = tmp_len + 1;
- *quoted = emalloc(*quotedlen + 1);
- memcpy((*quoted)+1, escaped, *quotedlen-2);
- (*quoted)[0] = '\'';
- (*quoted)[*quotedlen-1] = '\'';
- (*quoted)[*quotedlen] = '\0';
+ escaped = PQescapeByteaConn(H->server, (unsigned char *)ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), &tmp_len);
+ quotedlen = tmp_len + 1;
+ quoted = emalloc(quotedlen + 1);
+ memcpy(quoted+1, escaped, quotedlen-2);
+ quoted[0] = '\'';
+ quoted[quotedlen-1] = '\'';
+ quoted[quotedlen] = '\0';
PQfreemem(escaped);
break;
default:
- *quoted = safe_emalloc(2, unquotedlen, 3);
- (*quoted)[0] = '\'';
- *quotedlen = PQescapeStringConn(H->server, *quoted + 1, unquoted, unquotedlen, NULL);
- (*quoted)[*quotedlen + 1] = '\'';
- (*quoted)[*quotedlen + 2] = '\0';
- *quotedlen += 2;
+ quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
+ quoted[0] = '\'';
+ quotedlen = PQescapeStringConn(H->server, quoted + 1, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), NULL);
+ quoted[quotedlen + 1] = '\'';
+ quoted[quotedlen + 2] = '\0';
+ quotedlen += 2;
}
- return true;
+
+ quoted_str = zend_string_init(quoted, quotedlen, 0);
+ efree(quoted);
+ return quoted_str;
}
static char *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *len)
diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c
index 344850b099..ca069ec300 100644
--- a/ext/pdo_sqlite/sqlite_driver.c
+++ b/ext/pdo_sqlite/sqlite_driver.c
@@ -227,12 +227,14 @@ static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t
}
/* NB: doesn't handle binary strings... use prepared stmts for that */
-static bool sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype )
+static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
{
- *quoted = safe_emalloc(2, unquotedlen, 3);
- sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
- *quotedlen = strlen(*quoted);
- return true;
+ char *quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
+ /* TODO use %Q format? */
+ sqlite3_snprintf(2*ZSTR_LEN(unquoted) + 3, quoted, "'%q'", ZSTR_VAL(unquoted));
+ zend_string *quoted_str = zend_string_init(quoted, strlen(quoted), 0);
+ efree(quoted);
+ return quoted_str;
}
static bool sqlite_handle_begin(pdo_dbh_t *dbh)