diff options
Diffstat (limited to 'ext/pdo/pdo_sql_parser.c')
-rw-r--r-- | ext/pdo/pdo_sql_parser.c | 152 |
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**) ¶m) == 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**) ¶m); + param = zend_hash_index_find_ptr(params, plc->bindno); } else { - ret = zend_hash_find(params, plc->pos, plc->len, (void**) ¶m); + 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 = ¶m->parameter; + } + if (param->param_type == PDO_PARAM_LOB && Z_TYPE_P(parameter) == IS_RESOURCE) { php_stream *stm; - php_stream_from_zval_no_verify(stm, ¶m->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 = ¶m->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**)¶m)) { + 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 **)¶m)) + if((NULL != (param = zend_hash_str_find_ptr(params, s.tok, s.cur-s.tok)) || - (SUCCESS == zend_hash_index_find(params, bindno, (void **)¶m))) + 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), "edstr, "edstrlen TSRMLS_CC)) + if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), + Z_STRLEN_P(param->parameter), "edstr, "edstrlen)) { 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 **)¶m)) + 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), "edstr, "edstrlen TSRMLS_CC)) + if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), + Z_STRLEN_P(param->parameter), "edstr, "edstrlen)) { 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; } |