@@ -3203,8 +3203,14 @@ PHP_FUNCTION(pg_escape_string)
3203
3203
3204
3204
to = zend_string_safe_alloc (ZSTR_LEN (from ), 2 , 0 , 0 );
3205
3205
if (link ) {
3206
+ int err ;
3206
3207
pgsql = link -> conn ;
3207
- ZSTR_LEN (to ) = PQescapeStringConn (pgsql , ZSTR_VAL (to ), ZSTR_VAL (from ), ZSTR_LEN (from ), NULL );
3208
+ ZSTR_LEN (to ) = PQescapeStringConn (pgsql , ZSTR_VAL (to ), ZSTR_VAL (from ), ZSTR_LEN (from ), & err );
3209
+ if (err ) {
3210
+ zend_argument_value_error (ZEND_NUM_ARGS (), "Escaping string failed" );
3211
+ zend_string_efree (to );
3212
+ RETURN_THROWS ();
3213
+ }
3208
3214
} else
3209
3215
{
3210
3216
ZSTR_LEN (to ) = PQescapeString (ZSTR_VAL (to ), ZSTR_VAL (from ), ZSTR_LEN (from ));
@@ -3247,6 +3253,10 @@ PHP_FUNCTION(pg_escape_bytea)
3247
3253
} else {
3248
3254
to = (char * )PQescapeBytea ((unsigned char * )ZSTR_VAL (from ), ZSTR_LEN (from ), & to_len );
3249
3255
}
3256
+ if (to == NULL ) {
3257
+ zend_argument_value_error (ZEND_NUM_ARGS (), "Escape failure" );
3258
+ RETURN_THROWS ();
3259
+ }
3250
3260
3251
3261
RETVAL_STRINGL (to , to_len - 1 ); /* to_len includes additional '\0' */
3252
3262
PQfreemem (to );
@@ -4163,7 +4173,7 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string
4163
4173
char * escaped ;
4164
4174
smart_str querystr = {0 };
4165
4175
size_t new_len ;
4166
- int i , num_rows ;
4176
+ int i , num_rows , err ;
4167
4177
zval elem ;
4168
4178
4169
4179
ZEND_ASSERT (ZSTR_LEN (table_name ) != 0 );
@@ -4202,15 +4212,29 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string
4202
4212
"WHERE a.attnum > 0 AND c.relname = '" );
4203
4213
}
4204
4214
escaped = (char * )safe_emalloc (strlen (tmp_name2 ), 2 , 1 );
4205
- new_len = PQescapeStringConn (pg_link , escaped , tmp_name2 , strlen (tmp_name2 ), NULL );
4215
+ new_len = PQescapeStringConn (pg_link , escaped , tmp_name2 , strlen (tmp_name2 ), & err );
4216
+ if (err ) {
4217
+ php_error_docref (NULL , E_WARNING , "Escaping table name '%s' failed" , ZSTR_VAL (table_name ));
4218
+ efree (src );
4219
+ efree (escaped );
4220
+ smart_str_free (& querystr );
4221
+ return FAILURE ;
4222
+ }
4206
4223
if (new_len ) {
4207
4224
smart_str_appendl (& querystr , escaped , new_len );
4208
4225
}
4209
4226
efree (escaped );
4210
4227
4211
4228
smart_str_appends (& querystr , "' AND n.nspname = '" );
4212
4229
escaped = (char * )safe_emalloc (strlen (tmp_name ), 2 , 1 );
4213
- new_len = PQescapeStringConn (pg_link , escaped , tmp_name , strlen (tmp_name ), NULL );
4230
+ new_len = PQescapeStringConn (pg_link , escaped , tmp_name , strlen (tmp_name ), & err );
4231
+ if (err ) {
4232
+ php_error_docref (NULL , E_WARNING , "Escaping table namespace '%s' failed" , ZSTR_VAL (table_name ));
4233
+ efree (src );
4234
+ efree (escaped );
4235
+ smart_str_free (& querystr );
4236
+ return FAILURE ;
4237
+ }
4214
4238
if (new_len ) {
4215
4239
smart_str_appendl (& querystr , escaped , new_len );
4216
4240
}
@@ -4471,7 +4495,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4471
4495
{
4472
4496
zend_string * field = NULL ;
4473
4497
zval meta , * def , * type , * not_null , * has_default , * is_enum , * val , new_val ;
4474
- int err = 0 , skip_field ;
4498
+ int err = 0 , escape_err = 0 , skip_field ;
4475
4499
php_pgsql_data_type data_type ;
4476
4500
4477
4501
ZEND_ASSERT (pg_link != NULL );
@@ -4724,8 +4748,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4724
4748
/* PostgreSQL ignores \0 */
4725
4749
str = zend_string_alloc (Z_STRLEN_P (val ) * 2 , 0 );
4726
4750
/* better to use PGSQLescapeLiteral since PGescapeStringConn does not handle special \ */
4727
- ZSTR_LEN (str ) = PQescapeStringConn (pg_link , ZSTR_VAL (str ), Z_STRVAL_P (val ), Z_STRLEN_P (val ), NULL );
4728
- ZVAL_STR (& new_val , php_pgsql_add_quotes (str ));
4751
+ ZSTR_LEN (str ) = PQescapeStringConn (pg_link , ZSTR_VAL (str ),
4752
+ Z_STRVAL_P (val ), Z_STRLEN_P (val ), & escape_err );
4753
+ if (escape_err ) {
4754
+ err = 1 ;
4755
+ } else {
4756
+ ZVAL_STR (& new_val , php_pgsql_add_quotes (str ));
4757
+ }
4729
4758
zend_string_release_ex (str , false);
4730
4759
}
4731
4760
break ;
@@ -4748,7 +4777,15 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4748
4777
}
4749
4778
PGSQL_CONV_CHECK_IGNORE ();
4750
4779
if (err ) {
4751
- php_error_docref (NULL , E_NOTICE , "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)" , Z_STRVAL_P (type ), ZSTR_VAL (field ));
4780
+ if (escape_err ) {
4781
+ php_error_docref (NULL , E_NOTICE ,
4782
+ "String value escaping failed for PostgreSQL '%s' (%s)" ,
4783
+ Z_STRVAL_P (type ), ZSTR_VAL (field ));
4784
+ } else {
4785
+ php_error_docref (NULL , E_NOTICE ,
4786
+ "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)" ,
4787
+ Z_STRVAL_P (type ), ZSTR_VAL (field ));
4788
+ }
4752
4789
}
4753
4790
break ;
4754
4791
@@ -5019,6 +5056,11 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5019
5056
zend_string * tmp_zstr ;
5020
5057
5021
5058
tmp = PQescapeByteaConn (pg_link , (unsigned char * )Z_STRVAL_P (val ), Z_STRLEN_P (val ), & to_len );
5059
+ if (tmp == NULL ) {
5060
+ php_error_docref (NULL , E_NOTICE , "Escaping value failed for %s field (%s)" , Z_STRVAL_P (type ), ZSTR_VAL (field ));
5061
+ err = 1 ;
5062
+ break ;
5063
+ }
5022
5064
tmp_zstr = zend_string_init ((char * )tmp , to_len - 1 , false); /* PQescapeBytea's to_len includes additional '\0' */
5023
5065
PQfreemem (tmp );
5024
5066
@@ -5097,6 +5139,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5097
5139
zend_hash_update (Z_ARRVAL_P (result ), field , & new_val );
5098
5140
} else {
5099
5141
char * escaped = PQescapeIdentifier (pg_link , ZSTR_VAL (field ), ZSTR_LEN (field ));
5142
+ if (escaped == NULL ) {
5143
+ /* This cannot fail because of invalid string but only due to failed memory allocation */
5144
+ php_error_docref (NULL , E_NOTICE , "Escaping field '%s' failed" , ZSTR_VAL (field ));
5145
+ err = 1 ;
5146
+ break ;
5147
+ }
5100
5148
add_assoc_zval (result , escaped , & new_val );
5101
5149
PQfreemem (escaped );
5102
5150
}
@@ -5175,7 +5223,7 @@ static bool do_exec(smart_str *querystr, ExecStatusType expect, PGconn *pg_link,
5175
5223
}
5176
5224
/* }}} */
5177
5225
5178
- static inline void build_tablename (smart_str * querystr , PGconn * pg_link , const zend_string * table ) /* {{{ */
5226
+ static inline zend_result build_tablename (smart_str * querystr , PGconn * pg_link , const zend_string * table ) /* {{{ */
5179
5227
{
5180
5228
/* schema.table should be "schema"."table" */
5181
5229
const char * dot = memchr (ZSTR_VAL (table ), '.' , ZSTR_LEN (table ));
@@ -5185,6 +5233,10 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z
5185
5233
smart_str_appendl (querystr , ZSTR_VAL (table ), len );
5186
5234
} else {
5187
5235
char * escaped = PQescapeIdentifier (pg_link , ZSTR_VAL (table ), len );
5236
+ if (escaped == NULL ) {
5237
+ php_error_docref (NULL , E_NOTICE , "Failed to escape table name '%s'" , ZSTR_VAL (table ));
5238
+ return FAILURE ;
5239
+ }
5188
5240
smart_str_appends (querystr , escaped );
5189
5241
PQfreemem (escaped );
5190
5242
}
@@ -5197,11 +5249,17 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z
5197
5249
smart_str_appendl (querystr , after_dot , len );
5198
5250
} else {
5199
5251
char * escaped = PQescapeIdentifier (pg_link , after_dot , len );
5252
+ if (escaped == NULL ) {
5253
+ php_error_docref (NULL , E_NOTICE , "Failed to escape table name '%s'" , ZSTR_VAL (table ));
5254
+ return FAILURE ;
5255
+ }
5200
5256
smart_str_appendc (querystr , '.' );
5201
5257
smart_str_appends (querystr , escaped );
5202
5258
PQfreemem (escaped );
5203
5259
}
5204
5260
}
5261
+
5262
+ return SUCCESS ;
5205
5263
}
5206
5264
/* }}} */
5207
5265
@@ -5222,7 +5280,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
5222
5280
ZVAL_UNDEF (& converted );
5223
5281
if (zend_hash_num_elements (Z_ARRVAL_P (var_array )) == 0 ) {
5224
5282
smart_str_appends (& querystr , "INSERT INTO " );
5225
- build_tablename (& querystr , pg_link , table );
5283
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5284
+ goto cleanup ;
5285
+ }
5226
5286
smart_str_appends (& querystr , " DEFAULT VALUES" );
5227
5287
5228
5288
goto no_values ;
@@ -5238,7 +5298,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
5238
5298
}
5239
5299
5240
5300
smart_str_appends (& querystr , "INSERT INTO " );
5241
- build_tablename (& querystr , pg_link , table );
5301
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5302
+ goto cleanup ;
5303
+ }
5242
5304
smart_str_appends (& querystr , " (" );
5243
5305
5244
5306
ZEND_HASH_FOREACH_STR_KEY (Z_ARRVAL_P (var_array ), fld ) {
@@ -5248,6 +5310,10 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
5248
5310
}
5249
5311
if (opt & PGSQL_DML_ESCAPE ) {
5250
5312
tmp = PQescapeIdentifier (pg_link , ZSTR_VAL (fld ), ZSTR_LEN (fld ) + 1 );
5313
+ if (tmp == NULL ) {
5314
+ php_error_docref (NULL , E_NOTICE , "Failed to escape field '%s'" , ZSTR_VAL (fld ));
5315
+ goto cleanup ;
5316
+ }
5251
5317
smart_str_appends (& querystr , tmp );
5252
5318
PQfreemem (tmp );
5253
5319
} else {
@@ -5259,15 +5325,19 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
5259
5325
smart_str_appends (& querystr , ") VALUES (" );
5260
5326
5261
5327
/* make values string */
5262
- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (var_array ), val ) {
5328
+ ZEND_HASH_FOREACH_STR_KEY_VAL (Z_ARRVAL_P (var_array ), fld , val ) {
5263
5329
/* we can avoid the key_type check here, because we tested it in the other loop */
5264
5330
switch (Z_TYPE_P (val )) {
5265
5331
case IS_STRING :
5266
5332
if (opt & PGSQL_DML_ESCAPE ) {
5267
- size_t new_len ;
5268
- char * tmp ;
5269
- tmp = (char * )safe_emalloc (Z_STRLEN_P (val ), 2 , 1 );
5270
- new_len = PQescapeStringConn (pg_link , tmp , Z_STRVAL_P (val ), Z_STRLEN_P (val ), NULL );
5333
+ int error ;
5334
+ char * tmp = safe_emalloc (Z_STRLEN_P (val ), 2 , 1 );
5335
+ size_t new_len = PQescapeStringConn (pg_link , tmp , Z_STRVAL_P (val ), Z_STRLEN_P (val ), & error );
5336
+ if (error ) {
5337
+ php_error_docref (NULL , E_NOTICE , "Failed to escape field '%s' value" , ZSTR_VAL (fld ));
5338
+ efree (tmp );
5339
+ goto cleanup ;
5340
+ }
5271
5341
smart_str_appendc (& querystr , '\'' );
5272
5342
smart_str_appendl (& querystr , tmp , new_len );
5273
5343
smart_str_appendc (& querystr , '\'' );
@@ -5423,6 +5493,10 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
5423
5493
}
5424
5494
if (opt & PGSQL_DML_ESCAPE ) {
5425
5495
char * tmp = PQescapeIdentifier (pg_link , ZSTR_VAL (fld ), ZSTR_LEN (fld ) + 1 );
5496
+ if (tmp == NULL ) {
5497
+ php_error_docref (NULL , E_NOTICE , "Failed to escape field '%s'" , ZSTR_VAL (fld ));
5498
+ return -1 ;
5499
+ }
5426
5500
smart_str_appends (querystr , tmp );
5427
5501
PQfreemem (tmp );
5428
5502
} else {
@@ -5438,8 +5512,14 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
5438
5512
switch (Z_TYPE_P (val )) {
5439
5513
case IS_STRING :
5440
5514
if (opt & PGSQL_DML_ESCAPE ) {
5515
+ int error ;
5441
5516
char * tmp = (char * )safe_emalloc (Z_STRLEN_P (val ), 2 , 1 );
5442
- size_t new_len = PQescapeStringConn (pg_link , tmp , Z_STRVAL_P (val ), Z_STRLEN_P (val ), NULL );
5517
+ size_t new_len = PQescapeStringConn (pg_link , tmp , Z_STRVAL_P (val ), Z_STRLEN_P (val ), & error );
5518
+ if (error ) {
5519
+ php_error_docref (NULL , E_NOTICE , "Failed to escape field '%s' value" , ZSTR_VAL (fld ));
5520
+ efree (tmp );
5521
+ return -1 ;
5522
+ }
5443
5523
smart_str_appendc (querystr , '\'' );
5444
5524
smart_str_appendl (querystr , tmp , new_len );
5445
5525
smart_str_appendc (querystr , '\'' );
@@ -5507,7 +5587,9 @@ PHP_PGSQL_API zend_result php_pgsql_update(PGconn *pg_link, const zend_string *t
5507
5587
}
5508
5588
5509
5589
smart_str_appends (& querystr , "UPDATE " );
5510
- build_tablename (& querystr , pg_link , table );
5590
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5591
+ goto cleanup ;
5592
+ }
5511
5593
smart_str_appends (& querystr , " SET " );
5512
5594
5513
5595
if (build_assignment_string (pg_link , & querystr , Z_ARRVAL_P (var_array ), 0 , "," , 1 , opt ))
@@ -5610,7 +5692,9 @@ PHP_PGSQL_API zend_result php_pgsql_delete(PGconn *pg_link, const zend_string *t
5610
5692
}
5611
5693
5612
5694
smart_str_appends (& querystr , "DELETE FROM " );
5613
- build_tablename (& querystr , pg_link , table );
5695
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5696
+ goto cleanup ;
5697
+ }
5614
5698
smart_str_appends (& querystr , " WHERE " );
5615
5699
5616
5700
if (build_assignment_string (pg_link , & querystr , Z_ARRVAL_P (ids_array ), 1 , " AND " , sizeof (" AND " )- 1 , opt ))
@@ -5750,7 +5834,9 @@ PHP_PGSQL_API zend_result php_pgsql_select(PGconn *pg_link, const zend_string *t
5750
5834
}
5751
5835
5752
5836
smart_str_appends (& querystr , "SELECT * FROM " );
5753
- build_tablename (& querystr , pg_link , table );
5837
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5838
+ goto cleanup ;
5839
+ }
5754
5840
smart_str_appends (& querystr , " WHERE " );
5755
5841
5756
5842
if (build_assignment_string (pg_link , & querystr , Z_ARRVAL_P (ids_array ), 1 , " AND " , sizeof (" AND " )- 1 , opt ))
0 commit comments