Skip to content

Commit 63cda0f

Browse files
committed
Refactor PDO's quoter handler to return a zend_string
Closes phpGH-6547
1 parent df0fa5b commit 63cda0f

File tree

10 files changed

+124
-109
lines changed

10 files changed

+124
-109
lines changed

UPGRADING.INTERNALS

+5-1
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,12 @@ PHP 8.1 INTERNALS UPGRADE NOTES
4747
getColumnMeta(). The type provided here does not need to match the type
4848
returned by get_col (in fact no corresponding type might exist, e.g. for
4949
floats). It should be the closest logical equivalent for the column type.
50-
- The transaction, set_attribute, quoter, and preparer handler's return type
50+
- The transaction, set_attribute, and preparer handler's return type
5151
has been formalized to bool instead of int.
5252
- The check_liveness handler's return type has been formalized to zend_return
5353
instead of int.
5454
- The closer, and fetch_error handlers have been voidified.
55+
- The quoter handler now returns the quoted string as zend_string* instead
56+
of returning a boolean, and the quoted string as a pair of out params.
57+
Similarly the unquoted string is now a zend_string* instead of a pair of
58+
char* and size_t length.

ext/pdo/pdo_dbh.c

+6-13
Original file line numberDiff line numberDiff line change
@@ -1119,18 +1119,17 @@ PHP_METHOD(PDO, query)
11191119
}
11201120
/* }}} */
11211121

1122-
/* {{{ 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 */
1122+
/* {{{ quotes string for use in a query.
1123+
* The optional paramtype acts as a hint for drivers that have alternate quoting styles.
1124+
* The default value is PDO_PARAM_STR */
11231125
PHP_METHOD(PDO, quote)
11241126
{
11251127
pdo_dbh_t *dbh = Z_PDO_DBH_P(ZEND_THIS);
1126-
char *str;
1127-
size_t str_len;
1128+
zend_string *str;
11281129
zend_long paramtype = PDO_PARAM_STR;
1129-
char *qstr;
1130-
size_t qlen;
11311130

11321131
ZEND_PARSE_PARAMETERS_START(1, 2)
1133-
Z_PARAM_STRING(str, str_len)
1132+
Z_PARAM_STR(str)
11341133
Z_PARAM_OPTIONAL
11351134
Z_PARAM_LONG(paramtype)
11361135
ZEND_PARSE_PARAMETERS_END();
@@ -1143,13 +1142,7 @@ PHP_METHOD(PDO, quote)
11431142
RETURN_FALSE;
11441143
}
11451144

1146-
if (dbh->methods->quoter(dbh, str, str_len, &qstr, &qlen, paramtype)) {
1147-
RETVAL_STRINGL(qstr, qlen);
1148-
efree(qstr);
1149-
return;
1150-
}
1151-
PDO_HANDLE_DBH_ERR();
1152-
RETURN_FALSE;
1145+
RETURN_STR(dbh->methods->quoter(dbh, str, paramtype));
11531146
}
11541147
/* }}} */
11551148

ext/pdo/pdo_sql_parser.re

