Skip to content

Commit d3f361c

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3: Add NEWS entries Fix GHSA-vc5h-9ppw-p5f3: phar circular symlink crash Fix SQL injection in ext-pgsql via E'...' backslash breakout libgd patch for CVE-2026-9672
2 parents 1b091dc + 4169853 commit d3f361c

15 files changed

Lines changed: 165 additions & 33 deletions

NEWS

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3-
?? ??? ????, PHP 8.4.24
3+
?? ??? ????, PHP 8.4.25
44

55
- Date:
66
. Fixed leak on double DatePeriod::__construct() call. (ilutov)
@@ -29,6 +29,10 @@ PHP NEWS
2929

3030
30 Jul 2026, PHP 8.4.24
3131

32+
- BCMath:
33+
. Fixed GHSA-x692-q9x7-8c3f (Out-of-bounds write in bccomp()).
34+
(CVE-2026-17544) (Recep Asan)
35+
3236
- Calendar:
3337
. Fixed bug GH-22602 (gregoriantojd() and juliantojd() integer overflow with
3438
INT_MAX year). (arshidkv12)
@@ -53,6 +57,9 @@ PHP NEWS
5357
. Fixed bug GH-11020 (exif_read_data() emits a spurious "Illegal IFD size"
5458
warning when an IFD is not followed by a next-IFD offset). (Eyüp Can Akman)
5559

60+
- GD:
61+
. Upgrade libgd. (CVE-2026-9672) (Pierre Joye)
62+
5663
- Hash:
5764
. Fixed bug GH-18173 (ext/hash relies on implementation-defined malloc
5865
alignment). (iliaal)
@@ -83,12 +90,18 @@ PHP NEWS
8390
. Fixed bug GH-22665 (Out-of-bounds write when the ODBC driver reports a
8491
diagnostic message length beyond the error buffer). (iliaal)
8592

93+
- PGSQL:
94+
. Fixed GHSA-7qpv-r5mr-78m4 (SQL injection via E'...' backslash breakout).
95+
(CVE-2026-17543) (ilutov)
96+
8697
- Phar:
8798
. Fixed inconsistent handling of the magic ".phar" directory. Paths such as
8899
"/.phar" remain protected, while non-magic paths that merely start with
89100
".phar" are handled consistently across file and directory creation,
90101
copying, ArrayAccess, stream lookup, directory iteration and extraction.
91102
(Weilin Du)
103+
. Fixed GHSA-vc5h-9ppw-p5f3 (Crash via recursive symlinks). (CVE-2026-7260)
104+
(Jakub Zelenka)
92105

93106
- PHPDBG:
94107
. Fixed bug GH-17387 (Trivial crash in phpdbg lexer). (iliaal)

ext/gd/libgd/gd_gif_in.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ LWZReadByte_(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, i
452452
sd->table[1][i] = i;
453453
}
454454
for (; i < (1<<MAX_LWZ_BITS); ++i)
455-
sd->table[0][i] = sd->table[1][0] = 0;
455+
sd->table[0][i] = sd->table[1][i] = 0;
456456

457457
sd->sp = sd->stack;
458458

@@ -496,6 +496,8 @@ LWZReadByte_(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, i
496496

497497
if (count != 0)
498498
return -2;
499+
500+
return -2;
499501
}
500502

501503
incode = code;
@@ -562,7 +564,7 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)
562564
int v;
563565
int xpos = 0, ypos = 0, pass = 0;
564566
int i;
565-
LZW_STATIC_DATA sd;
567+
LZW_STATIC_DATA sd = {0};
566568

567569

568570
/*

ext/pgsql/pgsql.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4841,7 +4841,7 @@ static int php_pgsql_convert_match(const zend_string *str, zend_string *regex)
48414841
*/
48424842
static zend_string *php_pgsql_add_quotes(zend_string *src)
48434843
{
4844-
return zend_string_concat3("E'", strlen("E'"), ZSTR_VAL(src), ZSTR_LEN(src), "'", strlen("'"));
4844+
return zend_string_concat3("'", strlen("'"), ZSTR_VAL(src), ZSTR_LEN(src), "'", strlen("'"));
48454845
}
48464846
/* }}} */
48474847

