From: Christopher Jones Date: Mon, 17 Oct 2016 01:40:14 +0000 (+1100) Subject: Fixed bug #71148 (Bind reference overwritten on PHP 7) X-Git-Tag: php-7.1.0RC4~5^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8be59a13017f16396e862a8e50c888afafe1952d;p=php Fixed bug #71148 (Bind reference overwritten on PHP 7) --- diff --git a/NEWS b/NEWS index 08b4f64ac3..e5049b515d 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,9 @@ PHP NEWS . Fixed bug #73279 (Integer overflow in gdImageScaleBilinearPalette()). (cmb) . Fixed bug #73280 (Stack Buffer Overflow in GD dynamicGetbuf). (cmb) +- OCI8 + . Fixed bug #71148 (Bind reference overwritten on PHP 7). (Oracle Corp.) + - phpdbg: . Properly allow for stdin input from a file. (Bob) . Add -s command line option / stdin command for reading script from stdin. diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 0527b55847..59f993160c 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -1387,6 +1387,11 @@ void php_oci_bind_hash_dtor(zval *data) { php_oci_bind *bind = (php_oci_bind *) Z_PTR_P(data); + if (!Z_ISUNDEF(bind->parameter)) { + zval_ptr_dtor(&bind->parameter); + ZVAL_UNDEF(&bind->parameter); + } + if (bind->array.elements) { efree(bind->array.elements); bind->array.elements = NULL; diff --git a/ext/oci8/oci8_interface.c b/ext/oci8/oci8_interface.c index 727ec3e1c7..18714d16ed 100644 --- a/ext/oci8/oci8_interface.c +++ b/ext/oci8/oci8_interface.c @@ -110,7 +110,7 @@ PHP_FUNCTION(oci_bind_by_name) zval *bind_var = NULL; php_oci_statement *statement; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz/|ll", &z_statement, &name, &name_len, &bind_var, &maxlen, &type) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz|ll", &z_statement, &name, &name_len, &bind_var, &maxlen, &type) == FAILURE) { return; } diff --git a/ext/oci8/oci8_statement.c b/ext/oci8/oci8_statement.c index d4f08150e7..2b1fc4c1f1 100644 --- a/ext/oci8/oci8_statement.c +++ b/ext/oci8/oci8_statement.c @@ -1094,13 +1094,20 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l int mode = OCI_DATA_AT_EXEC; sb4 value_sz = -1; sword errstatus; + zval *param = NULL; + + if (!Z_ISREF_P(var)) { + param = var; + } else { + param = Z_REFVAL_P(var); + } switch (type) { case SQLT_NTY: { zval *tmp; - if (Z_TYPE_P(var) != IS_OBJECT || (tmp = zend_hash_str_find(Z_OBJPROP_P(var), "collection", sizeof("collection")-1)) == NULL) { + if (Z_TYPE_P(param) != IS_OBJECT || (tmp = zend_hash_str_find(Z_OBJPROP_P(param), "collection", sizeof("collection")-1)) == NULL) { php_error_docref(NULL, E_WARNING, "Unable to find collection property"); return 1; } @@ -1122,7 +1129,7 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l { zval *tmp; - if (Z_TYPE_P(var) != IS_OBJECT || (tmp = zend_hash_str_find(Z_OBJPROP_P(var), "descriptor", sizeof("descriptor")-1)) == NULL) { + if (Z_TYPE_P(param) != IS_OBJECT || (tmp = zend_hash_str_find(Z_OBJPROP_P(param), "descriptor", sizeof("descriptor")-1)) == NULL) { php_error_docref(NULL, E_WARNING, "Unable to find descriptor property"); return 1; } @@ -1141,17 +1148,17 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l case SQLT_INT: case SQLT_NUM: - if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) { + if (Z_TYPE_P(param) == IS_RESOURCE || Z_TYPE_P(param) == IS_OBJECT) { php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); return 1; } - convert_to_long(var); + convert_to_long(param); #if defined(OCI_MAJOR_VERSION) && (OCI_MAJOR_VERSION > 10) && \ (defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) - bind_data = (ub8 *)&Z_LVAL_P(var); + bind_data = (ub8 *)&Z_LVAL_P(param); value_sz = sizeof(ub8); #else - bind_data = (ub4 *)&Z_LVAL_P(var); + bind_data = (ub4 *)&Z_LVAL_P(param); value_sz = sizeof(ub4); #endif mode = OCI_DEFAULT; @@ -1162,20 +1169,20 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l case SQLT_LNG: case SQLT_AFC: case SQLT_CHR: /* SQLT_CHR is the default value when type was not specified */ - if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) { + if (Z_TYPE_P(param) == IS_RESOURCE || Z_TYPE_P(param) == IS_OBJECT) { php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); return 1; } - if (Z_TYPE_P(var) != IS_NULL) { - convert_to_string(var); + if (Z_TYPE_P(param) != IS_NULL) { + convert_to_string(param); } if ((maxlength == -1) || (maxlength == 0)) { if (type == SQLT_LNG) { value_sz = SB4MAXVAL; - } else if (Z_TYPE_P(var) == IS_STRING) { - value_sz = (sb4) Z_STRLEN_P(var); + } else if (Z_TYPE_P(param) == IS_STRING) { + value_sz = (sb4) Z_STRLEN_P(param); } else { - /* Bug-72524: revert value_sz from PHP_OCI_PIECE_SIZE to 0. This restores PHP 5.6 behavior */ + /* Bug-72524: revert value_sz from PHP_OCI_PIECE_SIZE to 0. This restores PHP 5.6 behavior */ value_sz = 0; } } else { @@ -1184,11 +1191,11 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l break; case SQLT_RSET: - if (Z_TYPE_P(var) != IS_RESOURCE) { + if (Z_TYPE_P(param) != IS_RESOURCE) { php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); return 1; } - PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement); + PHP_OCI_ZVAL_TO_STATEMENT_EX(param, bind_statement); value_sz = sizeof(void*); oci_stmt = bind_statement->stmt; @@ -1200,15 +1207,15 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l #if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12 case SQLT_BOL: - if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) { + if (Z_TYPE_P(param) == IS_RESOURCE || Z_TYPE_P(param) == IS_OBJECT) { php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); return 1; } - convert_to_boolean(var); - bind_data = (zend_long *)&Z_LVAL_P(var); - if (Z_TYPE_P(var) == IS_TRUE) + convert_to_boolean(param); + bind_data = (zend_long *)&Z_LVAL_P(param); + if (Z_TYPE_P(param) == IS_TRUE) *(zend_long *)bind_data = 1; - else if (Z_TYPE_P(var) == IS_FALSE) + else if (Z_TYPE_P(param) == IS_FALSE) *(zend_long *)bind_data = 0; else { php_error_docref(NULL, E_WARNING, "Invalid variable used for bind"); @@ -1234,6 +1241,10 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l if ((old_bind = zend_hash_str_find_ptr(statement->binds, name, name_len)) != NULL) { bindp = old_bind; + if (!Z_ISUNDEF(bindp->parameter)) { + zval_ptr_dtor(&bindp->parameter); + ZVAL_UNDEF(&bindp->parameter); + } } else { zend_string *zvtmp; zvtmp = zend_string_init(name, name_len, 0); @@ -1241,16 +1252,20 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l bindp = zend_hash_update_ptr(statement->binds, zvtmp, bindp); zend_string_release(zvtmp); } - /* Make sure the minimum of value_sz is 1 to avoid ORA-3149 - * when both in/out parameters are bound with empty strings - */ + + /* Keep a copy of bound variable in the bind hash */ + ZVAL_COPY(&bindp->parameter, var); + + /* Make sure the minimum of value_sz is 1 to avoid ORA-3149 + * when both in/out parameters are bound with empty strings + */ if (value_sz == 0) value_sz = 1; bindp->descriptor = oci_desc; bindp->statement = oci_stmt; bindp->parent_statement = statement; - bindp->zval = var; + bindp->zval = param; bindp->type = type; /* Storing max length set in OCIBindByName() to check it later in * php_oci_bind_in_callback() function to avoid ORA-1406 error while diff --git a/ext/oci8/package.xml b/ext/oci8/package.xml index 29b5d6db0b..da54dfa707 100644 --- a/ext/oci8/package.xml +++ b/ext/oci8/package.xml @@ -46,12 +46,12 @@ Interoperability Support" (ID 207303.1) for details. no - 2016-08-18 + 2016-10-17 - 2.1.2 - 2.1.2 + 2.1.3 + 2.1.3 stable @@ -60,8 +60,7 @@ Interoperability Support" (ID 207303.1) for details. PHP This version is for PHP 7 only. -Fixed invalid handle error with Implicit Result Sets -Fixed bug #72524 (Binding null values triggers ORA-24816 error) +Fixed bug #71148 (Bind reference overwritten on PHP 7) @@ -469,6 +468,23 @@ Fixed bug #72524 (Binding null values triggers ORA-24816 error) + + + 2.1.2 + 2.1.2 + + + stable + stable + + PHP + +This version is for PHP 7 only. +Fixed invalid handle error with Implicit Result Sets +Fixed bug #72524 (Binding null values triggers ORA-24816 error) + + + 2.1.1 diff --git a/ext/oci8/php_oci8.h b/ext/oci8/php_oci8.h index 70200e452d..ef9b35dcd4 100644 --- a/ext/oci8/php_oci8.h +++ b/ext/oci8/php_oci8.h @@ -43,7 +43,7 @@ */ #undef PHP_OCI8_VERSION #endif -#define PHP_OCI8_VERSION "2.1.2" +#define PHP_OCI8_VERSION "2.1.3" extern zend_module_entry oci8_module_entry; #define phpext_oci8_ptr &oci8_module_entry diff --git a/ext/oci8/php_oci8_int.h b/ext/oci8/php_oci8_int.h index 3a63504e05..1d66f05216 100644 --- a/ext/oci8/php_oci8_int.h +++ b/ext/oci8/php_oci8_int.h @@ -243,6 +243,7 @@ typedef struct { typedef struct { OCIBind *bind; /* bind handle */ zval *zval; /* value */ + zval parameter; /* a copy of bound variable used for oci_bind_by_name */ dvoid *descriptor; /* used for binding of LOBS etc */ OCIStmt *statement; /* used for binding REFCURSORs */ php_oci_statement *parent_statement; /* pointer to the parent statement */ diff --git a/ext/oci8/tests/bug71148.phpt b/ext/oci8/tests/bug71148.phpt new file mode 100644 index 0000000000..44bd0e8007 --- /dev/null +++ b/ext/oci8/tests/bug71148.phpt @@ -0,0 +1,191 @@ +--TEST-- +Bug #71448 (Binding reference overwritten on php7) +--SKIPIF-- + true, 'timesten' => true); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +?> +--FILE-- + +===DONE=== + +--EXPECT-- +Test 1: Bind input parameter in a local function +array(2) { + [":VAR1"]=> + string(6) "INSTR1" + [":VAR2"]=> + string(6) "INSTR2" +} + +Test 2: Bind output parameter in a local function +string(6) "xxxxxx" +string(6) "xxxxxx" + +Test 3: Bind output parameter within the same scope of execute +string(7) "OUTSTR1" +string(7) "OUTSTR2" + +Test 4: Bind output parameter within the same scope of execute +string(8) "STR1STR2" + +Test 5: Bind IN OUT parameter in a local function +string(4) "STR1" +string(4) "STR2" +string(1) " " + +Test 6: Bind IN OUT parameter within the same scope of execute +string(4) "STR1" +string(4) "STR2" +string(9) "STR1 STR2" +===DONE=== diff --git a/ext/oci8/tests/driver_name.phpt b/ext/oci8/tests/driver_name.phpt index 9814703159..d24044e68e 100644 --- a/ext/oci8/tests/driver_name.phpt +++ b/ext/oci8/tests/driver_name.phpt @@ -57,11 +57,11 @@ function get_attr($conn) ?> --EXPECT-- **Test 1.1 - Default values for the attribute ************** -The value of DRIVER_NAME is PHP OCI8 : 2.1.2 +The value of DRIVER_NAME is PHP OCI8 : 2.1.3 ***Test 1.2 - Get the values from different connections ************** Testing with oci_pconnect() -The value of DRIVER_NAME is PHP OCI8 : 2.1.2 +The value of DRIVER_NAME is PHP OCI8 : 2.1.3 Testing with oci_new_connect() -The value of DRIVER_NAME is PHP OCI8 : 2.1.2 +The value of DRIVER_NAME is PHP OCI8 : 2.1.3 Done