+20-15
Original file line numberDiff line numberDiff line change
@@ -235,21 +235,18 @@ safe:
235235
php_stream_from_zval_no_verify(stm, parameter);
236236
if (stm) {
237237
zend_string *buf;
238+
zend_string *quoted_buf;
238239

239240
buf = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
240241
if (!buf) {
241242
buf = ZSTR_EMPTY_ALLOC();
242243
}
243-
if (!stmt->dbh->methods->quoter(stmt->dbh, ZSTR_VAL(buf), ZSTR_LEN(buf), &plc->quoted, &plc->qlen,
244-
param->param_type)) {
245-
/* bork */
246-
ret = -1;
247-
strncpy(stmt->error_code, stmt->dbh->error_code, 6);
248-
if (buf) {
249-
zend_string_release_ex(buf, 0);
250-
}
251-
goto clean_up;
252-
}
244+
245+
quoted_buf = stmt->dbh->methods->quoter(stmt->dbh, buf, param->param_type);
246+
plc->quoted = estrndup(ZSTR_VAL(quoted_buf), ZSTR_LEN(quoted_buf));
247+
plc->qlen = ZSTR_LEN(quoted_buf);
248+
zend_string_release_ex(quoted_buf, 0);
249+
253250
if (buf) {
254251
zend_string_release_ex(buf, 0);
255252
}
@@ -289,21 +286,29 @@ safe:
289286
plc->freeq = 0;
290287
break;
291288

292-
default:
289+
default: {
290+
zend_string *quoted_buf;
291+
292+
/* TODO Should this be zval_try_get_string_func() ? */
293293
buf = zval_get_string(parameter);
294-
if (EG(exception) ||
295-
!stmt->dbh->methods->quoter(stmt->dbh, ZSTR_VAL(buf),
296-
ZSTR_LEN(buf), &plc->quoted, &plc->qlen,
297-
param_type)) {
294+
/* TODO Check when this can occur? */
295+
if (EG(exception)) {
298296
/* bork */
299297
ret = -1;
300298
strncpy(stmt->error_code, stmt->dbh->error_code, 6);
299+
/* TODO Is this dead code now? */
301300
if (buf) {
302301
zend_string_release_ex(buf, 0);
303302
}
304303
goto clean_up;
305304
}
305+
306+
quoted_buf = stmt->dbh->methods->quoter(stmt->dbh, buf, param_type);
307+
plc->quoted = estrndup(ZSTR_VAL(quoted_buf), ZSTR_LEN(quoted_buf));
308+
plc->qlen = ZSTR_LEN(quoted_buf);
306309
plc->freeq = 1;
310+
zend_string_release_ex(quoted_buf, 0);
311+
}
307312
}
308313

309314
if (buf) {

ext/pdo/php_pdo_driver.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ typedef bool (*pdo_dbh_prepare_func)(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_
236236
typedef zend_long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, size_t sql_len);
237237

238238
/* quote a string */
239-
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);
239+
typedef zend_string* (*pdo_dbh_quote_func)(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype);
240240

241241
/* transaction related (beingTransaction(), commit, rollBack, inTransaction)
242242
* Return true if currently inside a transaction, false otherwise. */

ext/pdo_dblib/dblib_driver.c

+16-16
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,14 @@ static zend_long dblib_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_l
142142
return DBCOUNT(H->link);
143143
}
144144

