Skip to content

Commit 65ae1ad

Browse files
lacatoiredevnexen
authored andcommitted
ext/pgsql: stop advertising PGSQL_DML_ASYNC where it is refused
pg_update() and pg_delete() list PGSQL_DML_ASYNC among the valid flags in the error they raise, although their masks reject it and their helpers assert it is never set. Conversely pg_insert() and pg_update() accept the whole PGSQL_CONV_OPTS set but only named PGSQL_CONV_FORCE_NULL, so PGSQL_CONV_IGNORE_DEFAULT and PGSQL_CONV_IGNORE_NOT_NULL are added. While there, widen php_pgsql_delete()'s assert to PGSQL_DML_NO_CONV, which pg_delete() accepts and the helper itself consults. Close GH-23480
1 parent 0a40e06 commit 65ae1ad

3 files changed

Lines changed: 76 additions & 6 deletions

File tree

‎NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ PHP NEWS
1616
. Added Pdo\Pgsql::ATTR_CHUNK_SIZE to fetch a result set in chunks of the
1717
given number of rows. (KentarouTakeda)
1818

19+
- PGSQL:
20+
. Fixed the pg_insert(), pg_update() and pg_delete() flag error messages,
21+
which did not name the set of flags actually accepted. (lacatoire)
22+
1923
- Phar:
2024
. Fixed bug GH-23418 (Use-after-free when looking up mounted directories).
2125
(Weilin Du)

‎ext/pgsql/pgsql.c‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,8 +5740,9 @@ PHP_FUNCTION(pg_insert)
57405740
}
57415741

57425742
if (option & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING|PGSQL_DML_ESCAPE)) {
5743-
zend_argument_value_error(4, "must be a valid bit mask of PGSQL_CONV_FORCE_NULL, PGSQL_DML_NO_CONV, "
5744-
"PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, PGSQL_DML_ASYNC, and PGSQL_DML_STRING");
5743+
zend_argument_value_error(4, "must be a valid bit mask of PGSQL_CONV_IGNORE_DEFAULT, PGSQL_CONV_FORCE_NULL, "
5744+
"PGSQL_CONV_IGNORE_NOT_NULL, PGSQL_DML_NO_CONV, PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, PGSQL_DML_ASYNC, "
5745+
"and PGSQL_DML_STRING");
57455746
RETURN_THROWS();
57465747
}
57475748

@@ -5972,8 +5973,9 @@ PHP_FUNCTION(pg_update)
59725973
}
59735974

59745975
if (option & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING|PGSQL_DML_ESCAPE)) {
5975-
zend_argument_value_error(5, "must be a valid bit mask of PGSQL_CONV_FORCE_NULL, PGSQL_DML_NO_CONV, "
5976-
"PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, PGSQL_DML_ASYNC, and PGSQL_DML_STRING");
5976+
zend_argument_value_error(5, "must be a valid bit mask of PGSQL_CONV_IGNORE_DEFAULT, PGSQL_CONV_FORCE_NULL, "
5977+
"PGSQL_CONV_IGNORE_NOT_NULL, PGSQL_DML_NO_CONV, PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, "
5978+
"and PGSQL_DML_STRING");
59775979
RETURN_THROWS();
59785980
}
59795981

@@ -6004,7 +6006,7 @@ PHP_PGSQL_API zend_result php_pgsql_delete(PGconn *pg_link, const zend_string *t
60046006
ZEND_ASSERT(pg_link != NULL);
60056007
ZEND_ASSERT(table != NULL);
60066008
ZEND_ASSERT(Z_TYPE_P(ids_array) == IS_ARRAY);
6007-
ZEND_ASSERT(!(opt & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_EXEC|PGSQL_DML_STRING|PGSQL_DML_ESCAPE)));
6009+
ZEND_ASSERT(!(opt & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING|PGSQL_DML_ESCAPE)));
60086010

