summaryrefslogtreecommitdiff
path: root/ext/pdo/pdo_sql_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo/pdo_sql_parser.c')
-rw-r--r--ext/pdo/pdo_sql_parser.c152
1 files changed, 84 insertions, 68 deletions
diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c
index 5a419782b5..0095c3d8dc 100644
--- a/ext/pdo/pdo_sql_parser.c
+++ b/ext/pdo/pdo_sql_parser.c
@@ -2,7 +2,7 @@
#line 1 "ext/pdo/pdo_sql_parser.re"
/*
+----------------------------------------------------------------------+
- | PHP Version 5 |
+ | PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2016 The PHP Group |
+----------------------------------------------------------------------+
@@ -42,7 +42,7 @@ typedef struct Scanner {
char *ptr, *cur, *tok, *end;
} Scanner;
-static int scan(Scanner *s)
+static int scan(Scanner *s)
{
char *cursor = s->cur;
@@ -377,28 +377,32 @@ yy39:
#line 378 "ext/pdo/pdo_sql_parser.c"
}
#line 66 "ext/pdo/pdo_sql_parser.re"
-
+
}
struct placeholder {
char *pos;
- int len;
+ size_t len;
int bindno;
- int qlen; /* quoted length of value */
+ size_t qlen; /* quoted length of value */
char *quoted; /* quoted value */
int freeq;
struct placeholder *next;
};
-PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len,
- char **outquery, int *outquery_len TSRMLS_DC)
+static void free_param_name(zval *el) {
+ efree(Z_PTR_P(el));
+}
+
+PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, size_t inquery_len,
+ char **outquery, size_t *outquery_len)
{
Scanner s;
char *ptr, *newbuffer;
int t;
int bindno = 0;
int ret = 0;
- int newbuffer_len;
+ size_t newbuffer_len;
HashTable *params;
struct pdo_bound_param_data *param;
int query_type = PDO_PLACEHOLDER_NONE;
@@ -445,7 +449,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len,
/* did the query make sense to me? */
if (query_type == (PDO_PLACEHOLDER_NAMED|PDO_PLACEHOLDER_POSITIONAL)) {
/* they mixed both types; punt */
- pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "mixed named and positional parameters" TSRMLS_CC);
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "mixed named and positional parameters");
ret = -1;
goto clean_up;
}
@@ -464,22 +468,22 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len,
* but it works. */
query_type = PDO_PLACEHOLDER_POSITIONAL;
}
-
+
params = stmt->bound_params;
-
+
/* Do we have placeholders but no bound params */
if (bindno && !params && stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "no parameters were bound" TSRMLS_CC);
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "no parameters were bound");
ret = -1;
goto clean_up;
}
if (params && bindno != zend_hash_num_elements(params) && stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
- /* extra bit of validation for instances when same params are bound more then once */
+ /* extra bit of validation for instances when same params are bound more than once */
if (query_type != PDO_PLACEHOLDER_POSITIONAL && bindno > zend_hash_num_elements(params)) {
int ok = 1;
for (plc = placeholders; plc; plc = plc->next) {
- if (zend_hash_find(params, plc->pos, plc->len, (void**) &param) == FAILURE) {
+ if ((param = zend_hash_str_find_ptr(params, plc->pos, plc->len)) == NULL) {
ok = 0;
break;
}
@@ -488,7 +492,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len,
goto safe;
}
}
- pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "number of bound variables does not match number of tokens" TSRMLS_CC);
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "number of bound variables does not match number of tokens");
ret = -1;
goto clean_up;
}
@@ -499,51 +503,59 @@ safe:
newbuffer_len = inquery_len;
- /* let's quote all the values */
+ /* let's quote all the values */
for (plc = placeholders; plc; plc = plc->next) {
if (query_type == PDO_PLACEHOLDER_POSITIONAL) {
- ret = zend_hash_index_find(params, plc->bindno, (void**) &param);
+ param = zend_hash_index_find_ptr(params, plc->bindno);
} else {
- ret = zend_hash_find(params, plc->pos, plc->len, (void**) &param);
+ param = zend_hash_str_find_ptr(params, plc->pos, plc->len);
}
- if (ret == FAILURE) {
+ if (param == NULL) {
/* parameter was not defined */
ret = -1;
- pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined" TSRMLS_CC);
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
goto clean_up;
}
if (stmt->dbh->methods->quoter) {
- if (param->param_type == PDO_PARAM_LOB && Z_TYPE_P(param->parameter) == IS_RESOURCE) {
+ zval *parameter;
+ if (Z_ISREF(param->parameter)) {
+ parameter = Z_REFVAL(param->parameter);
+ } else {
+ parameter = &param->parameter;
+ }
+ if (param->param_type == PDO_PARAM_LOB && Z_TYPE_P(parameter) == IS_RESOURCE) {
php_stream *stm;
- php_stream_from_zval_no_verify(stm, &param->parameter);
+ php_stream_from_zval_no_verify(stm, parameter);
if (stm) {
- size_t len;
- char *buf = NULL;
-
- len = php_stream_copy_to_mem(stm, &buf, PHP_STREAM_COPY_ALL, 0);
- if (!stmt->dbh->methods->quoter(stmt->dbh, buf, len, &plc->quoted, &plc->qlen,
- param->param_type TSRMLS_CC)) {
+ zend_string *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) {
- efree(buf);
+ zend_string_release(buf);
}
goto clean_up;
}
if (buf) {
- efree(buf);
+ zend_string_release(buf);
}
} else {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" TSRMLS_CC);
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource");
ret = -1;
goto clean_up;
}
plc->freeq = 1;
} else {
- zval tmp_param = *param->parameter;
- zval_copy_ctor(&tmp_param);
+ zval tmp_param;
+ ZVAL_DUP(&tmp_param, parameter);
switch (Z_TYPE(tmp_param)) {
case IS_NULL:
plc->quoted = "NULL";
@@ -551,7 +563,8 @@ safe:
plc->freeq = 0;
break;
- case IS_BOOL:
+ case IS_FALSE:
+ case IS_TRUE:
convert_to_long(&tmp_param);
/* fall through */
case IS_LONG:
@@ -566,7 +579,7 @@ safe:
convert_to_string(&tmp_param);
if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL(tmp_param),
Z_STRLEN(tmp_param), &plc->quoted, &plc->qlen,
- param->param_type TSRMLS_CC)) {
+ param->param_type)) {
/* bork */
ret = -1;
strncpy(stmt->error_code, stmt->dbh->error_code, 6);
@@ -577,8 +590,14 @@ safe:
zval_dtor(&tmp_param);
}
} else {
- plc->quoted = Z_STRVAL_P(param->parameter);
- plc->qlen = Z_STRLEN_P(param->parameter);
+ zval *parameter;
+ if (Z_ISREF(param->parameter)) {
+ parameter = Z_REFVAL(param->parameter);
+ } else {
+ parameter = &param->parameter;
+ }
+ plc->quoted = Z_STRVAL_P(parameter);
+ plc->qlen = Z_STRLEN_P(parameter);
}
newbuffer_len += plc->qlen;
}
@@ -621,12 +640,12 @@ rewrite:
char *name, *idxbuf;
const char *tmpl = stmt->named_rewrite_template ? stmt->named_rewrite_template : ":pdo%d";
int bind_no = 1;
-
+
newbuffer_len = inquery_len;
if (stmt->bound_param_map == NULL) {
ALLOC_HASHTABLE(stmt->bound_param_map);
- zend_hash_init(stmt->bound_param_map, 13, NULL, NULL, 0);
+ zend_hash_init(stmt->bound_param_map, 13, NULL, free_param_name, 0);
}
for (plc = placeholders; plc; plc = plc->next) {
@@ -635,7 +654,7 @@ rewrite:
name = estrndup(plc->pos, plc->len);
/* check if bound parameter is already available */
- if (!strcmp(name, "?") || zend_hash_find(stmt->bound_param_map, name, plc->len + 1, (void**) &p) == FAILURE) {
+ if (!strcmp(name, "?") || (p = zend_hash_str_find_ptr(stmt->bound_param_map, name, plc->len)) == NULL) {
spprintf(&idxbuf, 0, tmpl, bind_no++);
} else {
idxbuf = estrdup(p);
@@ -649,32 +668,31 @@ rewrite:
if (!skip_map && stmt->named_rewrite_template) {
/* create a mapping */
- zend_hash_update(stmt->bound_param_map, name, plc->len + 1, idxbuf, plc->qlen + 1, NULL);
+ zend_hash_str_update_mem(stmt->bound_param_map, name, plc->len, idxbuf, plc->qlen + 1);
}
/* map number to name */
- zend_hash_index_update(stmt->bound_param_map, plc->bindno, idxbuf, plc->qlen + 1, NULL);
-
+ zend_hash_index_update_mem(stmt->bound_param_map, plc->bindno, idxbuf, plc->qlen + 1);
+
efree(name);
}
-
+
goto rewrite;
} else {
/* rewrite :name to ? */
-
+
newbuffer_len = inquery_len;
-
+
if (stmt->bound_param_map == NULL) {
ALLOC_HASHTABLE(stmt->bound_param_map);
- zend_hash_init(stmt->bound_param_map, 13, NULL, NULL, 0);
+ zend_hash_init(stmt->bound_param_map, 13, NULL, free_param_name, 0);
}
-
+
for (plc = placeholders; plc; plc = plc->next) {
char *name;
-
name = estrndup(plc->pos, plc->len);
- zend_hash_index_update(stmt->bound_param_map, plc->bindno, name, plc->len + 1, NULL);
+ zend_hash_index_update_mem(stmt->bound_param_map, plc->bindno, name, plc->len + 1);
efree(name);
plc->quoted = "?";
plc->qlen = 1;
@@ -700,8 +718,8 @@ clean_up:
}
#if 0
-int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery,
- int *outquery_len TSRMLS_DC)
+int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery,
+ int *outquery_len)
{
Scanner s;
char *ptr;
@@ -721,8 +739,7 @@ int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char
padding = 3;
}
if(params) {
- zend_hash_internal_pointer_reset(params);
- while (SUCCESS == zend_hash_get_current_data(params, (void**)&param)) {
+ ZEND_HASH_FOREACH_PTR(params, param) {
if(param->parameter) {
convert_to_string(param->parameter);
/* accommodate a string that needs to be fully quoted
@@ -731,8 +748,7 @@ int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char
*/
newbuffer_len += padding * Z_STRLEN_P(param->parameter);
}
- zend_hash_move_forward(params);
- }
+ } ZEND_HASH_FOREACH_END();
}
*outquery = (char *) emalloc(newbuffer_len + 1);
*outquery_len = 0;
@@ -746,7 +762,7 @@ int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char
*outquery_len += (s.cur - s.tok);
}
else if(t == PDO_PARSER_BIND) {
- if(!params) {
+ if(!params) {
/* error */
efree(*outquery);
*outquery = NULL;
@@ -754,18 +770,18 @@ int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char
}
/* lookup bind first via hash and then index */
/* stupid keys need to be null-terminated, even though we know their length */
- if((SUCCESS == zend_hash_find(params, s.tok, s.cur-s.tok,(void **)&param))
+ if((NULL != (param = zend_hash_str_find_ptr(params, s.tok, s.cur-s.tok))
||
- (SUCCESS == zend_hash_index_find(params, bindno, (void **)&param)))
+ NULL != (params = zend_hash_index_find_ptr(params, bindno)))
{
char *quotedstr;
int quotedstrlen;
/* restore the in-string key, doesn't need null-termination here */
/* currently everything is a string here */
-
+
/* quote the bind value if necessary */
- if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
- Z_STRLEN_P(param->parameter), &quotedstr, &quotedstrlen TSRMLS_CC))
+ if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
+ Z_STRLEN_P(param->parameter), &quotedstr, &quotedstrlen))
{
memcpy(ptr, quotedstr, quotedstrlen);
ptr += quotedstrlen;
@@ -786,22 +802,22 @@ int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char
bindno++;
}
else if(t == PDO_PARSER_BIND_POS) {
- if(!params) {
+ if(!params) {
/* error */
efree(*outquery);
*outquery = NULL;
return (int) (s.cur - inquery);
}
/* lookup bind by index */
- if(SUCCESS == zend_hash_index_find(params, bindno, (void **)&param))
+ if(NULL != (params = zend_hash_index_find_ptr(params, bindno)))
{
char *quotedstr;
int quotedstrlen;
/* currently everything is a string here */
-
+
/* quote the bind value if necessary */
- if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
- Z_STRLEN_P(param->parameter), &quotedstr, &quotedstrlen TSRMLS_CC))
+ if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
+ Z_STRLEN_P(param->parameter), &quotedstr, &quotedstrlen))
{
memcpy(ptr, quotedstr, quotedstrlen);
ptr += quotedstrlen;
@@ -821,7 +837,7 @@ int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char
}
bindno++;
}
- }
+ }
*ptr = '\0';
return 0;
}