145-
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)
145+
static zend_string* dblib_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
146146
{
147147
pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
148148
zend_bool use_national_character_set = 0;
149-
150149
size_t i;
151-
char * q;
152-
*quotedlen = 0;
150+
char *q;
151+
size_t quotedlen = 0;
152+
zend_string *quoted_str;
153153

154154
if (H->assume_national_character_set_strings) {
155155
use_national_character_set = 1;
@@ -162,34 +162,34 @@ static bool dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unq
162162
}
163163

164164
/* Detect quoted length, adding extra char for doubled single quotes */
165-
for (i = 0; i < unquotedlen; i++) {
166-
if (unquoted[i] == '\'') ++*quotedlen;
167-
++*quotedlen;
165+
for (i = 0; i < ZSTR_LEN(unquoted); i++) {
166+
if (ZSTR_VAL(unquoted)[i] == '\'') ++quotedlen;
167+
++quotedlen;
168168
}
169169

170-
*quotedlen += 2; /* +2 for opening, closing quotes */
170+
quotedlen += 2; /* +2 for opening, closing quotes */
171171
if (use_national_character_set) {
172-
++*quotedlen; /* N prefix */
172+
++quotedlen; /* N prefix */
173173
}
174-
q = *quoted = emalloc(*quotedlen + 1); /* Add byte for terminal null */
174+
quoted_str = zend_string_alloc(quotedlen, 0);
175+
q = ZSTR_VAL(quoted_str);
175176
if (use_national_character_set) {
176177
*q++ = 'N';
177178
}
178179
*q++ = '\'';
179180

180-
for (i = 0; i < unquotedlen; i++) {
181-
if (unquoted[i] == '\'') {
181+
for (i = 0; i < ZSTR_LEN(unquoted); i++) {
182+
if (ZSTR_VAL(unquoted)[i] == '\'') {
182183
*q++ = '\'';
183184
*q++ = '\'';
184185
} else {
185-
*q++ = unquoted[i];
186+
*q++ = ZSTR_VAL(unquoted)[i];
186187
}
187188
}
188189
*q++ = '\'';
190+
*q = '\0';
189191

190-
*q = 0;
191-
192-
return true;
192+
return quoted_str;
193193
}
194194

195195
static bool pdo_dblib_transaction_cmd(const char *cmd, pdo_dbh_t *dbh)

ext/pdo_firebird/firebird_driver.c

+14-15
Original file line numberDiff line numberDiff line change
@@ -649,42 +649,41 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sq
649649
/* }}} */
650650

651651
/* called by the PDO SQL parser to add quotes to values that are copied into SQL */
652-
static bool firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, /* {{{ */
653-
char **quoted, size_t *quotedlen, enum pdo_param_type paramtype)
652+
static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
654653
{
655654
int qcount = 0;
656655
char const *co, *l, *r;
657656
char *c;
657+
size_t quotedlen;
658+
zend_string *quoted_str;
658659

659-
if (!unquotedlen) {
660-
*quotedlen = 2;
661-
*quoted = emalloc(*quotedlen+1);
662-
strcpy(*quoted, "''");
663-
return true;
660+
if (ZSTR_LEN(unquoted) == 0) {
661+
return zend_string_init("''", 2, 0);
664662
}
665663

666664
/* Firebird only requires single quotes to be doubled if string lengths are used */
667665
/* count the number of ' characters */
668-
for (co = unquoted; (co = strchr(co,'\'')); qcount++, co++);
666+
for (co = ZSTR_VAL(unquoted); (co = strchr(co,'\'')); qcount++, co++);
669667

670-
*quotedlen = unquotedlen + qcount + 2;
671-
*quoted = c = emalloc(*quotedlen+1);
668+
quotedlen = ZSTR_LEN(unquoted) + qcount + 2;
669+
quoted_str = zend_string_alloc(quotedlen, 0);
670+
c = ZSTR_VAL(quoted_str);
672671
*c++ = '\'';
673672

674673
/* foreach (chunk that ends in a quote) */
675-
for (l = unquoted; (r = strchr(l,'\'')); l = r+1) {
674+
for (l = ZSTR_VAL(unquoted); (r = strchr(l,'\'')); l = r+1) {
676675
strncpy(c, l, r-l+1);
677676
c += (r-l+1);
678677
/* add the second quote */
679678
*c++ = '\'';
680679
}
681680

682681
/* copy the remainder */
683-
strncpy(c, l, *quotedlen-(c-*quoted)-1);
684-
(*quoted)[*quotedlen-1] = '\'';
685-
(*quoted)[*quotedlen] = '\0';
682+
strncpy(c, l, quotedlen-(c-ZSTR_VAL(quoted_str))-1);
683+
ZSTR_VAL(quoted_str)[quotedlen-1] = '\'';
684+
ZSTR_VAL(quoted_str)[quotedlen] = '\0';
686685

687-
return true;
686+
return quoted_str;
688687
}
689688
/* }}} */
690689

ext/pdo_mysql/mysql_driver.c

+19-13
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,13 @@ static char *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *
301301
#endif
302302

303303
/* {{{ mysql_handle_quoter */
304-
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 )
304+
static zend_string* mysql_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype )
305305
{
306306
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
307307
zend_bool use_national_character_set = 0;
308+
char *quoted;
309+
size_t quotedlen;
310+
zend_string *quoted_str;
308311

309312
if (H->assume_national_character_set_strings) {
310313
use_national_character_set = 1;
@@ -318,24 +321,27 @@ static bool mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unq
318321

319322
PDO_DBG_ENTER("mysql_handle_quoter");
320323
PDO_DBG_INF_FMT("dbh=%p", dbh);
321-
PDO_DBG_INF_FMT("unquoted=%.*s", (int)unquotedlen, unquoted);
322-
*quoted = safe_emalloc(2, unquotedlen, 3 + (use_national_character_set ? 1 : 0));
324+
PDO_DBG_INF_FMT("unquoted=%.*s", (int)ZSTR_LEN(unquoted), ZSTR_VAL(unquoted));
325+
quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3 + (use_national_character_set ? 1 : 0));
323326

324327
if (use_national_character_set) {
325-
*quotedlen = mysql_real_escape_string_quote(H->server, *quoted + 2, unquoted, unquotedlen, '\'');
326-
(*quoted)[0] = 'N';
327-
(*quoted)[1] = '\'';
328+
quotedlen = mysql_real_escape_string_quote(H->server, quoted + 2, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), '\'');
329+
quoted[0] = 'N';
330+
quoted[1] = '\'';
328331

329-
++*quotedlen; /* N prefix */
332+
++quotedlen; /* N prefix */
330333
} else {
331-
*quotedlen = mysql_real_escape_string_quote(H->server, *quoted + 1, unquoted, unquotedlen, '\'');
332-
(*quoted)[0] = '\'';
334+
quotedlen = mysql_real_escape_string_quote(H->server, quoted + 1, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), '\'');
335+
quoted[0] = '\'';
333336
}
334337

335-
(*quoted)[++*quotedlen] = '\'';
336-
(*quoted)[++*quotedlen] = '\0';
337-
PDO_DBG_INF_FMT("quoted=%.*s", (int)*quotedlen, *quoted);
338-
PDO_DBG_RETURN(true);
338+
quoted[++quotedlen] = '\'';
339+
quoted[++quotedlen] = '\0';
340+
PDO_DBG_INF_FMT("quoted=%.*s", (int)quotedlen, quoted);
341+
342+
quoted_str = zend_string_init(quoted, quotedlen, 0);
343+
efree(quoted);
344+
PDO_DBG_RETURN(quoted_str);
339345
}
340346
/* }}} */
341347

