@@ -988,7 +988,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
988
988
return ;
989
989
}
990
990
991
- if (stmt->current_sensitivity_metadata != NULL ) {
991
+ if (stmt->current_sensitivity_metadata ) {
992
992
// Already cached, so return
993
993
return ;
994
994
}
@@ -1873,7 +1873,7 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
1873
1873
// be returned as a zval.
1874
1874
case SQLSRV_PHPTYPE_DATETIME:
1875
1875
{
1876
- char * field_value_temp = NULL ;
1876
+ sqlsrv_malloc_auto_ptr< char > field_value_temp;
1877
1877
SQLLEN field_len_temp = 0 ;
1878
1878
1879
1879
field_value_temp = static_cast <char *>(sqlsrv_malloc (MAX_DATETIME_STRING_LEN));
@@ -1882,8 +1882,7 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
1882
1882
SQLRETURN r = stmt->current_results ->get_data (field_index + 1 , SQL_C_CHAR, field_value_temp, MAX_DATETIME_STRING_LEN, &field_len_temp, true TSRMLS_CC);
1883
1883
1884
1884
if (r == SQL_NO_DATA || field_len_temp == SQL_NULL_DATA) {
1885
- sqlsrv_free (field_value_temp);
1886
- field_value_temp = NULL ;
1885
+ field_value_temp.reset ();
1887
1886
field_len_temp = 0 ;
1888
1887
}
1889
1888
@@ -1892,6 +1891,7 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
1892
1891
}
1893
1892
1894
1893
field_value = field_value_temp;
1894
+ field_value_temp.transferred ();
1895
1895
*field_len = field_len_temp;
1896
1896
1897
1897
break ;
@@ -2420,142 +2420,151 @@ void format_decimal_numbers(_In_ SQLSMALLINT decimals_places, _In_ SQLSMALLINT f
2420
2420
2421
2421
void finalize_output_parameters ( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
2422
2422
{
2423
- if ( Z_ISUNDEF (stmt->output_params ) )
2423
+ if ( Z_ISUNDEF (stmt->output_params ))
2424
2424
return ;
2425
2425
2426
- HashTable* params_ht = Z_ARRVAL ( stmt->output_params );
2426
+ HashTable* params_ht = Z_ARRVAL (stmt->output_params );
2427
2427
zend_ulong index = -1 ;
2428
2428
zend_string* key = NULL ;
2429
2429
void * output_param_temp = NULL ;
2430
2430
2431
- ZEND_HASH_FOREACH_KEY_PTR ( params_ht, index, key, output_param_temp ) {
2432
- sqlsrv_output_param* output_param = static_cast <sqlsrv_output_param*>( output_param_temp );
2433
- zval* value_z = Z_REFVAL_P ( output_param->param_z );
2434
- switch ( Z_TYPE_P ( value_z )) {
2435
- case IS_STRING:
2431
+ try {
2432
+ ZEND_HASH_FOREACH_KEY_PTR (params_ht, index, key, output_param_temp)
2436
2433
{
2437
- // adjust the length of the string to the value returned by SQLBindParameter in the ind_ptr parameter
2438
- char * str = Z_STRVAL_P ( value_z );
2439
- SQLLEN str_len = stmt->param_ind_ptrs [output_param->param_num ];
2440
- if ( str_len == 0 ) {
2441
- core::sqlsrv_zval_stringl ( value_z, " " , 0 );
2442
- continue ;
2443
- }
2444
- if ( str_len == SQL_NULL_DATA ) {
2445
- zend_string_release ( Z_STR_P ( value_z ));
2446
- ZVAL_NULL ( value_z );
2447
- continue ;
2448
- }
2449
-
2450
- // if there was more to output than buffer size to hold it, then throw a truncation error
2451
- int null_size = 0 ;
2452
- switch ( output_param->encoding ) {
2453
- case SQLSRV_ENCODING_UTF8:
2454
- null_size = sizeof ( SQLWCHAR ); // string isn't yet converted to UTF-8, still UTF-16
2455
- break ;
2456
- case SQLSRV_ENCODING_SYSTEM:
2457
- null_size = 1 ;
2458
- break ;
2459
- case SQLSRV_ENCODING_BINARY:
2460
- null_size = 0 ;
2461
- break ;
2462
- default :
2463
- SQLSRV_ASSERT ( false , " Invalid encoding in output_param structure." );
2464
- break ;
2465
- }
2466
- CHECK_CUSTOM_ERROR ( str_len > ( output_param->original_buffer_len - null_size ), stmt,
2467
- SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED, output_param->param_num + 1 ) {
2468
- throw core::CoreException ();
2469
- }
2470
-
2471
- // For ODBC 11+ see https://msdn.microsoft.com/en-us/library/jj219209.aspx
2472
- // A length value of SQL_NO_TOTAL for SQLBindParameter indicates that the buffer contains up to
2473
- // output_param->original_buffer_len data and is NULL terminated.
2474
- // The IF statement can be true when using connection pooling with unixODBC 2.3.4.
2475
- if ( str_len == SQL_NO_TOTAL )
2434
+ sqlsrv_output_param* output_param = static_cast <sqlsrv_output_param*>(output_param_temp);
2435
+ zval* value_z = Z_REFVAL_P (output_param->param_z );
2436
+ switch (Z_TYPE_P (value_z)) {
2437
+ case IS_STRING:
2476
2438
{
2477
- str_len = output_param->original_buffer_len - null_size;
2478
- }
2439
+ // adjust the length of the string to the value returned by SQLBindParameter in the ind_ptr parameter
2440
+ char * str = Z_STRVAL_P (value_z);
2441
+ SQLLEN str_len = stmt->param_ind_ptrs [output_param->param_num ];
2442
+ if (str_len == 0 ) {
2443
+ core::sqlsrv_zval_stringl (value_z, " " , 0 );
2444
+ continue ;
2445
+ }
2446
+ if (str_len == SQL_NULL_DATA) {
2447
+ zend_string_release (Z_STR_P (value_z));
2448
+ ZVAL_NULL (value_z);
2449
+ continue ;
2450
+ }
2479
2451
2480
- if (output_param->encoding == SQLSRV_ENCODING_BINARY) {
2481
- // ODBC doesn't null terminate binary encodings, but PHP complains if a string isn't null terminated
2482
- // so we do that here if the length of the returned data is less than the original allocation. The
2483
- // original allocation null terminates the buffer already.
2484
- if (str_len < output_param->original_buffer_len ) {
2485
- str[str_len] = ' \0 ' ;
2452
+ // if there was more to output than buffer size to hold it, then throw a truncation error
2453
+ int null_size = 0 ;
2454
+ switch (output_param->encoding ) {
2455
+ case SQLSRV_ENCODING_UTF8:
2456
+ null_size = sizeof (SQLWCHAR); // string isn't yet converted to UTF-8, still UTF-16
2457
+ break ;
2458
+ case SQLSRV_ENCODING_SYSTEM:
2459
+ null_size = 1 ;
2460
+ break ;
2461
+ case SQLSRV_ENCODING_BINARY:
2462
+ null_size = 0 ;
2463
+ break ;
2464
+ default :
2465
+ SQLSRV_ASSERT (false , " Invalid encoding in output_param structure." );
2466
+ break ;
2467
+ }
2468
+ CHECK_CUSTOM_ERROR (str_len > (output_param->original_buffer_len - null_size), stmt,
2469
+ SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED, output_param->param_num + 1 )
2470
+ {
2471
+ throw core::CoreException ();
2486
2472
}
2487
- core::sqlsrv_zval_stringl (value_z, str, str_len);
2488
- }
2489
- else {
2490
- param_meta_data metaData = output_param->getMetaData ();
2491
2473
2492
- if (output_param-> encoding != SQLSRV_ENCODING_CHAR) {
2493
- char * outString = NULL ;
2494
- SQLLEN outLen = 0 ;
2495
- bool result = convert_string_from_utf16 (output_param-> encoding , reinterpret_cast < const SQLWCHAR*>(str), int (str_len / sizeof (SQLWCHAR)), &outString, outLen );
2496
- CHECK_CUSTOM_ERROR (!result, stmt, SQLSRV_ERROR_OUTPUT_PARAM_ENCODING_TRANSLATE, get_last_error_message () ) {
2497
- throw core::CoreException () ;
2498
- }
2474
+ // For ODBC 11+ see https://msdn.microsoft.com/en-us/library/jj219209.aspx
2475
+ // A length value of SQL_NO_TOTAL for SQLBindParameter indicates that the buffer contains up to
2476
+ // output_param->original_buffer_len data and is NULL terminated.
2477
+ // The IF statement can be true when using connection pooling with unixODBC 2.3.4.
2478
+ if (str_len == SQL_NO_TOTAL ) {
2479
+ str_len = output_param-> original_buffer_len - null_size ;
2480
+ }
2499
2481
2500
- if (stmt->format_decimals && (metaData.sql_type == SQL_DECIMAL || metaData.sql_type == SQL_NUMERIC)) {
2501
- format_decimal_numbers (NO_CHANGE_DECIMAL_PLACES, metaData.decimal_digits , outString, &outLen);
2482
+ if (output_param->encoding == SQLSRV_ENCODING_BINARY) {
2483
+ // ODBC doesn't null terminate binary encodings, but PHP complains if a string isn't null terminated
2484
+ // so we do that here if the length of the returned data is less than the original allocation. The
2485
+ // original allocation null terminates the buffer already.
2486
+ if (str_len < output_param->original_buffer_len ) {
2487
+ str[str_len] = ' \0 ' ;
2502
2488
}
2503
-
2504
- core::sqlsrv_zval_stringl (value_z, outString, outLen);
2505
- sqlsrv_free (outString);
2489
+ core::sqlsrv_zval_stringl (value_z, str, str_len);
2506
2490
}
2507
2491
else {
2508
- if (stmt->format_decimals && (metaData.sql_type == SQL_DECIMAL || metaData.sql_type == SQL_NUMERIC)) {
2509
- format_decimal_numbers (NO_CHANGE_DECIMAL_PLACES, metaData.decimal_digits , str, &str_len);
2492
+ param_meta_data metaData = output_param->getMetaData ();
2493
+
2494
+ if (output_param->encoding != SQLSRV_ENCODING_CHAR) {
2495
+ char * outString = NULL ;
2496
+ SQLLEN outLen = 0 ;
2497
+ bool result = convert_string_from_utf16 (output_param->encoding , reinterpret_cast <const SQLWCHAR*>(str), int (str_len / sizeof (SQLWCHAR)), &outString, outLen);
2498
+ CHECK_CUSTOM_ERROR (!result, stmt, SQLSRV_ERROR_OUTPUT_PARAM_ENCODING_TRANSLATE, get_last_error_message ())
2499
+ {
2500
+ throw core::CoreException ();
2501
+ }
2502
+
2503
+ if (stmt->format_decimals && (metaData.sql_type == SQL_DECIMAL || metaData.sql_type == SQL_NUMERIC)) {
2504
+ format_decimal_numbers (NO_CHANGE_DECIMAL_PLACES, metaData.decimal_digits , outString, &outLen);
2505
+ }
2506
+
2507
+ core::sqlsrv_zval_stringl (value_z, outString, outLen);
2508
+ sqlsrv_free (outString);
2510
2509
}
2510
+ else {
2511
+ if (stmt->format_decimals && (metaData.sql_type == SQL_DECIMAL || metaData.sql_type == SQL_NUMERIC)) {
2512
+ format_decimal_numbers (NO_CHANGE_DECIMAL_PLACES, metaData.decimal_digits , str, &str_len);
2513
+ }
2511
2514
2512
- core::sqlsrv_zval_stringl (value_z, str, str_len);
2515
+ core::sqlsrv_zval_stringl (value_z, str, str_len);
2516
+ }
2513
2517
}
2514
2518
}
2515
- }
2516
- break ;
2517
- case IS_LONG:
2518
- // for a long or a float, simply check if NULL was returned and set the parameter to a PHP null if so
2519
- if ( stmt->param_ind_ptrs [output_param->param_num ] == SQL_NULL_DATA ) {
2520
- ZVAL_NULL ( value_z );
2521
- }
2522
- else if ( output_param->is_bool ) {
2523
- convert_to_boolean ( value_z );
2524
- }
2525
- else {
2526
- ZVAL_LONG ( value_z, static_cast <int >( Z_LVAL_P ( value_z )));
2527
- }
2528
2519
break ;
2529
- case IS_DOUBLE:
2530
- // for a long or a float, simply check if NULL was returned and set the parameter to a PHP null if so
2531
- if (stmt->param_ind_ptrs [output_param->param_num ] == SQL_NULL_DATA) {
2532
- ZVAL_NULL (value_z);
2533
- }
2534
- else if (output_param->php_out_type == SQLSRV_PHPTYPE_INT) {
2535
- // first check if its value is out of range
2536
- double dval = Z_DVAL_P (value_z);
2537
- if (dval > INT_MAX || dval < INT_MIN) {
2538
- CHECK_CUSTOM_ERROR (true , stmt, SQLSRV_ERROR_DOUBLE_CONVERSION_FAILED) {
2539
- throw core::CoreException ();
2540
- }
2520
+ case IS_LONG:
2521
+ // for a long or a float, simply check if NULL was returned and set the parameter to a PHP null if so
2522
+ if (stmt->param_ind_ptrs [output_param->param_num ] == SQL_NULL_DATA) {
2523
+ ZVAL_NULL (value_z);
2541
2524
}
2542
- // if the output param is a boolean, still convert to
2543
- // a long integer first to take care of rounding
2544
- convert_to_long (value_z);
2545
- if (output_param->is_bool ) {
2525
+ else if (output_param->is_bool ) {
2546
2526
convert_to_boolean (value_z);
2547
2527
}
2528
+ else {
2529
+ ZVAL_LONG (value_z, static_cast <int >(Z_LVAL_P (value_z)));
2530
+ }
2531
+ break ;
2532
+ case IS_DOUBLE:
2533
+ // for a long or a float, simply check if NULL was returned and set the parameter to a PHP null if so
2534
+ if (stmt->param_ind_ptrs [output_param->param_num ] == SQL_NULL_DATA) {
2535
+ ZVAL_NULL (value_z);
2536
+ }
2537
+ else if (output_param->php_out_type == SQLSRV_PHPTYPE_INT) {
2538
+ // first check if its value is out of range
2539
+ double dval = Z_DVAL_P (value_z);
2540
+ if (dval > INT_MAX || dval < INT_MIN) {
2541
+ CHECK_CUSTOM_ERROR (true , stmt, SQLSRV_ERROR_DOUBLE_CONVERSION_FAILED)
2542
+ {
2543
+ throw core::CoreException ();
2544
+ }
2545
+ }
2546
+ // if the output param is a boolean, still convert to
2547
+ // a long integer first to take care of rounding
2548
+ convert_to_long (value_z);
2549
+ if (output_param->is_bool ) {
2550
+ convert_to_boolean (value_z);
2551
+ }
2552
+ }
2553
+ break ;
2554
+ default :
2555
+ DIE (" Illegal or unknown output parameter type. This should have been caught in core_sqlsrv_bind_parameter." );
2556
+ break ;
2548
2557
}
2549
- break ;
2550
- default :
2551
- DIE ( " Illegal or unknown output parameter type. This should have been caught in core_sqlsrv_bind_parameter. " );
2552
- break ;
2553
- }
2554
- value_z = NULL ;
2555
- } ZEND_HASH_FOREACH_END () ;
2556
-
2558
+ value_z = NULL ;
2559
+ } ZEND_HASH_FOREACH_END ();
2560
+ }
2561
+ catch (core::CoreException&) {
2562
+ // empty the hash table due to exception caught
2563
+ zend_hash_clean ( Z_ARRVAL (stmt-> output_params )) ;
2564
+ throw ;
2565
+ }
2557
2566
// empty the hash table since it's been processed
2558
- zend_hash_clean ( Z_ARRVAL ( stmt->output_params ));
2567
+ zend_hash_clean (Z_ARRVAL (stmt->output_params ));
2559
2568
return ;
2560
2569
}
2561
2570
0 commit comments