Skip to content

Commit 9c6fe6b

Browse files
committed
Fix GH-18148: pg_copy_from() wrong \n offset check.
Close GH-18149
1 parent e28f78a commit 9c6fe6b

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ PHP NEWS
7575
- PDO:
7676
. Fix memory leak when destroying PDORow. (nielsdos)
7777

78+
- PGSQL:
79+
. Fixed bug GH-18148 (pg_copy_from() regression with explicit \n terminator
80+
due to wrong offset check). (David Carlier)
81+
7882
- Standard:
7983
. Fix memory leaks in array_any() / array_all(). (nielsdos)
8084

ext/pgsql/pgsql.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -3451,11 +3451,13 @@ PHP_FUNCTION(pg_copy_from)
34513451
if (UNEXPECTED(!tmp)) {
34523452
return;
34533453
}
3454-
zend_string *zquery = zend_string_alloc(ZSTR_LEN(tmp) + 1, false);
3454+
// we give allocation room for a potential command line `\n` terminator addition
3455+
zend_string *zquery = zend_string_alloc(ZSTR_LEN(tmp) + 2, false);
34553456
memcpy(ZSTR_VAL(zquery), ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 1);
34563457
ZSTR_LEN(zquery) = ZSTR_LEN(tmp);
3457-
if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(zquery)[ZSTR_LEN(tmp)] != '\n') {
3458+
if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(zquery)[ZSTR_LEN(tmp) - 1] != '\n') {
34583459
ZSTR_VAL(zquery)[ZSTR_LEN(tmp)] = '\n';
3460+
ZSTR_VAL(zquery)[ZSTR_LEN(tmp) + 1] = '\0';
34593461
ZSTR_LEN(zquery) ++;
34603462
}
34613463
if (PQputCopyData(pgsql, ZSTR_VAL(zquery), ZSTR_LEN(zquery)) != 1) {

ext/pgsql/tests/gh18148.phpt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Fix GH-18148 pg_copy_from() command position offset when giving explicit \n terminator
3+
--EXTENSIONS--
4+
pgsql
5+
--SKIPIF--
6+
<?php
7+
include("inc/skipif.inc");
8+
?>
9+
--FILE--
10+
<?php
11+
12+
include "inc/config.inc";
13+
$table_name = "gh18148";
14+
$db = pg_connect($conn_str);
15+
pg_query($db, "CREATE TABLE {$table_name} (a integer, b text)");
16+
var_dump(pg_copy_from( $db, $table_name, [ "1\tone\n" ] ));
17+
--CLEAN--
18+
<?php
19+
include('inc/config.inc');
20+
$db = pg_connect($conn_str);
21+
pg_query($db, "DROP TABLE IF EXISTS gh18148 cascade");
22+
?>
23+
--EXPECT--
24+
bool(true)

0 commit comments

Comments
 (0)