Fix a possible use-after-free in EDS transaction rollback#8991
Fix a possible use-after-free in EDS transaction rollback#8991MochalovAlexey wants to merge 1 commit intoFirebirdSQL:masterfrom
Conversation
Raise EDS rollback exception before the connection can be released by deleteTransaction(). Cleanup is still performed by catching the error and rethrow the original exception.
|
I would suggest to use |
| detachFromJrdTran(); | ||
| m_connection.deleteTransaction(tdbb, this); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Why not use class Cleanup here and avoid re-throw and explicit cleanup ?
That would be risky here because the cleanup destructor may throw from deleteTransaction(). |
Because it is a cleanup routine, I would make sure that it cannot throw. Throwing from |
|
Strictly speaking Alexey is correct. I'd say all usages of |
They say clang-tidy can track cases when noexcept functions call non-noexcept functions. May be it can handle destructors and lambdas. In this case it could be enough to mark |
|
On 4/16/26 20:38, Dmitry Yemanov wrote:
*dyemanov* left a comment (FirebirdSQL/firebird#8991)
<#8991 (comment)>
Strictly speaking Alexey is correct. I'd say all usages of |class
Cleanup| should be revisited, because |CCH_release|, |TRA_rollback|,
whatever -- all they can throw (even if unlikely). Moreover, our code
in /common/classes often throws from RAII destructors (usually this is
|system_call_failed|). The question is whether we're going to solve
this problem globally before v6 is out.
Yes, Cleanup is very small part of bigger problem. We should solve the
problem in general. May be ideal way is to merge exceptions according to
ERR_punt() rules but right now I see no easy way to do it,
std::uncaught_exceptions() returns only unwinding state and anyway we
can't modify active exception. In absence of better solutions we may
silently ignore errors in dtor, in most cases they are caused by
problems related with initial exception.
|
EDS::Transaction::rollback()used to callm_connection.deleteTransaction()before reporting rollback errors. This cleanup may release or delete the owningEDS::Connection.If rollback returned an error, the code then called
conn.raise(), which usesgetDataSourceName()and readsm_dbNamefrom the potentially deleted connection. This could lead to a crash while building the error message.The fix raises the rollback error while the connection is still alive and uses a catch/rethrow block to guarantee external transaction cleanup before propagating the original exception.