@@ -273,6 +273,8 @@ static void pgsql_lob_free_obj(zend_object *obj)
273273
274274/* Compatibility definitions */
275275
276+ static inline zend_result build_tablename (smart_str * querystr , PGconn * pg_link , const zend_string * table );
277+
276278static zend_string * _php_pgsql_trim_message (const char * message )
277279{
278280 size_t i = strlen (message );
@@ -3348,8 +3350,7 @@ PHP_FUNCTION(pg_copy_to)
33483350 zend_string * table_name ;
33493351 zend_string * pg_delimiter = NULL ;
33503352 char * pg_null_as = "\\\\N" ;
3351- size_t pg_null_as_len = 0 ;
3352- char * query ;
3353+ size_t pg_null_as_len = sizeof ("\\\\N" ) - 1 ;
33533354 PGconn * pgsql ;
33543355 PGresult * pgsql_result ;
33553356 ExecStatusType status ;
@@ -3373,14 +3374,36 @@ PHP_FUNCTION(pg_copy_to)
33733374 zend_argument_value_error (3 , "must be one character" );
33743375 RETURN_THROWS ();
33753376 }
3377+ smart_str querystr = {0 };
3378+ smart_str_appends (& querystr , "COPY " );
3379+ if (ZSTR_LEN (table_name ) > 0 && ZSTR_VAL (table_name )[0 ] == '(' ) {
3380+ smart_str_appendc (& querystr , '(' );
3381+ smart_str_append (& querystr , table_name );
3382+ smart_str_appendc (& querystr , ')' );
3383+ } else if (build_tablename (& querystr , pgsql , table_name ) == FAILURE ) {
3384+ smart_str_free (& querystr );
3385+ RETURN_FALSE ;
3386+ }
33763387
3377- spprintf (& query , 0 , "COPY %s TO STDOUT DELIMITER E'%c' NULL AS E'%s'" , ZSTR_VAL (table_name ), * ZSTR_VAL (pg_delimiter ), pg_null_as );
3388+ char * escaped_delimiter = PQescapeLiteral (pgsql , ZSTR_VAL (pg_delimiter ), 1 );
3389+ char * escaped_null_as = PQescapeLiteral (pgsql , pg_null_as , pg_null_as_len );
3390+ if (!escaped_delimiter || !escaped_null_as ) {
3391+ php_error_docref (NULL , E_WARNING , "Failed to escape COPY parameters" );
3392+ if (escaped_delimiter ) PQfreemem (escaped_delimiter );
3393+ if (escaped_null_as ) PQfreemem (escaped_null_as );
3394+ smart_str_free (& querystr );
3395+ RETURN_FALSE ;
3396+ }
3397+ smart_str_append_printf (& querystr , " TO STDOUT DELIMITER %s NULL AS %s" , escaped_delimiter , escaped_null_as );
3398+ smart_str_0 (& querystr );
3399+ PQfreemem (escaped_delimiter );
3400+ PQfreemem (escaped_null_as );
33783401
33793402 while ((pgsql_result = PQgetResult (pgsql ))) {
33803403 PQclear (pgsql_result );
33813404 }
3382- pgsql_result = PQexec (pgsql , query );
3383- efree ( query );
3405+ pgsql_result = PQexec (pgsql , ZSTR_VAL ( querystr . s ) );
3406+ smart_str_free ( & querystr );
33843407
33853408 if (pgsql_result ) {
33863409 status = PQresultStatus (pgsql_result );
@@ -3463,8 +3486,7 @@ PHP_FUNCTION(pg_copy_from)
34633486 zend_string * table_name ;
34643487 zend_string * pg_delimiter = NULL ;
34653488 char * pg_null_as = "\\\\N" ;
3466- size_t pg_null_as_len ;
3467- char * query ;
3489+ size_t pg_null_as_len = sizeof ("\\\\N" ) - 1 ;
34683490 PGconn * pgsql ;
34693491 PGresult * pgsql_result ;
34703492 ExecStatusType status ;
@@ -3488,14 +3510,33 @@ PHP_FUNCTION(pg_copy_from)
34883510 zend_argument_value_error (4 , "must be one character" );
34893511 RETURN_THROWS ();
34903512 }
3513+ smart_str querystr = {0 };
3514+ smart_str_appends (& querystr , "COPY " );
3515+ if (build_tablename (& querystr , pgsql , table_name ) == FAILURE ) {
3516+ smart_str_free (& querystr );
3517+ RETURN_FALSE ;
3518+ }
3519+
3520+ char * escaped_delimiter = PQescapeLiteral (pgsql , ZSTR_VAL (pg_delimiter ), 1 );
3521+ char * escaped_null_as = PQescapeLiteral (pgsql , pg_null_as , pg_null_as_len );
3522+ if (!escaped_delimiter || !escaped_null_as ) {
3523+ php_error_docref (NULL , E_WARNING , "Failed to escape COPY parameters" );
3524+ if (escaped_delimiter ) PQfreemem (escaped_delimiter );
3525+ if (escaped_null_as ) PQfreemem (escaped_null_as );
3526+ smart_str_free (& querystr );
3527+ RETURN_FALSE ;
3528+ }
3529+ smart_str_append_printf (& querystr , " FROM STDIN DELIMITER %s NULL AS %s" , escaped_delimiter , escaped_null_as );
3530+ smart_str_0 (& querystr );
3531+ PQfreemem (escaped_delimiter );
3532+ PQfreemem (escaped_null_as );
34913533
3492- spprintf (& query , 0 , "COPY %s FROM STDIN DELIMITER E'%c' NULL AS E'%s'" , ZSTR_VAL (table_name ), * ZSTR_VAL (pg_delimiter ), pg_null_as );
34933534 while ((pgsql_result = PQgetResult (pgsql ))) {
34943535 PQclear (pgsql_result );
34953536 }
3496- pgsql_result = PQexec (pgsql , query );
3537+ pgsql_result = PQexec (pgsql , ZSTR_VAL ( querystr . s ) );
34973538
3498- efree ( query );
3539+ smart_str_free ( & querystr );
34993540
35003541 if (pgsql_result ) {
35013542 status = PQresultStatus (pgsql_result );
0 commit comments