ext/pdo_oci/oci_driver.c

+15-15
Original file line numberDiff line numberDiff line change
@@ -350,40 +350,40 @@ static zend_long oci_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
350350
}
351351
/* }}} */
352352

353-
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 ) /* {{{ */
353+
static zend_string* oci_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype ) /* {{{ */
354354
{
355355
int qcount = 0;
356356
char const *cu, *l, *r;
357-
char *c;
357+
char *c, *quoted;
358+
zend_string *quoted_str;
358359

359-
if (!unquotedlen) {
360-
*quotedlen = 2;
361-
*quoted = emalloc(*quotedlen+1);
362-
strcpy(*quoted, "''");
363-
return true;
360+
if (ZSTR_LEN(unquoted) == 0) {
361+
return zend_string_init("''", 2, 0);
364362
}
365363

366364
/* count single quotes */
367-
for (cu = unquoted; (cu = strchr(cu,'\'')); qcount++, cu++)
365+
for (cu = ZSTR_VAL(unquoted); (cu = strchr(cu,'\'')); qcount++, cu++)
368366
; /* empty loop */
369367

370-
*quotedlen = unquotedlen + qcount + 2;
371-
*quoted = c = emalloc(*quotedlen+1);
368+
quotedlen = ZSTR_LEN(unquoted) + qcount + 2;
369+
quoted = c = emalloc(quotedlen+1);
372370
*c++ = '\'';
373371

374372
/* foreach (chunk that ends in a quote) */
375-
for (l = unquoted; (r = strchr(l,'\'')); l = r+1) {
373+
for (l = ZSTR_VAL(unquoted); (r = strchr(l,'\'')); l = r+1) {
376374
strncpy(c, l, r-l+1);
377375
c += (r-l+1);
378376
*c++ = '\''; /* add second quote */
379377
}
380378

381379
/* Copy remainder and add enclosing quote */
382-
strncpy(c, l, *quotedlen-(c-*quoted)-1);
383-
(*quoted)[*quotedlen-1] = '\'';
384-
(*quoted)[*quotedlen] = '\0';
380+
strncpy(c, l, quotedlen-(c-quoted)-1);
381+
quoted[quotedlen-1] = '\'';
382+
quoted[quotedlen] = '\0';
385383

386-
return true;
384+
quoted_str = zend_string_init(quoted, quotedlen, 0);
385+
efree(quoted);
386+
return quoted_str;
387387
}
388388
/* }}} */
389389

0 commit comments

Comments
 (0)