60096011
if (zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
60106012
return FAILURE;
@@ -6074,7 +6076,7 @@ PHP_FUNCTION(pg_delete)
60746076

60756077
if (option & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING|PGSQL_DML_ESCAPE)) {
60766078
zend_argument_value_error(4, "must be a valid bit mask of PGSQL_CONV_FORCE_NULL, PGSQL_DML_NO_CONV, "
6077-
"PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, PGSQL_DML_ASYNC, and PGSQL_DML_STRING");
6079+
"PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, and PGSQL_DML_STRING");
60786080
RETURN_THROWS();
60796081
}
60806082

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
--TEST--
2+
pg_insert()/pg_update()/pg_delete(): the flags refused are the flags the message names
3+
--EXTENSIONS--
4+
pgsql
5+
--SKIPIF--
6+
<?php include("inc/skipif.inc"); ?>
7+
--FILE--
8+
<?php
9+
10+
include('inc/config.inc');
11+
$table_name = 'table_pg_dml_option_flags';
12+
13+
$conn = pg_connect($conn_str);
14+
pg_query($conn, "CREATE TABLE {$table_name} (id INT, id2 INT)");
15+
16+
/* PGSQL_DML_ASYNC is not part of the accepted mask of these two */
17+
try {
18+
pg_update($conn, $table_name, ['id2' => 2], ['id' => 1], PGSQL_DML_ASYNC | PGSQL_DML_STRING);
19+
} catch (ValueError $e) {
20+
echo $e->getMessage(), "\n";
21+
}
22+
23+
try {
24+
pg_delete($conn, $table_name, ['id' => 1], PGSQL_DML_ASYNC | PGSQL_DML_STRING);
25+
} catch (ValueError $e) {
26+
echo $e->getMessage(), "\n";
27+
}
28+
29+
/* 1 << 13 is not one of the flags at all */
30+
try {
31+
pg_insert($conn, $table_name, ['id' => 1, 'id2' => 1], 1 << 13);
32+
} catch (ValueError $e) {
33+
echo $e->getMessage(), "\n";
34+
}
35+
36+
/* but PGSQL_DML_ASYNC is accepted by pg_insert() and pg_select() */
37+
var_dump(is_string(pg_insert($conn, $table_name, ['id' => 1, 'id2' => 1], PGSQL_DML_ASYNC | PGSQL_DML_STRING)));
38+
var_dump(is_string(pg_select($conn, $table_name, ['id' => 1], PGSQL_DML_ASYNC | PGSQL_DML_STRING)));
39+
40+
/* every PGSQL_CONV_* flag the messages name is genuinely accepted */
41+
var_dump(is_string(pg_insert($conn, $table_name, ['id' => 1, 'id2' => 1], PGSQL_CONV_IGNORE_DEFAULT | PGSQL_DML_STRING)));
42+
var_dump(is_string(pg_update($conn, $table_name, ['id2' => 2], ['id' => 1], PGSQL_CONV_IGNORE_NOT_NULL | PGSQL_DML_STRING)));
43+
44+
/* PGSQL_DML_NO_CONV is accepted by pg_delete() and reaches its helper */
45+
var_dump(is_string(pg_delete($conn, $table_name, ['id' => 1], PGSQL_DML_NO_CONV | PGSQL_DML_STRING)));
46+
47+
?>
48+
--CLEAN--
49+
<?php
50+
include('inc/config.inc');
51+
$table_name = 'table_pg_dml_option_flags';
52+
53+
$conn = pg_connect($conn_str);
54+
pg_query($conn, "DROP TABLE IF EXISTS {$table_name}");
55+
?>
56+
--EXPECT--
57+
pg_update(): Argument #5 ($flags) must be a valid bit mask of PGSQL_CONV_IGNORE_DEFAULT, PGSQL_CONV_FORCE_NULL, PGSQL_CONV_IGNORE_NOT_NULL, PGSQL_DML_NO_CONV, PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, and PGSQL_DML_STRING
58+
pg_delete(): Argument #4 ($flags) must be a valid bit mask of PGSQL_CONV_FORCE_NULL, PGSQL_DML_NO_CONV, PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, and PGSQL_DML_STRING
59+
pg_insert(): Argument #4 ($flags) must be a valid bit mask of PGSQL_CONV_IGNORE_DEFAULT, PGSQL_CONV_FORCE_NULL, PGSQL_CONV_IGNORE_NOT_NULL, PGSQL_DML_NO_CONV, PGSQL_DML_ESCAPE, PGSQL_DML_EXEC, PGSQL_DML_ASYNC, and PGSQL_DML_STRING
60+
bool(true)
61+
bool(true)
62+
bool(true)
63+
bool(true)
64+
bool(true)

0 commit comments

Comments
 (0)