Icon View Incident Report

Serious Serious
Reported By: Krystian Bigaj
Reported On: 10/13/2023
For: Version 2.37 Build 1
# 4910 ElevateDB Server Encountering Use-After-Free AV When Cleaning Up Dead Sessions

I've identified possible memory corruption (use after free bug), that causes EDB Server to crash, or dead-lock, etc.
Possibly because of this bug, I've seen errors like "#9999 Cannot lock new handle object" , access Violations, or many other "strange" exceptions (session lock timeouts that never unlocks, except after EDB server restart, etc.).

It looks like an incorrect order of destroying objects in CheckForDeadServerUserSessionManagers
TEDBLocalCursor.Destroy tries to call:
FTableManager.DatabaseManager.Cursors.ClearObject(Self);
FTableManager.DatabaseManager.SessionManager.Cursors.RemoveObject(Self);
but FTableManager has been already destroyed.

"	start EDB server (Remote)
"	connect to it by for example ElevateDB Manager (Remote session over TCP)
"	open any table by SQL query with data (like: SELECT * FROM testtable), and keep it open (do NOT Close result set or do NOT Unprepare). Opening table does not trigger error. Only opening Query and keep it open
"	terminate process of ElevateDB Manager (I'm using process explorer, to make sure it's TerminateProcess'ed, not safe close) - it's required to simulate TCP connection termination
"	wait for CheckForDeadServerUserSessionManagers to call Close for dead session, I've commented out:
//                        if (TempTotalDeadSessions > FMaxDeadSessions) or 
//                           ((FDeadSessionExpiration > 0) and
//                            (GetSecondsBetween(TempServerUserSessionManager.LastConnected,CurrentTimeStamp) > FDeadSessionExpiration)) then
to make bug to reproduce more easy. If you do not comment that check, then you will have to make at least FMaxDeadSessions dead sessions.
"	keep in mind, that it's a use after free bug, so it might not be always reproduced. But if you use for example FastMM4 with FullDebugMode (which clears memory after release), then you will be able to reproduce it almost 100/100.



Comments Comments
constructor TEDBLocalCursor.Create(TableManagerToUse: TEDBVirtualTableManager;
const CursorName: String;
OpenReadOnly: Boolean=False;
OpenExclusive: Boolean=False);
var
I: Integer;
begin

inherited Create(CursorName,TableManagerToUse.DatabaseManager.SessionManager.Settings.CharacterSet,
OpenReadOnly,OpenExclusive);
FTableManager:=TableManagerToUse;

// Workaround: keep separate FTableManager_DatabaseManager for Destroy
FTableManager_DatabaseManager:= FTableManager.DatabaseManager; // add field FTableManager_DatabaseManager in TEDBLocalCursor
...

destructor TEDBLocalCursor.Destroy;
begin
// Workaround: use FTableManager_DatabaseManager (set in constructor), beacuse FTableManager might be already destroyed
FTableManager_DatabaseManager.Cursors.ClearObject(Self);
FTableManager_DatabaseManager.SessionManager.Cursors.RemoveObject(Self);
// FTableManager.DatabaseManager.Cursors.ClearObject(Self);
// FTableManager.DatabaseManager.SessionManager.Cursors.RemoveObject(Self);


Resolution Resolution
Fixed Problem on 10/30/2023 in version 2.37 build 2


Products Affected Products Affected
ElevateDB Additional Software and Utilities
ElevateDB DAC Client-Server
ElevateDB DAC Client-Server with Source
ElevateDB DAC Standard
ElevateDB DAC Standard with Source
ElevateDB DAC Trial
ElevateDB LCL Standard with Source
ElevateDB PHP Standard
ElevateDB PHP Standard with Source
ElevateDB PHP Trial
ElevateDB VCL Client-Server
ElevateDB VCL Client-Server with Source
ElevateDB VCL Standard
ElevateDB VCL Standard with Source
ElevateDB VCL Trial

Image