From 53b930475f3f3e6b6dd727db5f1c565effc04324 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sun, 11 May 2014 16:05:14 +0800 Subject: [PATCH] Various bug fixed --- ext/mysqli/mysqli.c | 21 +++++---- ext/mysqli/mysqli_api.c | 77 +++++++++++++++++++-------------- ext/mysqli/php_mysqli_structs.h | 4 +- 3 files changed, 59 insertions(+), 43 deletions(-) diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 54e490d73b..09fafd3eea 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -81,6 +81,9 @@ typedef struct _mysqli_prop_handler { static int le_pmysqli; +static void free_prop_handler(zval *el) { + pefree(Z_PTR_P(el), 1); +} /* Destructor for mysqli entries in free_links/used_links */ void php_mysqli_dtor_p_elements(void *data) @@ -424,7 +427,6 @@ HashTable *mysqli_object_get_debug_info(zval *object, int *is_temp TSRMLS_DC) { mysqli_object *obj = Z_MYSQLI_P(object); HashTable *retval, *props = obj->prop_handler; - HashPosition pos; mysqli_prop_handler *entry; ALLOC_HASHTABLE(retval); @@ -618,7 +620,7 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_MYSQLI_CLASS_ENTRY("mysqli_driver", mysqli_driver_class_entry, mysqli_driver_methods); ce = mysqli_driver_class_entry; - zend_hash_init(&mysqli_driver_properties, 0, NULL, NULL, 1); + zend_hash_init(&mysqli_driver_properties, 0, NULL, free_prop_handler, 1); MYSQLI_ADD_PROPERTIES(&mysqli_driver_properties, mysqli_driver_property_entries); zend_declare_property_null(ce, "client_info", sizeof("client_info") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(ce, "client_version", sizeof("client_version") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); @@ -631,7 +633,7 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_MYSQLI_CLASS_ENTRY("mysqli", mysqli_link_class_entry, mysqli_link_methods); ce = mysqli_link_class_entry; - zend_hash_init(&mysqli_link_properties, 0, NULL, NULL, 1); + zend_hash_init(&mysqli_link_properties, 0, NULL, free_prop_handler, 1); MYSQLI_ADD_PROPERTIES(&mysqli_link_properties, mysqli_link_property_entries); zend_declare_property_null(ce, "affected_rows", sizeof("affected_rows") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(ce, "client_info", sizeof("client_info") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); @@ -657,7 +659,7 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_MYSQLI_CLASS_ENTRY("mysqli_warning", mysqli_warning_class_entry, mysqli_warning_methods); ce = mysqli_warning_class_entry; ce->ce_flags |= ZEND_ACC_FINAL_CLASS | ZEND_ACC_PROTECTED; - zend_hash_init(&mysqli_warning_properties, 0, NULL, NULL, 1); + zend_hash_init(&mysqli_warning_properties, 0, NULL, free_prop_handler, 1); MYSQLI_ADD_PROPERTIES(&mysqli_warning_properties, mysqli_warning_property_entries); zend_declare_property_null(ce, "message", sizeof("message") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(ce, "sqlstate", sizeof("sqlstate") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); @@ -666,7 +668,7 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_MYSQLI_CLASS_ENTRY("mysqli_result", mysqli_result_class_entry, mysqli_result_methods); ce = mysqli_result_class_entry; - zend_hash_init(&mysqli_result_properties, 0, NULL, NULL, 1); + zend_hash_init(&mysqli_result_properties, 0, NULL, free_prop_handler, 1); MYSQLI_ADD_PROPERTIES(&mysqli_result_properties, mysqli_result_property_entries); zend_declare_property_null(ce, "current_field", sizeof("current_field") - 1,ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(ce, "field_count", sizeof("field_count") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); @@ -680,7 +682,7 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_MYSQLI_CLASS_ENTRY("mysqli_stmt", mysqli_stmt_class_entry, mysqli_stmt_methods); ce = mysqli_stmt_class_entry; - zend_hash_init(&mysqli_stmt_properties, 0, NULL, NULL, 1); + zend_hash_init(&mysqli_stmt_properties, 0, NULL, free_prop_handler, 1); MYSQLI_ADD_PROPERTIES(&mysqli_stmt_properties, mysqli_stmt_property_entries); zend_declare_property_null(ce, "affected_rows", sizeof("affected_rows") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(ce, "insert_id", sizeof("insert_id") - 1, ZEND_ACC_PUBLIC TSRMLS_CC); @@ -1248,13 +1250,13 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|Sz", &mysql_result, mysqli_result_class_entry, &class_name, &ctor_params) == FAILURE) { return; } - if (class_name) { + if (class_name == NULL) { ce = zend_standard_class_def; } else { ce = zend_fetch_class(class_name, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); } if (!ce) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name->val); return; } fetchtype = MYSQLI_ASSOC; @@ -1288,7 +1290,8 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags ZVAL_COPY_VALUE(&dataset, return_value); object_and_properties_init(return_value, ce, NULL); - zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC); + zend_merge_properties(return_value, Z_ARRVAL(dataset), 0 TSRMLS_CC); + zval_ptr_dtor(&dataset); if (ce->constructor) { fci.size = sizeof(fci); diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index d1767082f9..59d03e6579 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -198,12 +198,17 @@ int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned in ofs = 0; for (i = start; i < argc; i++) { - + zval *param; + if (Z_ISREF(args[i])) { + param = Z_REFVAL(args[i]); + } else { + param = &args[i]; + } /* set specified type */ switch (types[ofs]) { case 'd': /* Double */ bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE; - bind[ofs].buffer = &Z_DVAL(args[i]); + bind[ofs].buffer = &Z_DVAL_P(param); bind[ofs].is_null = &stmt->param.is_null[ofs]; break; @@ -213,7 +218,7 @@ int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned in #elif SIZEOF_LONG==4 bind[ofs].buffer_type = MYSQL_TYPE_LONG; #endif - bind[ofs].buffer = &Z_LVAL(args[i]); + bind[ofs].buffer = &Z_LVAL_P(param); bind[ofs].is_null = &stmt->param.is_null[ofs]; break; @@ -397,7 +402,7 @@ mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc, un bind = (MYSQL_BIND *)ecalloc(var_cnt, sizeof(MYSQL_BIND)); { int size; - char *p= emalloc(size= var_cnt * (sizeof(char) + sizeof(VAR_BUFFER))); + char *p = emalloc(size= var_cnt * (sizeof(char) + sizeof(VAR_BUFFER))); stmt->result.buf = (VAR_BUFFER *) p; stmt->result.is_null = p + var_cnt * sizeof(VAR_BUFFER); memset(p, 0, size); @@ -410,7 +415,6 @@ mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc, un switch (col_type) { case MYSQL_TYPE_DOUBLE: case MYSQL_TYPE_FLOAT: - convert_to_double_ex(&args[i]); stmt->result.buf[ofs].type = IS_DOUBLE; stmt->result.buf[ofs].buflen = sizeof(double); @@ -439,7 +443,6 @@ mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc, un case MYSQL_TYPE_LONG: case MYSQL_TYPE_INT24: case MYSQL_TYPE_YEAR: - convert_to_long_ex(&args[i]); stmt->result.buf[ofs].type = IS_LONG; /* don't set stmt->result.buf[ofs].buflen to 0, we used ecalloc */ stmt->result.buf[ofs].val = (char *)emalloc(sizeof(int)); @@ -863,10 +866,11 @@ PHP_FUNCTION(mysqli_error) } /* }}} */ +#if 0 #ifndef MYSQLI_USE_MYSQLND /* {{{ php_mysqli_stmt_copy_it */ static void -php_mysqli_stmt_copy_it(zval *** copies, zval *original, uint param_count, uint current) +php_mysqli_stmt_copy_it(zval *copies, zval *original, uint param_count, uint current) { if (!*copies) { *copies = ecalloc(param_count, sizeof(zval *)); @@ -878,6 +882,7 @@ php_mysqli_stmt_copy_it(zval *** copies, zval *original, uint param_count, uint } /* }}} */ #endif +#endif /* {{{ proto bool mysqli_stmt_execute(object stmt) Execute a prepared statement */ @@ -897,22 +902,27 @@ PHP_FUNCTION(mysqli_stmt_execute) #ifndef MYSQLI_USE_MYSQLND for (i = 0; i < stmt->param.var_cnt; i++) { if (!Z_ISUNDEF(stmt->param.vars[i])) { - if (!(stmt->param.is_null[i] = (Z_ISNULL(stmt->param.vars[i])))) { - zval *the_var = &stmt->param.vars[i]; + zval *param; + if (Z_ISREF(stmt->param.vars[i])) { + param = Z_REFVAL(stmt->param.vars[i]); + } else { + param = &stmt->param.vars[i]; + } + if (!(stmt->param.is_null[i] = (Z_ISNULL_P(param)))) { switch (stmt->stmt->params[i].buffer_type) { case MYSQL_TYPE_VAR_STRING: - convert_to_string_ex(the_var); - stmt->stmt->params[i].buffer = Z_STRVAL_P(the_var); - stmt->stmt->params[i].buffer_length = Z_STRLEN_P(the_var); + convert_to_string_ex(param); + stmt->stmt->params[i].buffer = Z_STRVAL_P(param); + stmt->stmt->params[i].buffer_length = Z_STRLEN_P(param); break; case MYSQL_TYPE_DOUBLE: - convert_to_double_ex(the_var); - stmt->stmt->params[i].buffer = &Z_DVAL_P(the_var); + convert_to_double_ex(param); + stmt->stmt->params[i].buffer = &Z_DVAL_P(param); break; case MYSQL_TYPE_LONGLONG: case MYSQL_TYPE_LONG: - convert_to_long_ex(the_var); - stmt->stmt->params[i].buffer = &Z_LVAL_P(the_var); + convert_to_long_ex(param); + stmt->stmt->params[i].buffer = &Z_LVAL_P(param); break; default: break; @@ -966,15 +976,20 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS) if (!ret) { #endif for (i = 0; i < stmt->result.var_cnt; i++) { + zval *result; + /* it must be a reference, isn't it? */ + if (Z_ISREF(stmt->result.vars[i])) { + result = Z_REFVAL(stmt->result.vars[i]); + } else { + result = &stmt->result.vars[i]; + } /* QQ: Isn't it quite better to call zval_dtor(). What if the user has assigned a resource, or an array to the bound variable? We are going to leak probably. zval_dtor() will handle also Unicode/Non-unicode mode. */ /* Even if the string is of length zero there is one byte alloced so efree() in all cases */ - if (Z_TYPE(stmt->result.vars[i]) == IS_STRING) { - zval_ptr_dtor(&stmt->result.vars[i]); - } + zval_ptr_dtor(result); if (!stmt->result.is_null[i]) { switch (stmt->result.buf[i].type) { case IS_LONG: @@ -986,7 +1001,7 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS) #if SIZEOF_LONG==4 if (uval > INT_MAX) { char *tmp, *p; - int j=10; + int j = 10; tmp = emalloc(11); p= &tmp[9]; do { @@ -995,20 +1010,20 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS) } while (--j > 0); tmp[10]= '\0'; /* unsigned int > INT_MAX is 10 digits - ALWAYS */ - ZVAL_STRINGL(&stmt->result.vars[i], tmp, 10); + ZVAL_STRINGL(result, tmp, 10); efree(tmp); break; } #endif } if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) { - ZVAL_LONG(&stmt->result.vars[i], *(unsigned int *)stmt->result.buf[i].val); + ZVAL_LONG(result, *(unsigned int *)stmt->result.buf[i].val); } else { - ZVAL_LONG(&stmt->result.vars[i], *(int *)stmt->result.buf[i].val); + ZVAL_LONG(result, *(int *)stmt->result.buf[i].val); } break; case IS_DOUBLE: - ZVAL_DOUBLE(&stmt->result.vars[i], *(double *)stmt->result.buf[i].val); + ZVAL_DOUBLE(result, *(double *)stmt->result.buf[i].val); break; case IS_STRING: if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG @@ -1016,7 +1031,7 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS) || stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT #endif ) { - my_bool uns= (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0; + my_bool uns = (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0; #if MYSQL_VERSION_ID > 50002 if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) { switch (stmt->result.buf[i].output_len) { @@ -1048,22 +1063,20 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS) * use MYSQLI_LL_SPEC. */ snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval); - ZVAL_STRING(&stmt->result.vars[i], tmp); + ZVAL_STRING(result, tmp); } else { - ZVAL_LONG(&stmt->result.vars[i], llval); + ZVAL_LONG(result, llval); } } else { #if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002 if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) { /* result was truncated */ - ZVAL_STRINGL(&stmt->result.vars[i], stmt->result.buf[i].val, - stmt->stmt->bind[i].buffer_length); + ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length); } else { #else { #endif - ZVAL_STRINGL(&stmt->result.vars[i], stmt->result.buf[i].val, - stmt->result.buf[i].output_len); + ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->result.buf[i].output_len); } } break; @@ -1071,7 +1084,7 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS) break; } } else { - ZVAL_NULL(&stmt->result.vars[i]); + ZVAL_NULL(result); } } } else { diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h index 8fea060f08..8b0bf1faf9 100644 --- a/ext/mysqli/php_mysqli_structs.h +++ b/ext/mysqli/php_mysqli_structs.h @@ -259,7 +259,7 @@ extern PHPAPI zend_class_entry *spl_ce_RuntimeException; MYSQLI_RESOURCE *my_res; \ mysqli_object *intern = Z_MYSQLI_P(__id); \ if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {\ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %s", intern->zo.ce->name);\ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %s", intern->zo.ce->name->val);\ RETURN_NULL();\ }\ __ptr = (__type)my_res->ptr; \ @@ -298,7 +298,7 @@ extern PHPAPI zend_class_entry *spl_ce_RuntimeException; MYSQLI_FETCH_RESOURCE((__ptr), MY_STMT *, (__id), "mysqli_stmt", (__check)); \ if (!(__ptr)->stmt) { \ mysqli_object *intern = Z_MYSQLI_P(__id); \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid object or resource %s\n", intern->zo.ce->name); \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid object or resource %s\n", intern->zo.ce->name->val); \ RETURN_NULL();\ } \ } -- 2.40.0