@@ -3269,8 +3269,14 @@ PHP_FUNCTION(pg_escape_string)
3269
3269
3270
3270
to = zend_string_safe_alloc (ZSTR_LEN (from ), 2 , 0 , 0 );
3271
3271
if (link ) {
3272
+ int err ;
3272
3273
pgsql = link -> conn ;
3273
- ZSTR_LEN (to ) = PQescapeStringConn (pgsql , ZSTR_VAL (to ), ZSTR_VAL (from ), ZSTR_LEN (from ), NULL );
3274
+ ZSTR_LEN (to ) = PQescapeStringConn (pgsql , ZSTR_VAL (to ), ZSTR_VAL (from ), ZSTR_LEN (from ), & err );
3275
+ if (err ) {
3276
+ zend_argument_value_error (ZEND_NUM_ARGS (), "Escaping string failed" );
3277
+ zend_string_efree (to );
3278
+ RETURN_THROWS ();
3279
+ }
3274
3280
} else
3275
3281
{
3276
3282
ZSTR_LEN (to ) = PQescapeString (ZSTR_VAL (to ), ZSTR_VAL (from ), ZSTR_LEN (from ));
@@ -3313,6 +3319,10 @@ PHP_FUNCTION(pg_escape_bytea)
3313
3319
} else {
3314
3320
to = (char * )PQescapeBytea ((unsigned char * )ZSTR_VAL (from ), ZSTR_LEN (from ), & to_len );
3315
3321
}
3322
+ if (to == NULL ) {
3323
+ zend_argument_value_error (ZEND_NUM_ARGS (), "Escape failure" );
3324
+ RETURN_THROWS ();
3325
+ }
3316
3326
3317
3327
RETVAL_STRINGL (to , to_len - 1 ); /* to_len includes additional '\0' */
3318
3328
PQfreemem (to );
@@ -4245,7 +4255,7 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string
4245
4255
char * escaped ;
4246
4256
smart_str querystr = {0 };
4247
4257
size_t new_len ;
4248
- int i , num_rows ;
4258
+ int i , num_rows , err ;
4249
4259
zval elem ;
4250
4260
4251
4261
ZEND_ASSERT (ZSTR_LEN (table_name ) != 0 );
@@ -4283,15 +4293,29 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string
4283
4293
"WHERE a.attnum > 0 AND c.relname = '" );
4284
4294
}
4285
4295
escaped = (char * )safe_emalloc (strlen (tmp_name2 ), 2 , 1 );
4286
- new_len = PQescapeStringConn (pg_link , escaped , tmp_name2 , strlen (tmp_name2 ), NULL );
4296
+ new_len = PQescapeStringConn (pg_link , escaped , tmp_name2 , strlen (tmp_name2 ), & err );
4297
+ if (err ) {
4298
+ php_error_docref (NULL , E_WARNING , "Escaping table name '%s' failed" , ZSTR_VAL (table_name ));
4299
+ efree (src );
4300
+ efree (escaped );
4301
+ smart_str_free (& querystr );
4302
+ return FAILURE ;
4303
+ }
4287
4304
if (new_len ) {
4288
4305
smart_str_appendl (& querystr , escaped , new_len );
4289
4306
}
4290
4307
efree (escaped );
4291
4308
4292
4309
smart_str_appends (& querystr , "' AND n.nspname = '" );
4293
4310
escaped = (char * )safe_emalloc (strlen (tmp_name ), 2 , 1 );
4294
- new_len = PQescapeStringConn (pg_link , escaped , tmp_name , strlen (tmp_name ), NULL );
4311
+ new_len = PQescapeStringConn (pg_link , escaped , tmp_name , strlen (tmp_name ), & err );
4312
+ if (err ) {
4313
+ php_error_docref (NULL , E_WARNING , "Escaping table namespace '%s' failed" , ZSTR_VAL (table_name ));
4314
+ efree (src );
4315
+ efree (escaped );
4316
+ smart_str_free (& querystr );
4317
+ return FAILURE ;
4318
+ }
4295
4319
if (new_len ) {
4296
4320
smart_str_appendl (& querystr , escaped , new_len );
4297
4321
}
@@ -4552,7 +4576,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4552
4576
{
4553
4577
zend_string * field = NULL ;
4554
4578
zval meta , * def , * type , * not_null , * has_default , * is_enum , * val , new_val ;
4555
- int err = 0 , skip_field ;
4579
+ int err = 0 , escape_err = 0 , skip_field ;
4556
4580
php_pgsql_data_type data_type ;
4557
4581
4558
4582
ZEND_ASSERT (pg_link != NULL );
@@ -4804,8 +4828,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4804
4828
/* PostgreSQL ignores \0 */
4805
4829
str = zend_string_alloc (Z_STRLEN_P (val ) * 2 , 0 );
4806
4830
/* better to use PGSQLescapeLiteral since PGescapeStringConn does not handle special \ */
4807
- ZSTR_LEN (str ) = PQescapeStringConn (pg_link , ZSTR_VAL (str ), Z_STRVAL_P (val ), Z_STRLEN_P (val ), NULL );
4808
- ZVAL_STR (& new_val , php_pgsql_add_quotes (str ));
4831
+ ZSTR_LEN (str ) = PQescapeStringConn (pg_link , ZSTR_VAL (str ),
4832
+ Z_STRVAL_P (val ), Z_STRLEN_P (val ), & escape_err );
4833
+ if (escape_err ) {
4834
+ err = 1 ;
4835
+ } else {
4836
+ ZVAL_STR (& new_val , php_pgsql_add_quotes (str ));
4837
+ }
4809
4838
zend_string_release_ex (str , false);
4810
4839
}
4811
4840
break ;
@@ -4828,7 +4857,14 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
4828
4857
}
4829
4858
PGSQL_CONV_CHECK_IGNORE ();
4830
4859
if (err ) {
4831
- zend_type_error ("%s(): Field \"%s\" must be of type string|null, %s given" , get_active_function_name (), ZSTR_VAL (field ), Z_STRVAL_P (type ));
4860
+ if (escape_err ) {
4861
+ php_error_docref (NULL , E_NOTICE ,
4862
+ "String value escaping failed for PostgreSQL '%s' (%s)" ,
4863
+ Z_STRVAL_P (type ), ZSTR_VAL (field ));
4864
+ } else {
4865
+ zend_type_error ("%s(): Field \"%s\" must be of type string|null, %s given" ,
4866
+ get_active_function_name (), ZSTR_VAL (field ), Z_STRVAL_P (type ));
4867
+ }
4832
4868
}
4833
4869
break ;
4834
4870
@@ -5103,6 +5139,11 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5103
5139
zend_string * tmp_zstr ;
5104
5140
5105
5141
tmp = PQescapeByteaConn (pg_link , (unsigned char * )Z_STRVAL_P (val ), Z_STRLEN_P (val ), & to_len );
5142
+ if (tmp == NULL ) {
5143
+ php_error_docref (NULL , E_NOTICE , "Escaping value failed for %s field (%s)" , Z_STRVAL_P (type ), ZSTR_VAL (field ));
5144
+ err = 1 ;
5145
+ break ;
5146
+ }
5106
5147
tmp_zstr = zend_string_init ((char * )tmp , to_len - 1 , false); /* PQescapeBytea's to_len includes additional '\0' */
5107
5148
PQfreemem (tmp );
5108
5149
@@ -5181,6 +5222,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
5181
5222
zend_hash_update (Z_ARRVAL_P (result ), field , & new_val );
5182
5223
} else {
5183
5224
char * escaped = PQescapeIdentifier (pg_link , ZSTR_VAL (field ), ZSTR_LEN (field ));
5225
+ if (escaped == NULL ) {
5226
+ /* This cannot fail because of invalid string but only due to failed memory allocation */
5227
+ php_error_docref (NULL , E_NOTICE , "Escaping field '%s' failed" , ZSTR_VAL (field ));
5228
+ err = 1 ;
5229
+ break ;
5230
+ }
5184
5231
add_assoc_zval (result , escaped , & new_val );
5185
5232
PQfreemem (escaped );
5186
5233
}
@@ -5259,7 +5306,7 @@ static bool do_exec(smart_str *querystr, ExecStatusType expect, PGconn *pg_link,
5259
5306
}
5260
5307
/* }}} */
5261
5308
5262
- static inline void build_tablename (smart_str * querystr , PGconn * pg_link , const zend_string * table ) /* {{{ */
5309
+ static inline zend_result build_tablename (smart_str * querystr , PGconn * pg_link , const zend_string * table ) /* {{{ */
5263
5310
{
5264
5311
/* schema.table should be "schema"."table" */
5265
5312
const char * dot = memchr (ZSTR_VAL (table ), '.' , ZSTR_LEN (table ));
@@ -5269,6 +5316,10 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z
5269
5316
smart_str_appendl (querystr , ZSTR_VAL (table ), len );
5270
5317
} else {
5271
5318
char * escaped = PQescapeIdentifier (pg_link , ZSTR_VAL (table ), len );
5319
+ if (escaped == NULL ) {
5320
+ php_error_docref (NULL , E_NOTICE , "Failed to escape table name '%s'" , ZSTR_VAL (table ));
5321
+ return FAILURE ;
5322
+ }
5272
5323
smart_str_appends (querystr , escaped );
5273
5324
PQfreemem (escaped );
5274
5325
}
@@ -5281,11 +5332,17 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z
5281
5332
smart_str_appendl (querystr , after_dot , len );
5282
5333
} else {
5283
5334
char * escaped = PQescapeIdentifier (pg_link , after_dot , len );
5335
+ if (escaped == NULL ) {
5336
+ php_error_docref (NULL , E_NOTICE , "Failed to escape table name '%s'" , ZSTR_VAL (table ));
5337
+ return FAILURE ;
5338
+ }
5284
5339
smart_str_appendc (querystr , '.' );
5285
5340
smart_str_appends (querystr , escaped );
5286
5341
PQfreemem (escaped );
5287
5342
}
5288
5343
}
5344
+
5345
+ return SUCCESS ;
5289
5346
}
5290
5347
/* }}} */
5291
5348
@@ -5306,7 +5363,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
5306
5363
ZVAL_UNDEF (& converted );
5307
5364
if (zend_hash_num_elements (Z_ARRVAL_P (var_array )) == 0 ) {
5308
5365
smart_str_appends (& querystr , "INSERT INTO " );
5309
- build_tablename (& querystr , pg_link , table );
5366
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5367
+ goto cleanup ;
5368
+ }
5310
5369
smart_str_appends (& querystr , " DEFAULT VALUES" );
5311
5370
5312
5371
goto no_values ;
@@ -5322,7 +5381,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
5322
5381
}
5323
5382
5324
5383
smart_str_appends (& querystr , "INSERT INTO " );
5325
- build_tablename (& querystr , pg_link , table );
5384
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5385
+ goto cleanup ;
5386
+ }
5326
5387
smart_str_appends (& querystr , " (" );
5327
5388
5328
5389
ZEND_HASH_FOREACH_STR_KEY (Z_ARRVAL_P (var_array ), fld ) {
@@ -5332,6 +5393,10 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
5332
5393
}
5333
5394
if (opt & PGSQL_DML_ESCAPE ) {
5334
5395
tmp = PQescapeIdentifier (pg_link , ZSTR_VAL (fld ), ZSTR_LEN (fld ) + 1 );
5396
+ if (tmp == NULL ) {
5397
+ php_error_docref (NULL , E_NOTICE , "Failed to escape field '%s'" , ZSTR_VAL (fld ));
5398
+ goto cleanup ;
5399
+ }
5335
5400
smart_str_appends (& querystr , tmp );
5336
5401
PQfreemem (tmp );
5337
5402
} else {
@@ -5343,15 +5408,19 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
5343
5408
smart_str_appends (& querystr , ") VALUES (" );
5344
5409
5345
5410
/* make values string */
5346
- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (var_array ), val ) {
5411
+ ZEND_HASH_FOREACH_STR_KEY_VAL (Z_ARRVAL_P (var_array ), fld , val ) {
5347
5412
/* we can avoid the key_type check here, because we tested it in the other loop */
5348
5413
switch (Z_TYPE_P (val )) {
5349
5414
case IS_STRING :
5350
5415
if (opt & PGSQL_DML_ESCAPE ) {
5351
- size_t new_len ;
5352
- char * tmp ;
5353
- tmp = (char * )safe_emalloc (Z_STRLEN_P (val ), 2 , 1 );
5354
- new_len = PQescapeStringConn (pg_link , tmp , Z_STRVAL_P (val ), Z_STRLEN_P (val ), NULL );
5416
+ int error ;
5417
+ char * tmp = safe_emalloc (Z_STRLEN_P (val ), 2 , 1 );
5418
+ size_t new_len = PQescapeStringConn (pg_link , tmp , Z_STRVAL_P (val ), Z_STRLEN_P (val ), & error );
5419
+ if (error ) {
5420
+ php_error_docref (NULL , E_NOTICE , "Failed to escape field '%s' value" , ZSTR_VAL (fld ));
5421
+ efree (tmp );
5422
+ goto cleanup ;
5423
+ }
5355
5424
smart_str_appendc (& querystr , '\'' );
5356
5425
smart_str_appendl (& querystr , tmp , new_len );
5357
5426
smart_str_appendc (& querystr , '\'' );
@@ -5507,6 +5576,10 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
5507
5576
}
5508
5577
if (opt & PGSQL_DML_ESCAPE ) {
5509
5578
char * tmp = PQescapeIdentifier (pg_link , ZSTR_VAL (fld ), ZSTR_LEN (fld ) + 1 );
5579
+ if (tmp == NULL ) {
5580
+ php_error_docref (NULL , E_NOTICE , "Failed to escape field '%s'" , ZSTR_VAL (fld ));
5581
+ return -1 ;
5582
+ }
5510
5583
smart_str_appends (querystr , tmp );
5511
5584
PQfreemem (tmp );
5512
5585
} else {
@@ -5522,8 +5595,14 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
5522
5595
switch (Z_TYPE_P (val )) {
5523
5596
case IS_STRING :
5524
5597
if (opt & PGSQL_DML_ESCAPE ) {
5598
+ int error ;
5525
5599
char * tmp = (char * )safe_emalloc (Z_STRLEN_P (val ), 2 , 1 );
5526
- size_t new_len = PQescapeStringConn (pg_link , tmp , Z_STRVAL_P (val ), Z_STRLEN_P (val ), NULL );
5600
+ size_t new_len = PQescapeStringConn (pg_link , tmp , Z_STRVAL_P (val ), Z_STRLEN_P (val ), & error );
5601
+ if (error ) {
5602
+ php_error_docref (NULL , E_NOTICE , "Failed to escape field '%s' value" , ZSTR_VAL (fld ));
5603
+ efree (tmp );
5604
+ return -1 ;
5605
+ }
5527
5606
smart_str_appendc (querystr , '\'' );
5528
5607
smart_str_appendl (querystr , tmp , new_len );
5529
5608
smart_str_appendc (querystr , '\'' );
@@ -5591,7 +5670,9 @@ PHP_PGSQL_API zend_result php_pgsql_update(PGconn *pg_link, const zend_string *t
5591
5670
}
5592
5671
5593
5672
smart_str_appends (& querystr , "UPDATE " );
5594
- build_tablename (& querystr , pg_link , table );
5673
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5674
+ goto cleanup ;
5675
+ }
5595
5676
smart_str_appends (& querystr , " SET " );
5596
5677
5597
5678
if (build_assignment_string (pg_link , & querystr , Z_ARRVAL_P (var_array ), 0 , "," , 1 , opt ))
@@ -5694,7 +5775,9 @@ PHP_PGSQL_API zend_result php_pgsql_delete(PGconn *pg_link, const zend_string *t
5694
5775
}
5695
5776
5696
5777
smart_str_appends (& querystr , "DELETE FROM " );
5697
- build_tablename (& querystr , pg_link , table );
5778
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5779
+ goto cleanup ;
5780
+ }
5698
5781
smart_str_appends (& querystr , " WHERE " );
5699
5782
5700
5783
if (build_assignment_string (pg_link , & querystr , Z_ARRVAL_P (ids_array ), 1 , " AND " , sizeof (" AND " )- 1 , opt ))
@@ -5834,7 +5917,9 @@ PHP_PGSQL_API zend_result php_pgsql_select(PGconn *pg_link, const zend_string *t
5834
5917
}
5835
5918
5836
5919
smart_str_appends (& querystr , "SELECT * FROM " );
5837
- build_tablename (& querystr , pg_link , table );
5920
+ if (build_tablename (& querystr , pg_link , table ) == FAILURE ) {
5921
+ goto cleanup ;
5922
+ }
5838
5923
smart_str_appends (& querystr , " WHERE " );
5839
5924
5840
5925
if (build_assignment_string (pg_link , & querystr , Z_ARRVAL_P (ids_array ), 1 , " AND " , sizeof (" AND " )- 1 , opt ))
0 commit comments