@@ -1223,26 +1223,55 @@ PHP_FUNCTION(pg_query)
12231223 }
12241224}
12251225
1226- static void _php_pgsql_free_params (char * * params , int num_params )
1226+ /* The char pointer MUST refer to the char* of a zend_string struct */
1227+ static void php_pgsql_zend_string_release_from_char_pointer (char * ptr ) {
1228+ zend_string_release ((zend_string * ) (ptr - XtOffsetOf (zend_string , val )));
1229+ }
1230+
1231+ static void _php_pgsql_free_params (char * * params , uint32_t num_params )
12271232{
1228- int i ;
1229- for (i = 0 ; i < num_params ; i ++ ) {
1233+ for (uint32_t i = 0 ; i < num_params ; i ++ ) {
12301234 if (params [i ]) {
1231- efree (params [i ]);
1235+ php_pgsql_zend_string_release_from_char_pointer (params [i ]);
12321236 }
12331237 }
12341238 efree (params );
12351239}
12361240
1241+ static char * * php_pgsql_make_arguments (const HashTable * param_arr , int * num_params )
1242+ {
1243+ /* This conversion is safe because of the limit of number of elements in a table. */
1244+ * num_params = (int ) zend_hash_num_elements (param_arr );
1245+ char * * params = safe_emalloc (sizeof (char * ), * num_params , 0 );
1246+ uint32_t i = 0 ;
1247+
1248+ ZEND_HASH_FOREACH_VAL (param_arr , zval * tmp ) {
1249+ ZVAL_DEREF (tmp );
1250+ if (Z_TYPE_P (tmp ) == IS_NULL ) {
1251+ params [i ] = NULL ;
1252+ } else {
1253+ zend_string * param_str = zval_try_get_string (tmp );
1254+ if (!param_str ) {
1255+ _php_pgsql_free_params (params , i );
1256+ return NULL ;
1257+ }
1258+ params [i ] = ZSTR_VAL (param_str );
1259+ }
1260+ i ++ ;
1261+ } ZEND_HASH_FOREACH_END ();
1262+
1263+ return params ;
1264+ }
1265+
12371266/* Execute a query */
12381267PHP_FUNCTION (pg_query_params )
12391268{
12401269 zval * pgsql_link = NULL ;
1241- zval * pv_param_arr , * tmp ;
1270+ zval * pv_param_arr ;
12421271 char * query ;
12431272 size_t query_len ;
12441273 bool leftover = false;
1245- int num_params = 0 ;
1274+ int num_params ;
12461275 char * * params = NULL ;
12471276 pgsql_link_handle * link ;
12481277 PGconn * pgsql ;
@@ -1286,26 +1315,9 @@ PHP_FUNCTION(pg_query_params)
12861315 php_error_docref (NULL , E_NOTICE , "Found results on this connection. Use pg_get_result() to get these results first" );
12871316 }
12881317
1289- num_params = zend_hash_num_elements (Z_ARRVAL_P (pv_param_arr ));
1290- if (num_params > 0 ) {
1291- int i = 0 ;
1292- params = (char * * )safe_emalloc (sizeof (char * ), num_params , 0 );
1293-
1294- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (pv_param_arr ), tmp ) {
1295- ZVAL_DEREF (tmp );
1296- if (Z_TYPE_P (tmp ) == IS_NULL ) {
1297- params [i ] = NULL ;
1298- } else {
1299- zend_string * param_str = zval_try_get_string (tmp );
1300- if (!param_str ) {
1301- _php_pgsql_free_params (params , i );
1302- RETURN_THROWS ();
1303- }
1304- params [i ] = estrndup (ZSTR_VAL (param_str ), ZSTR_LEN (param_str ));
1305- zend_string_release (param_str );
1306- }
1307- i ++ ;
1308- } ZEND_HASH_FOREACH_END ();
1318+ params = php_pgsql_make_arguments (Z_ARRVAL_P (pv_param_arr ), & num_params );
1319+ if (UNEXPECTED (!params )) {
1320+ RETURN_THROWS ();
13091321 }
13101322
13111323 pgsql_result = PQexecParams (pgsql , query , num_params ,
@@ -1440,11 +1452,11 @@ PHP_FUNCTION(pg_prepare)
14401452PHP_FUNCTION (pg_execute )
14411453{
14421454 zval * pgsql_link = NULL ;
1443- zval * pv_param_arr , * tmp ;
1455+ zval * pv_param_arr ;
14441456 char * stmtname ;
14451457 size_t stmtname_len ;
14461458 bool leftover = false;
1447- int num_params = 0 ;
1459+ int num_params ;
14481460 char * * params = NULL ;
14491461 PGconn * pgsql ;
14501462 pgsql_link_handle * link ;
@@ -1488,25 +1500,9 @@ PHP_FUNCTION(pg_execute)
14881500 php_error_docref (NULL , E_NOTICE , "Found results on this connection. Use pg_get_result() to get these results first" );
14891501 }
14901502
1491- num_params = zend_hash_num_elements (Z_ARRVAL_P (pv_param_arr ));
1492- if (num_params > 0 ) {
1493- int i = 0 ;
1494- params = (char * * )safe_emalloc (sizeof (char * ), num_params , 0 );
1495-
1496- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (pv_param_arr ), tmp ) {
1497- ZVAL_DEREF (tmp );
1498- if (Z_TYPE_P (tmp ) == IS_NULL ) {
1499- params [i ] = NULL ;
1500- } else {
1501- zend_string * tmp_str ;
1502- zend_string * str = zval_get_tmp_string (tmp , & tmp_str );
1503-
1504- params [i ] = estrndup (ZSTR_VAL (str ), ZSTR_LEN (str ));
1505- zend_tmp_string_release (tmp_str );
1506- }
1507-
1508- i ++ ;
1509- } ZEND_HASH_FOREACH_END ();
1503+ params = php_pgsql_make_arguments (Z_ARRVAL_P (pv_param_arr ), & num_params );
1504+ if (UNEXPECTED (!params )) {
1505+ RETURN_THROWS ();
15101506 }
15111507
15121508 pgsql_result = PQexecPrepared (pgsql , stmtname , num_params ,
@@ -4034,9 +4030,9 @@ PHP_FUNCTION(pg_send_query)
40344030/* {{{ Send asynchronous parameterized query */
40354031PHP_FUNCTION (pg_send_query_params )
40364032{
4037- zval * pgsql_link , * pv_param_arr , * tmp ;
4033+ zval * pgsql_link , * pv_param_arr ;
40384034 pgsql_link_handle * link ;
4039- int num_params = 0 ;
4035+ int num_params ;
40404036 char * * params = NULL ;
40414037 char * query ;
40424038 size_t query_len ;
@@ -4066,25 +4062,9 @@ PHP_FUNCTION(pg_send_query_params)
40664062 "There are results on this connection. Call pg_get_result() until it returns FALSE" );
40674063 }
40684064
4069- num_params = zend_hash_num_elements (Z_ARRVAL_P (pv_param_arr ));
4070- if (num_params > 0 ) {
4071- int i = 0 ;
4072- params = (char * * )safe_emalloc (sizeof (char * ), num_params , 0 );
4073-
4074- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (pv_param_arr ), tmp ) {
4075- ZVAL_DEREF (tmp );
4076- if (Z_TYPE_P (tmp ) == IS_NULL ) {
4077- params [i ] = NULL ;
4078- } else {
4079- zend_string * tmp_str ;
4080- zend_string * str = zval_get_tmp_string (tmp , & tmp_str );
4081-
4082- params [i ] = estrndup (ZSTR_VAL (str ), ZSTR_LEN (str ));
4083- zend_tmp_string_release (tmp_str );
4084- }
4085-
4086- i ++ ;
4087- } ZEND_HASH_FOREACH_END ();
4065+ params = php_pgsql_make_arguments (Z_ARRVAL_P (pv_param_arr ), & num_params );
4066+ if (UNEXPECTED (!params )) {
4067+ RETURN_THROWS ();
40884068 }
40894069
40904070 if (PQsendQueryParams (pgsql , query , num_params , NULL , (const char * const * )params , NULL , NULL , 0 )) {
@@ -4206,8 +4186,8 @@ PHP_FUNCTION(pg_send_execute)
42064186{
42074187 zval * pgsql_link ;
42084188 pgsql_link_handle * link ;
4209- zval * pv_param_arr , * tmp ;
4210- int num_params = 0 ;
4189+ zval * pv_param_arr ;
4190+ int num_params ;
42114191 char * * params = NULL ;
42124192 char * stmtname ;
42134193 size_t stmtname_len ;
@@ -4237,27 +4217,9 @@ PHP_FUNCTION(pg_send_execute)
42374217 "There are results on this connection. Call pg_get_result() until it returns FALSE" );
42384218 }
42394219
4240- num_params = zend_hash_num_elements (Z_ARRVAL_P (pv_param_arr ));
4241- if (num_params > 0 ) {
4242- int i = 0 ;
4243- params = (char * * )safe_emalloc (sizeof (char * ), num_params , 0 );
4244-
4245- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (pv_param_arr ), tmp ) {
4246- ZVAL_DEREF (tmp );
4247- if (Z_TYPE_P (tmp ) == IS_NULL ) {
4248- params [i ] = NULL ;
4249- } else {
4250- zend_string * tmp_str = zval_try_get_string (tmp );
4251- if (UNEXPECTED (!tmp_str )) {
4252- _php_pgsql_free_params (params , i );
4253- return ;
4254- }
4255- params [i ] = estrndup (ZSTR_VAL (tmp_str ), ZSTR_LEN (tmp_str ));
4256- zend_string_release (tmp_str );
4257- }
4258-
4259- i ++ ;
4260- } ZEND_HASH_FOREACH_END ();
4220+ params = php_pgsql_make_arguments (Z_ARRVAL_P (pv_param_arr ), & num_params );
4221+ if (UNEXPECTED (!params )) {
4222+ RETURN_THROWS ();
42614223 }
42624224
42634225 if (PQsendQueryPrepared (pgsql , stmtname , num_params , (const char * const * )params , NULL , NULL , 0 )) {
0 commit comments