@@ -3269,8 +3269,14 @@ PHP_FUNCTION(pg_escape_string)
32693269
32703270 to = zend_string_safe_alloc (ZSTR_LEN (from ), 2 , 0 , 0 );
32713271 if (link ) {
3272+ int err ;
32723273 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+ }
32743280 } else
32753281 {
32763282 ZSTR_LEN (to ) = PQescapeString (ZSTR_VAL (to ), ZSTR_VAL (from ), ZSTR_LEN (from ));
@@ -3313,6 +3319,10 @@ PHP_FUNCTION(pg_escape_bytea)
33133319 } else {
33143320 to = (char * )PQescapeBytea ((unsigned char * )ZSTR_VAL (from ), ZSTR_LEN (from ), & to_len );
33153321 }
3322+ if (to == NULL ) {
3323+ zend_argument_value_error (ZEND_NUM_ARGS (), "Escape failure" );
3324+ RETURN_THROWS ();
3325+ }
33163326
33173327 RETVAL_STRINGL (to , to_len - 1 ); /* to_len includes additional '\0' */
33183328 PQfreemem (to );
@@ -4245,7 +4255,7 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string
42454255 char * escaped ;
42464256 smart_str querystr = {0 };
42474257 size_t new_len ;
4248- int i , num_rows ;
4258+ int i , num_rows , err ;
42494259 zval elem ;
42504260
42514261 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
42834293 "WHERE a.attnum > 0 AND c.relname = '" );
42844294 }
42854295 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+ }
42874304 if (new_len ) {
42884305 smart_str_appendl (& querystr , escaped , new_len );
42894306 }
42904307 efree (escaped );
42914308
42924309 smart_str_appends (& querystr , "' AND n.nspname = '" );
42934310 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+ }
42954319 if (new_len ) {
42964320 smart_str_appendl (& querystr , escaped , new_len );
42974321 }
@@ -4552,7 +4576,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
45524576{
45534577 zend_string * field = NULL ;
45544578 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 ;
45564580 php_pgsql_data_type data_type ;
45574581
45584582 ZEND_ASSERT (pg_link != NULL );
@@ -4804,8 +4828,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
48044828 /* PostgreSQL ignores \0 */
48054829 str = zend_string_alloc (Z_STRLEN_P (val ) * 2 , 0 );
48064830 /* 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+ }
48094838 zend_string_release_ex (str , false);
48104839 }
48114840 break ;
@@ -4828,7 +4857,14 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
48284857 }
48294858 PGSQL_CONV_CHECK_IGNORE ();
48304859 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+ }
48324868 }
48334869 break ;
48344870
@@ -5103,6 +5139,11 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
51035139 zend_string * tmp_zstr ;
51045140
51055141 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+ }
51065147 tmp_zstr = zend_string_init ((char * )tmp , to_len - 1 , false); /* PQescapeBytea's to_len includes additional '\0' */
51075148 PQfreemem (tmp );
51085149
@@ -5181,6 +5222,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
51815222 zend_hash_update (Z_ARRVAL_P (result ), field , & new_val );
51825223 } else {
51835224 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+ }
51845231 add_assoc_zval (result , escaped , & new_val );
51855232 PQfreemem (escaped );
51865233 }
@@ -5259,7 +5306,7 @@ static bool do_exec(smart_str *querystr, ExecStatusType expect, PGconn *pg_link,
52595306}
52605307/* }}} */
52615308
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 ) /* {{{ */
52635310{
52645311 /* schema.table should be "schema"."table" */
52655312 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
52695316 smart_str_appendl (querystr , ZSTR_VAL (table ), len );
52705317 } else {
52715318 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+ }
52725323 smart_str_appends (querystr , escaped );
52735324 PQfreemem (escaped );
52745325 }
@@ -5281,11 +5332,17 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z
52815332 smart_str_appendl (querystr , after_dot , len );
52825333 } else {
52835334 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+ }
52845339 smart_str_appendc (querystr , '.' );
52855340 smart_str_appends (querystr , escaped );
52865341 PQfreemem (escaped );
52875342 }
52885343 }
5344+
5345+ return SUCCESS ;
52895346}
52905347/* }}} */
52915348
@@ -5306,7 +5363,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
53065363 ZVAL_UNDEF (& converted );
53075364 if (zend_hash_num_elements (Z_ARRVAL_P (var_array )) == 0 ) {
53085365 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+ }
53105369 smart_str_appends (& querystr , " DEFAULT VALUES" );
53115370
53125371 goto no_values ;
@@ -5322,7 +5381,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
53225381 }
53235382
53245383 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+ }
53265387 smart_str_appends (& querystr , " (" );
53275388
53285389 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
53325393 }
53335394 if (opt & PGSQL_DML_ESCAPE ) {
53345395 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+ }
53355400 smart_str_appends (& querystr , tmp );
53365401 PQfreemem (tmp );
53375402 } else {
@@ -5343,15 +5408,19 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t
53435408 smart_str_appends (& querystr , ") VALUES (" );
53445409
53455410 /* 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 ) {
53475412 /* we can avoid the key_type check here, because we tested it in the other loop */
53485413 switch (Z_TYPE_P (val )) {
53495414 case IS_STRING :
53505415 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+ }
53555424 smart_str_appendc (& querystr , '\'' );
53565425 smart_str_appendl (& querystr , tmp , new_len );
53575426 smart_str_appendc (& querystr , '\'' );
@@ -5507,6 +5576,10 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
55075576 }
55085577 if (opt & PGSQL_DML_ESCAPE ) {
55095578 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+ }
55105583 smart_str_appends (querystr , tmp );
55115584 PQfreemem (tmp );
55125585 } else {
@@ -5522,8 +5595,14 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
55225595 switch (Z_TYPE_P (val )) {
55235596 case IS_STRING :
55245597 if (opt & PGSQL_DML_ESCAPE ) {
5598+ int error ;
55255599 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+ }
55275606 smart_str_appendc (querystr , '\'' );
55285607 smart_str_appendl (querystr , tmp , new_len );
55295608 smart_str_appendc (querystr , '\'' );
@@ -5591,7 +5670,9 @@ PHP_PGSQL_API zend_result php_pgsql_update(PGconn *pg_link, const zend_string *t
55915670 }
55925671
55935672 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+ }
55955676 smart_str_appends (& querystr , " SET " );
55965677
55975678 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
56945775 }
56955776
56965777 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+ }
56985781 smart_str_appends (& querystr , " WHERE " );
56995782
57005783 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
58345917 }
58355918
58365919 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+ }
58385923 smart_str_appends (& querystr , " WHERE " );
58395924
58405925 if (build_assignment_string (pg_link , & querystr , Z_ARRVAL_P (ids_array ), 1 , " AND " , sizeof (" AND " )- 1 , opt ))
0 commit comments