StreamPollHandle took the descriptor through the select cast. On a TLS
stream that cast reads: it moves what OpenSSL holds decrypted into the
stream buffer so that stream_select() can report it. Adding a watcher to
an Io\Poll\Context therefore read from the stream, filled the buffer of a
stream set unbuffered with stream_set_read_buffer() and changed
unread_bytes. That is not how the poll API should behave. Adding a handle
is a registration and must leave the stream as it found it, and the data
that moved was not reported by the watcher anyway, as bytes held by the
stream layer are not readiness of the descriptor.
A new cast PHP_STREAM_AS_FD_FOR_POLL returns the descriptor and nothing
else. The socket, TLS, plain and pgsql wrappers answer it, a userspace
wrapper sees it as STREAM_CAST_FOR_SELECT and the stream it returns is
cast the same way, and a filtered stream allows it like the select cast.
StreamPollHandle uses it, so adding a TLS stream leaves its buffer and
unread_bytes as they were. The select cast and stream_select() are
unchanged.
This is fixed in 8.6 because the API is new there and this is the
behaviour it should ship with. Keeping a read inside the registration
would complicate things later: once reads on a TLS stream can suspend,
the cast would become a nested read on a stream with an operation in
flight, and changing the cast then would change the visible behaviour of
a released API.
The conversion of the data parameter to Z_PARAM_PATH_STR() made
pg_lo_write() reject any data containing a null byte, breaking writes of
arbitrary binary payloads which were accepted before. Accept embedded
null bytes again by parsing the data as a length-aware string. Sibling
audit: the other Z_PARAM_PATH* conversions from the same change
(pg_connect(), pg_lo_import(), table/statement identifiers) operate on
paths or SQL text where null-byte rejection is intentional.
Closes GH-23649
Headers required by the generated code (zend_attributes.h, zend_constants.h, zend_enum.h) are collected during generation and emitted as includes at the top of the arginfo file, with the same preprocessor conditions and PHP version guards as the code that needs them.
Removes the manual zend_attributes.h and zend_enum.h includes from sources that only needed them for the arginfo file they include.
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
php_pgsql_add_quotes() quotes the string with E'...', but PQescapeStringConn()
does not escape \ unless standard_conforming_strings is off.
PQescapeStringConn() is meant to be used with '', so do that instead.
Fixes GHSA-7qpv-r5mr-78m4
* ftp: For single fd poll calls, use php_pollfd_for_ms
* pgsql: Use php_pollfd_for_ms in compat shim
This is only used on pre-libpq 17.
* fastcgi: Use php_pollfd_for_ms for single fd
This also handles the case where poll isn't available (does that even
matter nowadays?)
* io: Use php_pollfd_for_ms for single fd poll
* cli: Convert to php_pollfd_for from select
This is not a poll call, but it is functionally the same as one; convert
it to the single fd polling function which is clearer to read.
* ext/*: Make `X_from_obj(zend_object *obj)` functions macros
With the introduction of the `ZEND_CONTAINER_OF()` macro we can now preserve
whether or not the `zend_object *` is `const` when extracting the
class-specific struct. This change will allow to use `const zend_object *` in
more locations.
Changes performed with Coccinelle followed by some manual cleanup for comment
and whitespace formatting:
@a@
attribute name zend_always_inline;
type T;
identifier obj;
identifier f;
typedef zend_object;
@@
T* f(zend_object *obj) { return ZEND_CONTAINER_OF(obj, T, std); }
+ #define f(obj) ZEND_CONTAINER_OF(obj, T, std)
@@
identifier a.f;
@@
- f(...) { ... }
@b@
attribute name zend_always_inline;
type T;
identifier obj;
identifier f;
typedef zend_object;
@@
T* f(zend_object *obj) { return ZEND_CONTAINER_OF(obj, T, zo); }
+ #define f(obj) ZEND_CONTAINER_OF(obj, T, zo)
@@
identifier b.f;
@@
- f(...) { ... }
* sockets: Fix build
* odbc: Fix build
* zend_portability: Add `ZEND_CONTAINER_OF()`
* tree-wide: Use `ZEND_CONTAINER_OF()`
Changes made with Coccinelle:
@@
type T_container;
identifier member;
expression e;
@@
- (T_container *)(((char *)(e)) - offsetof(T_container, member))
+ ZEND_CONTAINER_OF(e, T_container, member)
@@
type T_container;
identifier member;
expression e;
typedef uintptr_t;
@@
- (T_container *)(((uintptr_t)(e)) - offsetof(T_container, member))
+ ZEND_CONTAINER_OF(e, T_container, member)
@@
type T_container;
identifier member;
expression e;
@@
- (const T_container *)(((char *)(e)) - offsetof(T_container, member))
+ ZEND_CONTAINER_OF(e, T_container, member)
@@
type T_container;
identifier member;
expression e;
typedef uintptr_t;
@@
- (const T_container *)(((uintptr_t)(e)) - offsetof(T_container, member))
+ ZEND_CONTAINER_OF(e, T_container, member)
* bcmath: Fix `get_bcmath_number_from_obj()` const-correctness
A follow-up change to the new `ZEND_CONTAINER_OF()` macro will preserve the
`const`-ness of the input pointer. By wrapping this macro inside a macro rather
an an inline function we can preserve the `const`-ness across all layers.
* zend_portability: Keep `const`-ness in `ZEND_CONTAINER_OF()`
* zend_portability: Add C++ version to `ZEND_CONTAINER_OF()`
Move object_init_ex() before php_pgsql_fetch_hash() so abstract,
interface and enum errors surface earlier, look up the constructor
via the get_constructor handler (under EG(fake_scope)) so classes
with overridden handlers work, and mark the object as ctor-failed
when the constructor throws.
The ValueError for ctor args on a class without a constructor now
reports argument 4 ($constructor_args) instead of argument 3 ($class).
close GH-21884
There are several issues with this macro:
- It is incorrectly named: It's not an empty default case. It's an unreachable
default case.
- It is hiding control flow in its definition, which can be confusing for
humans and tools (such as Coccinelle) alike, because it looks like it would
be a statement that belongs to the "current" case rather than opening a new
one.
Since this macro is exactly as long as explicitly spelling out its definition
(excluding the useless `break;`), it is not even making the code any more
succinct.
The guards reference undefined VE_PG_LO64, a misspelling of
HAVE_PG_LO64 (removed in GH-14628), making the 64-bit code paths
permanently dead. Remove the guards to unconditionally enable the
64-bit variants for PostgreSQL >= 9.3, consistent with pg_lo_seek().
Dropped from GH-21386 as not suitable for backport.
close GH-21437
The PHP_PQ_ERROR macro calls php_error_docref() which triggers user error handlers
thus libpq does not have the chance to clean the resources (and empty
connections string are allowed) on failure thus we avoid this macro
and delay the error handling after.
close GH-21165