-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Refactor QZydis instance in Bridge class #3641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor QZydis instance in Bridge class #3641
Conversation
Co-authored-by: mr.exodia.tpodt <mr.exodia.tpodt@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Race Condition in Shared Disassembly Instance
A race condition was introduced by changing GUI_GET_DISASSEMBLY
to use a shared mDisasm
QZydis
instance instead of a local one. This allows mDisasm->DisassembleAt()
to be called concurrently with mDisasm->UpdateConfig()
and mDisasm->UpdateArchitecture()
(from configUpdatedSlot
). Without synchronization, this can lead to undefined behavior or inconsistent disassembly results.
src/gui/Src/Bridge/Bridge.cpp#L284-L543
x64dbg/src/gui/Src/Bridge/Bridge.cpp
Lines 284 to 543 in ad8cc1f
void Bridge::configUpdatedSlot() | |
{ | |
if(mDisasm) | |
{ | |
mDisasm->UpdateConfig(); | |
mDisasm->UpdateArchitecture(); | |
} | |
} | |
/************************************************************************************ | |
Message processing | |
************************************************************************************/ | |
void* Bridge::processMessage(GUIMSG type, void* param1, void* param2) | |
{ | |
if(mDbgStopped) //there can be no more messages if the debugger stopped = IGNORE | |
return nullptr; | |
switch(type) | |
{ | |
case GUI_DISASSEMBLE_AT: | |
mLastCip = (duint)param2; | |
emit disassembleAt((duint)param1, (duint)param2); | |
break; | |
case GUI_SET_DEBUG_STATE: | |
mIsRunning = DBGSTATE(duint(param1)) == running; | |
if(!param2) | |
emit dbgStateChanged((DBGSTATE)(dsint)param1); | |
break; | |
case GUI_ADD_MSG_TO_LOG: | |
{ | |
auto msg = (const char*)param1; | |
emit addMsgToLog(QByteArray(msg, int(strlen(msg)) + 1)); //Speed up performance: don't convert to UCS-2 QString | |
} | |
break; | |
case GUI_ADD_MSG_TO_LOG_HTML: | |
{ | |
auto msg = (const char*)param1; | |
emit addMsgToLogHtml(QByteArray(msg, int(strlen(msg)) + 1)); //Speed up performance: don't convert to UCS-2 QString | |
} | |
break; | |
case GUI_CLEAR_LOG: | |
emit clearLog(); | |
break; | |
case GUI_SAVE_LOG: | |
if(!param1) | |
emit saveLog(); | |
else | |
emit saveLogToFile(QString((const char*)param1)); | |
break; | |
case GUI_REDIRECT_LOG: | |
emit redirectLogToFile(QString((const char*)param1)); | |
break; | |
case GUI_STOP_REDIRECT_LOG: | |
emit redirectLogStop(); | |
break; | |
case GUI_UPDATE_WINDOW_TITLE: | |
emit updateWindowTitle(QString((const char*)param1)); | |
break; | |
case GUI_GET_WINDOW_HANDLE: | |
return mWinId; | |
case GUI_DUMP_AT: | |
emit dumpAt((dsint)param1); | |
break; | |
case GUI_SCRIPT_ADD: | |
{ | |
BridgeResult result(BridgeResult::ScriptAdd); | |
emit scriptAdd((int)(duint)param1, (const char**)param2); | |
result.Wait(); | |
} | |
break; | |
case GUI_SCRIPT_CLEAR: | |
emit scriptClear(); | |
break; | |
case GUI_SCRIPT_SETIP: | |
emit scriptSetIp((int)(duint)param1); | |
break; | |
case GUI_SCRIPT_ERROR: | |
{ | |
BridgeResult result(BridgeResult::ScriptMessage); | |
emit scriptError((int)(duint)param1, QString((const char*)param2)); | |
result.Wait(); | |
} | |
break; | |
case GUI_SCRIPT_SETTITLE: | |
emit scriptSetTitle(QString((const char*)param1)); | |
break; | |
case GUI_SCRIPT_SETINFOLINE: | |
emit scriptSetInfoLine((int)(duint)param1, QString((const char*)param2)); | |
break; | |
case GUI_SCRIPT_MESSAGE: | |
{ | |
BridgeResult result(BridgeResult::ScriptMessage); | |
emit scriptMessage(QString((const char*)param1)); | |
result.Wait(); | |
} | |
break; | |
case GUI_SCRIPT_MSGYN: | |
{ | |
BridgeResult result(BridgeResult::ScriptMessage); | |
emit scriptQuestion(QString((const char*)param1)); | |
return (void*)result.Wait(); | |
} | |
break; | |
case GUI_SCRIPT_ENABLEHIGHLIGHTING: | |
emit scriptEnableHighlighting((bool)param1); | |
break; | |
case GUI_SYMBOL_UPDATE_MODULE_LIST: | |
emit updateSymbolList((int)(duint)param1, (SYMBOLMODULEINFO*)param2); | |
break; | |
case GUI_SYMBOL_LOG_ADD: | |
emit addMsgToSymbolLog(QString((const char*)param1)); | |
break; | |
case GUI_SYMBOL_LOG_CLEAR: | |
emit clearSymbolLog(); | |
break; | |
case GUI_SYMBOL_SET_PROGRESS: | |
emit setSymbolProgress((int)(duint)param1); | |
break; | |
case GUI_REF_ADDCOLUMN: | |
if(mReferenceManager->currentReferenceView()) | |
mReferenceManager->currentReferenceView()->addColumnAtRef((int)(duint)param1, QString((const char*)param2)); | |
break; | |
case GUI_REF_SETROWCOUNT: | |
{ | |
if(mReferenceManager->currentReferenceView()) | |
mReferenceManager->currentReferenceView()->setRowCount((dsint)param1); | |
} | |
break; | |
case GUI_REF_GETROWCOUNT: | |
if(mReferenceManager->currentReferenceView()) | |
return (void*)mReferenceManager->currentReferenceView()->stdList()->getRowCount(); | |
return 0; | |
case GUI_REF_SEARCH_GETROWCOUNT: | |
if(mReferenceManager->currentReferenceView()) | |
return (void*)mReferenceManager->currentReferenceView()->mCurList->getRowCount(); | |
return 0; | |
case GUI_REF_DELETEALLCOLUMNS: | |
GuiReferenceInitialize(tr("References").toUtf8().constData()); | |
break; | |
case GUI_REF_SETCELLCONTENT: | |
{ | |
CELLINFO* info = (CELLINFO*)param1; | |
if(mReferenceManager->currentReferenceView()) | |
mReferenceManager->currentReferenceView()->setCellContent(info->row, info->col, QString(info->str)); | |
} | |
break; | |
case GUI_REF_GETCELLCONTENT: | |
{ | |
QString content; | |
if(mReferenceManager->currentReferenceView()) | |
content = mReferenceManager->currentReferenceView()->stdList()->getCellContent((int)(duint)param1, (int)(duint)param2); | |
auto bytes = content.toUtf8(); | |
auto data = BridgeAlloc(bytes.size() + 1); | |
memcpy(data, bytes.constData(), bytes.size()); | |
return data; | |
} | |
case GUI_REF_SEARCH_GETCELLCONTENT: | |
{ | |
QString content; | |
if(mReferenceManager->currentReferenceView()) | |
content = mReferenceManager->currentReferenceView()->mCurList->getCellContent((int)(duint)param1, (int)(duint)param2); | |
auto bytes = content.toUtf8(); | |
auto data = BridgeAlloc(bytes.size() + 1); | |
memcpy(data, bytes.constData(), bytes.size()); | |
return data; | |
} | |
case GUI_REF_RELOADDATA: | |
emit referenceReloadData(); | |
break; | |
case GUI_REF_SETSINGLESELECTION: | |
emit referenceSetSingleSelection((int)(duint)param1, (bool)param2); | |
break; | |
case GUI_REF_SETPROGRESS: | |
if(mReferenceManager->currentReferenceView()) | |
{ | |
auto newProgress = (int)(duint)param1; | |
if(mReferenceManager->currentReferenceView()->progress() != newProgress) | |
emit referenceSetProgress(newProgress); | |
} | |
break; | |
case GUI_REF_SETCURRENTTASKPROGRESS: | |
if(mReferenceManager->currentReferenceView()) | |
{ | |
auto newProgress = (int)(duint)param1; | |
if(mReferenceManager->currentReferenceView()->currentTaskProgress() != newProgress) | |
emit referenceSetCurrentTaskProgress((int)(duint)param1, QString((const char*)param2)); | |
} | |
break; | |
case GUI_REF_SETSEARCHSTARTCOL: | |
if(mReferenceManager->currentReferenceView()) | |
mReferenceManager->currentReferenceView()->setSearchStartCol((duint)param1); | |
break; | |
case GUI_REF_INITIALIZE: | |
{ | |
BridgeResult result(BridgeResult::RefInitialize); | |
emit referenceInitialize(QString((const char*)param1)); | |
result.Wait(); | |
} | |
break; | |
case GUI_STACK_DUMP_AT: | |
emit stackDumpAt((duint)param1, (duint)param2); | |
break; | |
case GUI_ADD_RECENT_FILE: | |
emit addRecentFile(QString((const char*)param1)); | |
break; | |
case GUI_SET_LAST_EXCEPTION: | |
emit setLastException((unsigned int)(duint)param1); | |
break; | |
case GUI_GET_DISASSEMBLY: | |
{ | |
duint parVA = (duint)param1; | |
char* text = (char*)param2; | |
if(!text || !parVA || !DbgIsDebugging() || !mDisasm) | |
return 0; | |
byte_t buffer[16]; | |
if(!DbgMemRead(parVA, buffer, 16)) | |
return 0; | |
Instruction_t instr = mDisasm->DisassembleAt(buffer, 16, 0, parVA); |
BugBot free trial expires on July 22, 2025
You have used $0.00 of your $10.00 spend limit so far. Manage your spend limit in the Cursor dashboard.
Was this report helpful? Give feedback by reacting with 👍 or 👎
Make
QZydis
a member of theBridge
class to optimizeGuiGetDisassembly
performance and ensure configuration synchronization.