diff --git a/NEWS b/NEWS index 4fde6a2b10d..40a6e52dff8 100644 --- a/NEWS +++ b/NEWS @@ -63,6 +63,9 @@ PHP NEWS . Added pg_close_stmt to close a prepared statement while allowing its name to be reused. (David Carlier) . Added Iterable support for pgsql_copy_from. (David Carlier) + . pg_connect checks if connection_string contains any null byte, + pg_close_stmt check if the statement contains any null byte. + (David Carlier) - POSIX: . Added POSIX_SC_OPEN_MAX constant to get the number of file descriptors diff --git a/UPGRADING b/UPGRADING index 7e50c0e7a93..805d2f62440 100644 --- a/UPGRADING +++ b/UPGRADING @@ -125,6 +125,10 @@ PHP 8.5 UPGRADE NOTES - PGSQL: . pg_copy_from also supports inputs as Iterable. + . pg_connect checks if the connection_string argument contains + any null byte. + . pg_close_stmt checks if the statement_name argument contains + any null byte. - POSIX: . posix_ttyname sets last_error to EBADF when encountering diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 4854fdbfd1a..b1a1dfb49a7 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -665,7 +665,7 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) PGresult *pg_result; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(connstring, connstring_len) + Z_PARAM_PATH(connstring, connstring_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(connect_type) ZEND_PARSE_PARAMETERS_END(); @@ -1123,7 +1123,7 @@ PHP_FUNCTION(pg_query) zval *pgsql_link = NULL; char *query; size_t query_len; - int leftover = 0; + bool leftover = false; pgsql_link_handle *link; PGconn *pgsql; PGresult *pgsql_result; @@ -1157,7 +1157,7 @@ PHP_FUNCTION(pg_query) } while ((pgsql_result = PQgetResult(pgsql))) { PQclear(pgsql_result); - leftover = 1; + leftover = true; } if (leftover) { php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); @@ -1220,7 +1220,7 @@ PHP_FUNCTION(pg_query_params) zval *pv_param_arr, *tmp; char *query; size_t query_len; - int leftover = 0; + bool leftover = false; int num_params = 0; char **params = NULL; pgsql_link_handle *link; @@ -1259,7 +1259,7 @@ PHP_FUNCTION(pg_query_params) } while ((pgsql_result = PQgetResult(pgsql))) { PQclear(pgsql_result); - leftover = 1; + leftover = true; } if (leftover) { php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); @@ -1335,7 +1335,7 @@ PHP_FUNCTION(pg_prepare) zval *pgsql_link = NULL; char *query, *stmtname; size_t query_len, stmtname_len; - int leftover = 0; + bool leftover = false; PGconn *pgsql; pgsql_link_handle *link; PGresult *pgsql_result; @@ -1372,7 +1372,7 @@ PHP_FUNCTION(pg_prepare) } while ((pgsql_result = PQgetResult(pgsql))) { PQclear(pgsql_result); - leftover = 1; + leftover = true; } if (leftover) { php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); @@ -1422,7 +1422,7 @@ PHP_FUNCTION(pg_execute) zval *pv_param_arr, *tmp; char *stmtname; size_t stmtname_len; - int leftover = 0; + bool leftover = false; int num_params = 0; char **params = NULL; PGconn *pgsql; @@ -1461,7 +1461,7 @@ PHP_FUNCTION(pg_execute) } while ((pgsql_result = PQgetResult(pgsql))) { PQclear(pgsql_result); - leftover = 1; + leftover = true; } if (leftover) { php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); @@ -1690,7 +1690,7 @@ PHP_FUNCTION(pg_field_table) zval *result; pgsql_result_handle *pg_result; zend_long fnum = -1; - bool return_oid = 0; + bool return_oid = false; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_OBJECT_OF_CLASS(result, pgsql_result_ce) @@ -2770,14 +2770,14 @@ PHP_FUNCTION(pg_lo_write) zval *pgsql_id; zend_string *str; zend_long z_len; - bool z_len_is_null = 1; + bool z_len_is_null = true; size_t nbytes; size_t len; pgLofp *pgsql; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_OBJECT_OF_CLASS(pgsql_id, pgsql_lob_ce) - Z_PARAM_STR(str) + Z_PARAM_PATH_STR(str) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(z_len, z_len_is_null) ZEND_PARSE_PARAMETERS_END(); @@ -3346,7 +3346,7 @@ PHP_FUNCTION(pg_copy_to) switch (status) { case PGRES_COPY_OUT: if (pgsql_result) { - int copydone = 0; + bool copydone = false; PQclear(pgsql_result); array_init(return_value); @@ -3355,7 +3355,7 @@ PHP_FUNCTION(pg_copy_to) int ret = PQgetCopyData(pgsql, &csv, 0); switch (ret) { case -1: - copydone = 1; + copydone = true; break; case 0: case -2: @@ -4654,7 +4654,7 @@ PHP_FUNCTION(pg_meta_data) zval *pgsql_link; pgsql_link_handle *link; zend_string *table_name; - bool extended=0; + bool extended = false; PGconn *pgsql; ZEND_PARSE_PARAMETERS_START(2, 3) @@ -4832,7 +4832,7 @@ static zend_string *php_pgsql_add_quotes(zend_string *src) /* if new_value is string "NULL" and field has default value, remove element to use default value */ \ if (!(opt & PGSQL_CONV_IGNORE_DEFAULT) && Z_TYPE_P(has_default) == IS_TRUE) { \ zval_ptr_dtor(&new_val); \ - skip_field = 1; \ + skip_field = true; \ } \ /* raise error if it's not null and cannot be ignored */ \ else if (!(opt & PGSQL_CONV_IGNORE_NOT_NULL) && Z_TYPE_P(not_null) == IS_TRUE) { \ @@ -4848,7 +4848,8 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * { zend_string *field = NULL; zval meta, *def, *type, *not_null, *has_default, *is_enum, *val, new_val; - int err = 0, skip_field; + int err = 0; + bool skip_field; php_pgsql_data_type data_type; ZEND_ASSERT(pg_link != NULL); @@ -4867,7 +4868,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(values), field, val) { - skip_field = 0; + skip_field = false; ZVAL_DEREF(val); ZVAL_NULL(&new_val); @@ -6324,11 +6325,11 @@ PHP_FUNCTION(pg_close_stmt) ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_OBJECT_OF_CLASS(pgsql_link, pgsql_link_ce) - Z_PARAM_STR(stmt) + Z_PARAM_PATH_STR(stmt) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(stmt) == 0) { - zend_argument_value_error(2, "cannot be empty"); + zend_argument_must_not_be_empty_error(2); RETURN_THROWS(); } diff --git a/ext/pgsql/tests/05large_object.phpt b/ext/pgsql/tests/05large_object.phpt index a785b76a572..957f2dffa8e 100644 --- a/ext/pgsql/tests/05large_object.phpt +++ b/ext/pgsql/tests/05large_object.phpt @@ -17,6 +17,11 @@ $oid = pg_lo_create ($db); if (!$oid) echo ("pg_lo_create() error\n"); $handle = pg_lo_open ($db, $oid, "w"); if (!$handle) echo ("pg_lo_open() error\n"); +try { + pg_lo_write ($handle, "large\0object data"); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} pg_lo_write ($handle, "large object data"); pg_lo_close ($handle); pg_exec ($db, "COMMIT"); @@ -105,6 +110,7 @@ echo "OK"; ?> --EXPECTF-- create/write/close LO +pg_lo_write(): Argument #2 ($data) must not contain any null bytes open/read/tell/seek/close LO string(5) "large" int(5) diff --git a/ext/pgsql/tests/pg_close_stmt.phpt b/ext/pgsql/tests/pg_close_stmt.phpt index e93108c1e7a..206ffeb0eea 100644 --- a/ext/pgsql/tests/pg_close_stmt.phpt +++ b/ext/pgsql/tests/pg_close_stmt.phpt @@ -18,6 +18,11 @@ $db = pg_connect($conn_str); $res = pg_prepare($db, 'test', $query); $res = pg_execute($db, 'test', $params_null); +try { + pg_close_stmt($db, ''); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} $res = pg_close_stmt($db, 'test'); var_dump($res !== false); var_dump(pg_result_status($res) === PGSQL_COMMAND_OK); @@ -29,5 +34,6 @@ pg_close($db); ?> --EXPECT-- +pg_close_stmt(): Argument #2 ($statement_name) must not be empty bool(true) bool(true)