Priority: Not Evaluated
Affects Version/s: Qt Creator 4.13.0-beta1
Fix Version/s: None
Environment:Qt Creator compiled from master branch at commit 7c985c14ad3ef802a4f2b490559cf30df226d84f
When having a C++ project open and writing a function call until the first parenthesis like "function(", Qt Creator occasionally crash.
After investigation, it is a use after free bug on IAssistProcessor
When CodeAssistantPrivate::cancelCurrentRequest is called,
delete m_asyncProcessor; is done on the processor.
But the cancel request is not handled on the ClangCompletionAssistProcessor side, and when the result of the completion request is received from the clang backend, it will call setAsyncProposalAvailable on the now deleted processor. Then this cause Qt Creator to crash.
The processor is kept on clang side in BackendReceiver::m_assistProcessorsTable.
I think that setAsyncProposalAvailable nor the processor deletion should never be done from outside of the concrete processor (here, from ClangCompletionAssistProcessor) which is the responsible to call it and the owner of the processor while it is running, and instead it should handle the cancel case appropriately.
Maybe pass around std::unique_ptr if possible to ensure the uniqueness of the owner.
In this case, cancel should always be defined which means it would be a virtual pure function in IAssistProcessor instead of a function doing nothing, to ensure the underlying code is aware of the cancel request (and remove the processor reference it has as appropriate).
Maybe other processors than the clang code model's one are affected too.
I think the bug was introduced with commit 8bde432dfe40ff9b9491acd62a7854c060cad01d which was done to avoid processor leaks.
To reproduce the bug, I do this:
- Have a C++ project with a cpp file open and clang code model enabled
- Write a function call until the first parenthesis like this "function("
- Then repeatedly do "Backspace" and "(" to remove and re-add the parenthesis
Eventually, this will cause a crash in some code in the processor called from BackendReceiver::completions.
(Sometimes I need to to this for like 30s, this is random)