Fix crash in firebird statement dtor

If both the driver object and statement end up in the GC buffer and are
freed by the GC, then the destruction order is not deterministic and it
is possible that the driver object is freed before the statement. In
that case, accessing S->H will cause a UAF. As the resources are already
released we simply skip the destruction if the driver object is already
destroyed.
This commit is contained in:
Niels Dossche 2025-01-24 20:19:42 +01:00 committed by Gina Peter Banyard
parent 99f8ec33d9
commit 2ae897fff7
No known key found for this signature in database
GPG key ID: F30F8C1ACF51943F

View file

@ -87,8 +87,15 @@ static int firebird_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
int result = 1; int result = 1;
/* release the statement */ /* TODO: for master, move this check to a separate function shared between pdo drivers.
if (isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) { * pdo_pgsql and pdo_mysql do this exact same thing */
bool server_obj_usable = !Z_ISUNDEF(stmt->database_object_handle)
&& IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)])
&& !(OBJ_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED);
/* release the statement.
* Note: if the server object is already gone then the statement was closed already as well. */
if (server_obj_usable && isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) {
RECORD_ERROR(stmt); RECORD_ERROR(stmt);
result = 0; result = 0;
} }