diff --git a/sqlsrv/CREDITS b/sqlsrv/CREDITS index 7bb31c89..ca764f97 100644 --- a/sqlsrv/CREDITS +++ b/sqlsrv/CREDITS @@ -1 +1 @@ -Microsoft Drivers 4.0.0 for PHP for SQL Server (SQLSRV driver) +Microsoft Drivers 4.0.8219 for PHP for SQL Server (SQLSRV driver) diff --git a/sqlsrv/conn.cpp b/sqlsrv/conn.cpp index c9926ad9..444d91c2 100644 --- a/sqlsrv/conn.cpp +++ b/sqlsrv/conn.cpp @@ -900,7 +900,7 @@ PHP_FUNCTION( sqlsrv_prepare ) //mark_params_by_reference( stmt, params_z TSRMLS_CC ); stmt->params_z = params_z; if (params_z) { - zval_add_ref(params_z); + Z_TRY_ADDREF_P(params_z); } stmt->prepared = true; @@ -1020,7 +1020,7 @@ PHP_FUNCTION( sqlsrv_query ) stmt->params_z = params_z; if( params_z ) { - zval_add_ref( params_z ); + Z_TRY_ADDREF_P(params_z); } stmt->set_func( "sqlsrv_query" ); @@ -1204,7 +1204,7 @@ void add_stmt_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len, throw ss::SSException(); } - zval_add_ref( data ); // inc the ref count since this is going into the options_ht too. + Z_TRY_ADDREF_P(data); // inc the ref count since this is going into the options_ht too. core::sqlsrv_zend_hash_index_update( ctx, options_ht, option_key, data TSRMLS_CC ); } @@ -1217,7 +1217,7 @@ void add_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len, throw ss::SSException(); } - zval_add_ref( data ); // inc the ref count since this is going into the options_ht too. + Z_TRY_ADDREF_P(data); // inc the ref count since this is going into the options_ht too. core::sqlsrv_zend_hash_index_update( ctx, options_ht, option_key, data TSRMLS_CC ); } diff --git a/sqlsrv/core_stmt.cpp b/sqlsrv/core_stmt.cpp index 36f864f9..747ae214 100644 --- a/sqlsrv/core_stmt.cpp +++ b/sqlsrv/core_stmt.cpp @@ -547,7 +547,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, zend_ulong param_num, int directi HashTable* streams_ht = Z_ARRVAL( stmt->param_streams ); core::sqlsrv_zend_hash_index_update_mem(*stmt, streams_ht, param_num, &stream_encoding, sizeof(stream_encoding) TSRMLS_CC); buffer = reinterpret_cast( param_num ); - zval_add_ref( param_z ); // so that it doesn't go away while we're using it + Z_TRY_ADDREF_P(param_z); // so that it doesn't go away while we're using it buffer_len = 0; ind_ptr = SQL_DATA_AT_EXEC; } @@ -560,7 +560,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, zend_ulong param_num, int directi zval format_z; zval params[1]; bool valid_class_name_found = false; - + zend_class_entry *class_entry = Z_OBJCE_P(param_z TSRMLS_CC); while( class_entry != NULL ) { @@ -581,7 +581,7 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, zend_ulong param_num, int directi CHECK_CUSTOM_ERROR( !valid_class_name_found, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) { throw core::CoreException(); } - + // if the user specifies the 'date' sql type, giving it the normal format will cause a 'date overflow error' // meaning there is too much information in the character string. If the user specifies the 'datetimeoffset' // sql type, it lacks the timezone. @@ -604,12 +604,12 @@ void core_sqlsrv_bind_param(sqlsrv_stmt* stmt, zend_ulong param_num, int directi CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) { throw core::CoreException(); } - buffer = Z_STRVAL_P( &buffer_z ); + buffer = Z_STRVAL( buffer_z ); zr = add_next_index_zval( &(stmt->param_datetime_buffers), &buffer_z ); CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) { throw core::CoreException(); } - buffer_len = Z_STRLEN_P( &buffer_z ); + buffer_len = Z_STRLEN( buffer_z ) - 1; ind_ptr = buffer_len; break; } @@ -2379,7 +2379,7 @@ void save_output_param_for_later( sqlsrv_stmt* stmt, sqlsrv_output_param& param HashTable* param_ht = Z_ARRVAL( stmt->output_params ); zend_ulong paramno = static_cast(param.param_num); core::sqlsrv_zend_hash_index_update_mem(*stmt, param_ht, paramno, ¶m, sizeof(sqlsrv_output_param)); - zval_add_ref( param.param_z ); // we have a reference to the param + Z_TRY_ADDREF_P(param.param_z); // we have a reference to the param } diff --git a/sqlsrv/php_sqlsrv.h b/sqlsrv/php_sqlsrv.h index 6219034c..0371238d 100644 --- a/sqlsrv/php_sqlsrv.h +++ b/sqlsrv/php_sqlsrv.h @@ -353,6 +353,7 @@ enum SS_ERROR_CODES { SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, SS_SQLSRV_ERROR_CONNECT_BRACES_NOT_ESCAPED, SS_SQLSRV_ERROR_INVALID_OUTPUT_PARAM_TYPE, + SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF }; extern ss_error SS_ERRORS[]; diff --git a/sqlsrv/stmt.cpp b/sqlsrv/stmt.cpp index ab447d99..4a64ca4f 100644 --- a/sqlsrv/stmt.cpp +++ b/sqlsrv/stmt.cpp @@ -88,7 +88,7 @@ const char SS_SQLSRV_WARNING_PARAM_VAR_NOT_REF[] = "Variable parameter %d not pa /* internal functions */ -zval convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void* in_val, SQLLEN field_len ); +zval* convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void* in_val, SQLLEN field_len ); void fetch_fields_common( __inout ss_sqlsrv_stmt* stmt, zend_long fetch_type, __out zval* return_value, bool allow_empty_field_names TSRMLS_DC ); bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, sqlsrv_sqltype sqlsrv_type, __out SQLUINTEGER* column_size, @@ -1072,8 +1072,8 @@ PHP_FUNCTION( sqlsrv_get_field ) core_sqlsrv_get_field( stmt, field_index, sqlsrv_php_type, false, &field_value, &field_len, false/*cache_field*/, &sqlsrv_php_type_out TSRMLS_CC ); - zval retval_z = convert_to_zval(sqlsrv_php_type_out, field_value, field_len); - RETURN_ZVAL(&retval_z, 1, 1); + zval* retval_z = convert_to_zval(sqlsrv_php_type_out, field_value, field_len); + RETURN_ZVAL(retval_z, 1, 1); } catch( core::CoreException& ) { @@ -1200,12 +1200,12 @@ void mark_params_by_reference( ss_sqlsrv_stmt* stmt, zval* params_z TSRMLS_DC ) CHECK_CUSTOM_ERROR(zr == FAILURE, stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index + 1) { throw ss::SSException(); } - ZVAL_MAKE_REF(var); + ZVAL_MAKE_REF(var); } } // save our parameters for later. - zval_add_ref( params_z ); + Z_TRY_ADDREF_P(params_z); stmt->params_z = params_z; } @@ -1484,70 +1484,52 @@ void stmt_option_scrollable:: operator()( sqlsrv_stmt* stmt, stmt_option const* namespace { -zval convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void* in_val, SQLLEN field_len ) +zval* convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void* in_val, SQLLEN field_len ) { - zval out_zval; - ZVAL_UNDEF( &out_zval ); + zval* out_zval = NULL; + + if (in_val == NULL) { + + out_zval = (zval*)sqlsrv_malloc(sizeof(zval)); + ZVAL_NULL(out_zval); + return out_zval; + } switch( sqlsrv_php_type ) { case SQLSRV_PHPTYPE_INT: case SQLSRV_PHPTYPE_FLOAT: { - if( in_val == NULL ) { - ZVAL_NULL( &out_zval ); + out_zval = (zval*)sqlsrv_malloc(sizeof(zval)); + if( sqlsrv_php_type == SQLSRV_PHPTYPE_INT ) { + ZVAL_LONG( out_zval, *(reinterpret_cast( in_val ))); } else { - - if( sqlsrv_php_type == SQLSRV_PHPTYPE_INT ) { - ZVAL_LONG( &out_zval, *(reinterpret_cast( in_val ))); - } - else { - ZVAL_DOUBLE( &out_zval, *(reinterpret_cast( in_val ))); - } + ZVAL_DOUBLE( out_zval, *(reinterpret_cast( in_val ))); } - - if( in_val ) { - sqlsrv_free( in_val ); - } - + sqlsrv_free( in_val ); break; } case SQLSRV_PHPTYPE_STRING: { - - if( in_val == NULL ) { - - ZVAL_NULL( &out_zval ); - } - else { - - ZVAL_STRINGL( &out_zval, reinterpret_cast( in_val ), field_len); - sqlsrv_free( in_val ); - } + out_zval = (zval*) sqlsrv_malloc( sizeof(zval) ); + ZVAL_STRINGL( out_zval, reinterpret_cast( in_val ), field_len); + sqlsrv_free( in_val ); break; } case SQLSRV_PHPTYPE_STREAM: + case SQLSRV_PHPTYPE_DATETIME : { - out_zval = *(reinterpret_cast( in_val )); + out_zval = (reinterpret_cast( in_val )); + in_val = NULL; break; } - case SQLSRV_PHPTYPE_DATETIME: - { - if (in_val == NULL) { - - ZVAL_NULL(&out_zval); - } - out_zval = *(reinterpret_cast(in_val)); - sqlsrv_free(in_val); - break; - } - case SQLSRV_PHPTYPE_NULL: - ZVAL_NULL( &out_zval ); + out_zval = (zval*)sqlsrv_malloc(sizeof(zval)); + ZVAL_NULL( out_zval ); break; default: @@ -1865,7 +1847,7 @@ void fetch_fields_common( __inout ss_sqlsrv_stmt* stmt, zend_long fetch_type, __ core_sqlsrv_get_field( stmt, i, sqlsrv_php_type, true /*prefer string*/, &field_value, &field_len, false /*cache_field*/, &sqlsrv_php_type_out TSRMLS_CC ); - field = convert_to_zval( sqlsrv_php_type_out, field_value, field_len ); + field = *(convert_to_zval( sqlsrv_php_type_out, field_value, field_len )); if( fetch_type & SQLSRV_FETCH_NUMERIC ) { @@ -1873,7 +1855,7 @@ void fetch_fields_common( __inout ss_sqlsrv_stmt* stmt, zend_long fetch_type, __ CHECK_ZEND_ERROR( zr, stmt, SQLSRV_ERROR_ZEND_HASH ) { throw ss::SSException(); } - zval_add_ref( &field ); + Z_TRY_ADDREF_P(&field); } if( fetch_type & SQLSRV_FETCH_ASSOC ) { @@ -1889,7 +1871,7 @@ void fetch_fields_common( __inout ss_sqlsrv_stmt* stmt, zend_long fetch_type, __ CHECK_ZEND_ERROR( zr, stmt, SQLSRV_ERROR_ZEND_HASH ) { throw ss::SSException(); } - zval_add_ref( &field ); + Z_TRY_ADDREF_P(&field); } } } //for loop @@ -1938,6 +1920,11 @@ void parse_param_array( ss_sqlsrv_stmt* stmt, __inout zval* param_array, zend_ul stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION, index + 1 ) { throw ss::SSException(); } + + CHECK_CUSTOM_ERROR(!Z_ISREF_P(var_or_val) && (direction == SQL_PARAM_OUTPUT || direction == SQL_PARAM_INPUT_OUTPUT), stmt, SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF, index + 1) { + throw ss::SSException(); + } + } else { direction = SQL_PARAM_INPUT; diff --git a/sqlsrv/util.cpp b/sqlsrv/util.cpp index 5be50158..5632c06a 100644 --- a/sqlsrv/util.cpp +++ b/sqlsrv/util.cpp @@ -360,6 +360,12 @@ ss_error SS_ERRORS[] = { SQLSRV_ERROR_INVALID_BUFFER_LIMIT, { IMSSP, (SQLCHAR*) "Setting for " INI_BUFFERED_QUERY_LIMIT " was non-int or non-positive.", -60, false } }, + { + SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF, + { IMSSP, (SQLCHAR*)"Variable parameter %1!d! not passed by reference (prefaced with an &). " + "Output or bidirectional variable parameters (SQLSRV_PARAM_OUT and SQLSRV_PARAM_INOUT) passed to sqlsrv_prepare or sqlsrv_query should be passed by reference, not by value." + , -61, true } + }, // internal warning definitions { @@ -924,7 +930,7 @@ bool sqlsrv_merge_zend_hash( __inout zval* dest_z, zval const* src_z TSRMLS_DC ) zend_hash_apply( Z_ARRVAL_P( dest_z ), sqlsrv_merge_zend_hash_dtor TSRMLS_CC ); return false; } - zval_add_ref( value_z ); + Z_TRY_ADDREF_P(value_z); } return true; diff --git a/sqlsrv/version.h b/sqlsrv/version.h index c3d06906..9bc0a0ae 100644 --- a/sqlsrv/version.h +++ b/sqlsrv/version.h @@ -16,11 +16,11 @@ // IN THE SOFTWARE. //--------------------------------------------------------------------------------------------------------------------------------- -#define VER_FILEVERSION_STR "4.0.0.0" +#define VER_FILEVERSION_STR "4.0.8219.0" #define _FILEVERSION 4,0,0,0 #define SQLVERSION_MAJOR 4 #define SQLVERSION_MINOR 0 -#define SQLVERSION_MMDD 0 +#define SQLVERSION_MMDD 8219 #define SQLVERSION_REVISION 0