diff options
author | George Peter Banyard <girgias@php.net> | 2020-12-23 15:58:10 +0100 |
---|---|---|
committer | George Peter Banyard <girgias@php.net> | 2021-01-07 15:53:48 +0000 |
commit | 63cda0fea83d19d17d19df18d712328372e7891c (patch) | |
tree | 805c6ddfeeb5fd2de0920bf976e091702e41e9cf /ext | |
parent | df0fa5b1787c6b26b6abfb721d7b5a00b77a1fb6 (diff) | |
download | php-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.c | 19 | ||||
-rw-r--r-- | ext/pdo/pdo_sql_parser.re | 35 | ||||
-rw-r--r-- | ext/pdo/php_pdo_driver.h | 2 | ||||
-rw-r--r-- | ext/pdo_dblib/dblib_driver.c | 32 | ||||
-rw-r--r-- | ext/pdo_firebird/firebird_driver.c | 29 | ||||
-rw-r--r-- | ext/pdo_mysql/mysql_driver.c | 32 | ||||
-rw-r--r-- | ext/pdo_oci/oci_driver.c | 30 | ||||
-rw-r--r-- | ext/pdo_pgsql/pgsql_driver.c | 36 | ||||
-rw-r--r-- | ext/pdo_sqlite/sqlite_driver.c | 12 |
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) |