@@ -5112,7 +5112,6 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
51125112
zend_string *str;
51135113
/* PostgreSQL ignores \0 */
51145114
str = zend_string_alloc(Z_STRLEN_P(val) * 2, 0);
5115-
/* better to use PGSQLescapeLiteral since PGescapeStringConn does not handle special \ */
51165115
ZSTR_LEN(str) = PQescapeStringConn(pg_link, ZSTR_VAL(str),
51175116
Z_STRVAL_P(val), Z_STRLEN_P(val), &escape_err);
51185117
if (escape_err) {

ext/pgsql/tests/10pg_convert_9.phpt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ $converted = pg_convert($db, $table_name, $fields);
2424

2525
var_dump($converted);
2626

27+
var_dump(pg_convert($db, $table_name, ['str' => "\\' OR 1=1"]));
28+
2729
/* Invalid values */
2830
try {
2931
$converted = pg_convert($db, $table_name, [5 => 'AAA']);
@@ -51,6 +53,10 @@ try {
5153
} catch (\TypeError $e) {
5254
echo $e->getMessage(), \PHP_EOL;
5355
}
56+
57+
/* standard_conforming_strings = 1 */
58+
pg_query($db, "SET standard_conforming_strings = 1");
59+
var_dump(pg_convert($db, $table_name, ['str' => "\\' OR 1=1"]));
5460
?>
5561
--CLEAN--
5662
<?php
@@ -65,12 +71,20 @@ array(3) {
6571
[""num""]=>
6672
string(4) "1234"
6773
[""str""]=>
68-
string(6) "E'AAA'"
74+
string(5) "'AAA'"
6975
[""bin""]=>
70-
string(12) "E'\\x424242'"
76+
string(11) "'\\x424242'"
77+
}
78+
array(1) {
79+
[""str""]=>
80+
string(13) "'\\'' OR 1=1'"
7181
}
7282
Array of values must be an associative array with string keys
7383
Array of values must be an associative array with string keys
7484
Values must be of type string|int|float|bool|null, array given
7585
Values must be of type string|int|float|bool|null, stdClass given
7686
Values must be of type string|int|float|bool|null, PgSql\Connection given
87+
array(1) {
88+
[""str""]=>
89+
string(12) "'\'' OR 1=1'"
90+
}

ext/pgsql/tests/10pg_convert_json_array.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ pg_query($db, "DROP TABLE IF EXISTS {$table_name_92}");
4242
--EXPECT--
4343
array(2) {
4444
[""textary""]=>
45-
string(51) "E'{"meeting", "lunch", "training", "presentation"}'"
45+
string(50) "'{"meeting", "lunch", "training", "presentation"}'"
4646
[""jsn""]=>
47-
string(22) "E'{"f1":1,"f2":"foo"}'"
47+
string(21) "'{"f1":1,"f2":"foo"}'"
4848
}
4949
OK

ext/pgsql/tests/12pg_insert_9.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ $db = pg_connect($conn_str);
6565
pg_query($db, "DROP TABLE IF EXISTS {$table_name}");
6666
?>
6767
--EXPECTF--
68-
INSERT INTO "table_12pg_insert_9" ("num","str","bin") VALUES (1234,E'AAA',E'\\x424242');
68+
INSERT INTO "table_12pg_insert_9" ("num","str","bin") VALUES (1234,'AAA','\\x424242');
6969
INSERT INTO "table_12pg_insert_9" ("num","str","bin") VALUES ('1234','AAA','BBB');
7070
object(PgSql\Result)#%d (0) {
7171
}

ext/pgsql/tests/14pg_update_9.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ $db = pg_connect($conn_str);
3939
pg_query($db, "DROP TABLE IF EXISTS {$table_name}");
4040
?>
4141
--EXPECT--
42-
UPDATE "table_14pg_update_9" SET "num"=1234,"str"=E'ABC',"bin"=E'\\x58595a' WHERE "num"=1234;
42+
UPDATE "table_14pg_update_9" SET "num"=1234,"str"='ABC',"bin"='\\x58595a' WHERE "num"=1234;
4343
UPDATE "table_14pg_update_9" SET "num"='1234',"str"='ABC',"bin"='XYZ' WHERE "num"='1234';
4444
Ok
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--TEST--
2+
GHSA-7qpv-r5mr-78m4: SQL injection via E'...' backslash breakout
3+
--CREDITS--
4+
expatch.llc
5+
--EXTENSIONS--
6+
pgsql
7+
--SKIPIF--
8+
<?php include("inc/skipif.inc"); ?>
9+
--FILE--
10+
<?php
11+
include 'inc/config.inc';
12+
13+
$db = pg_connect($conn_str);
14+
15+
pg_query($db, "SET standard_conforming_strings = 1");
16+
17+
pg_query($db, "DROP TABLE IF EXISTS ghsa_7qpv_r5mr_78m4");
18+
pg_query($db, "CREATE TABLE ghsa_7qpv_r5mr_78m4 (id serial primary key, name text, admin boolean)");
19+
pg_query($db, "INSERT INTO ghsa_7qpv_r5mr_78m4 (name, admin) VALUES ('alice', false), ('bob', false)");
20+
21+
$params = ['name' => "zzz' OR 1=1 --"];
22+
echo pg_select($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_STRING) . "\n";
23+
printf("returned: %d\n\n", count(pg_select($db, 'ghsa_7qpv_r5mr_78m4', $params)));
24+
25+
$params = ['name' => "zzz\\' OR 1=1 --"];
26+
echo pg_select($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_STRING) . "\n";
27+
printf("returned: %d\n\n", count(pg_select($db, 'ghsa_7qpv_r5mr_78m4', $params)));
28+
29+
$params = ['name' => "john\\', true) --", 'admin' => 'false'];
30+
echo pg_insert($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_STRING) . "\n";
31+
pg_insert($db, 'ghsa_7qpv_r5mr_78m4', $params);
32+
var_dump(pg_select($db, 'ghsa_7qpv_r5mr_78m4', ['id' => 3])[0]['admin']);
33+
echo "\n";
34+
35+
$params = ['name' => "jake\\', true) --", 'admin' => 'f'];
36+
echo pg_insert($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_ESCAPE|PGSQL_DML_STRING) . "\n";
37+
pg_insert($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_EXEC|PGSQL_DML_ESCAPE);
38+
var_dump(pg_select($db, 'ghsa_7qpv_r5mr_78m4', ['id' => 4])[0]['admin']);
39+
40+
?>
41+
--EXPECT--
42+
SELECT * FROM "ghsa_7qpv_r5mr_78m4" WHERE "name"='zzz'' OR 1=1 --';
43+
returned: 0
44+
45+
SELECT * FROM "ghsa_7qpv_r5mr_78m4" WHERE "name"='zzz\'' OR 1=1 --';
46+
returned: 0
47+
48+
INSERT INTO "ghsa_7qpv_r5mr_78m4" ("name","admin") VALUES ('john\'', true) --','f');
49+
string(1) "f"
50+
51+
INSERT INTO "ghsa_7qpv_r5mr_78m4" ("name","admin") VALUES ('jake\'', true) --','f');
52+
string(1) "f"
53+
--CLEAN--
54+
<?php
55+
include('inc/config.inc');
56+
$db = pg_connect($conn_str);
57+
pg_query($db, "DROP TABLE IF EXISTS ghsa_7qpv_r5mr_78m4");
58+
?>

ext/pgsql/tests/bug64609.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@ var_dump($converted);
3030
--EXPECT--
3131
array(1) {
3232
[""a""]=>
33-
string(5) "E'ok'"
33+
string(4) "'ok'"
3434
}

ext/pgsql/tests/bug68638.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ $table='test_68638';
4141
pg_query($conn, "DROP TABLE IF EXISTS $table");
4242
?>
4343
--EXPECT--
44-
string(52) "UPDATE "test_68638" SET "value"=E'inf' WHERE "id"=1;"
44+
string(51) "UPDATE "test_68638" SET "value"='inf' WHERE "id"=1;"
4545
array(2) {
4646
["id"]=>
4747
string(1) "1"

0 commit comments

Comments
 (0)