SlideShare a Scribd company logo
Checking the Qt 5 Framework 
Author: Andrey Karpov 
Date: 18.04.2014 
Static code analysis tools can help developers eliminate numbers of bugs as early as at the coding stage. 
With their help you can, for example, quickly catch and fix any typos. Well, some programmers are 
sincerely sure they never make typos and silly mistakes. But they are wrong; everyone makes mistakes. 
This article is a good evidence of that. Typos can be found even in high-quality and well tested projects 
such as Qt. 
Qt 
Qt is a cross-platform application framework that is widely used for developing application software 
with a graphical user interface (GUI) (in which cases Qt is classified as a widget toolkit), and also used for 
developing non-GUI programs such as command-line tools and consoles for servers. 
Qt uses standard C++ but makes extensive use of a special code generator (called the Meta Object 
Compiler, or moc) together with several macros to enrich the language. Qt can also be used in several 
other programming languages via language bindings. It runs on the major desktop platforms and some 
of the mobile platforms. It has extensive internationalization support. Non-GUI features include SQL 
database access, XML parsing, thread management, network support, and a unified cross-platform 
application programming interface (API) for file handling. [the source: Wikipedia] 
Links: 
• Wikipedia: Qt; 
• The official website: Qt Project; 
• The article about Qt 4.7.3's check in 2011. 
This time we were dealing with Qt 5.2.1. Analysis was done with the PVS-Studio 5.15 analyzer. 
Please note that PVS-Studio managed to detect bugs despite that the Qt project had been checked 
before by the Klocwork and Coverity analyzers. I don't know how regularly the project's authors use 
these tools, but Klocwork and Coverity are mentioned in the bugtracker and ChangeLog-xxx files. I also 
saw Qt mentioned to be regularly checked with PC-lint.
Specifics of the Qt project's analysis 
Just for a change, we decided to check Qt using a new mechanism recently introduced in PVS-Studio 
Standalone. Nobody knows of this mechanism yet, so we will remind you about it from time to time in 
our next articles. Well, what is that mysterious and wonderful mechanism, after all? 
In certain cases, you may have a difficult time trying to check a project with PVS-Studio - these are the 
cases when the project is built with nmake and the like. You need to integrate PVS-Studio into the build, 
which becomes not an easy thing to do. To say the least, quickly trying and making up an opinion about 
the tool will become impossible. 
But now PVS-Studio has acquired a new mode which makes it much simpler to work with such projects. 
The analyzer has learned how to trace compilation parameters and collect all the necessary information 
for analysis. You just need to tell the analyzer when to start monitoring compiler calls and when to stop 
it. 
Compilation monitoring can be controlled both from the GUI application and the command line. To find 
out more about how it all works and how to use this mode, see the following article: 
Evgeniy Ryzhkov. PVS-Studio Now Supports Any Build System under Windows and Any Compiler. Easy 
and Right Out of the Box. 
It describes the process of checking the Qt project with the monitoring mode launched from the 
command line. 
Do read it please to avoid any misconceptions. For example, you should keep in mind that you can't 
code while project compilation is being monitored: if you compile files from another project, the 
analyzer will collect the information about these files and check them too. It will result in the analysis 
report including extraneous messages, the relevant and irrelevant warnings all mixed in one pile. 
Analysis results 
My general opinion of Qt's code is this: 
It is pretty high-quality and is almost free of bugs related to dangerous specifics of the C++ language. On 
the other hand, it does have quite a lot of ordinary typos. 
This article is a good illustration of the thesis that every developer makes typos, however skillful he is. 
Static code analysis has always been and will be topical and useful. Suppose the analyzer has found 10 
typos with a one-time check. So it could have prevented hundreds or thousands of bugs by now if it had 
been used regularly. That makes an enormous amount of time that could have been saved. Therefore it 
is much more profitable to detect an error right after it has been made than at the stage of code 
debugging or after user complaints.
Welcome to a wondrous world of typos 
Typo No.1 
bool QWindowsUser32DLL::initTouch() 
{ 
QSystemLibrary library(QStringLiteral("user32"));
registerTouchWindow = ....; 
unregisterTouchWindow = ....; 
getTouchInputInfo = ....; 
closeTouchInputHandle = ....; 
return registerTouchWindow && 
unregisterTouchWindow && 
getTouchInputInfo && 
getTouchInputInfo; 
} 
PVS-Studio's diagnostic message: V501 There are identical sub-expressions 'getTouchInputInfo' to the 
left and to the right of the '&&' operator. qwindowscontext.cpp 216 
Values are assigned to four variables, and all the four must be checked. But only 3 are actually checked 
because of a typo. In the last line, 'closeTouchInputHandle' should be written instead of 
'getTouchInputInfo'. 
Typo No.2 
QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(....) 
{ 
.... 
int iw = gm.width.toInt(); 
int ih = gm.height.toInt(); 
if (iw <= 0 || iw <= 0) 
return 0; 
.... 
} 
PVS-Studio's diagnostic message: V501 There are identical sub-expressions to the left and to the right of 
the '||' operator: iw <= 0 || iw <= 0 qwindowsfontengine.cpp 1095 
The check of the height parameter stored in the 'ih' variable is missing. 
Typos No.3, No.4
This error was found inside tests. A nice example of how static analysis complements unit tests. To find 
out more on this topic, see the article: "How to complement TDD with static analysis". 
inline bool qCompare(QImage const &t1, QImage const &t2, ....) 
{ 
.... 
if (t1.width() != t2.width() || t2.height() != t2.height()) { 
.... 
} 
PVS-Studio's diagnostic message: V501 There are identical sub-expressions to the left and to the right of 
the '!=' operator: t2.height() != t2.height() qtest_gui.h 101 
The function to compare two images is incorrectly comparing their heights. Or rather, it doesn't 
compare them at all. 
This bug was multiplied through the Copy-Paste method. The same comparison can be found a bit 
farther in the code in the same file (line 135). 
Typo No.5 
I apologize for the ugly code formatting - the lines were too lengthy. 
void QXmlSimpleReader::setFeature( 
const QString& name, bool enable) 
{ 
.... 
} else if ( name == QLatin1String( 
"http://trolltech.com/xml/features/report-start-end-entity") 
|| name == QLatin1String( 
"http://trolltech.com/xml/features/report-start-end-entity")) 
{ 
.... 
} 
PVS-Studio's diagnostic message: V501 There are identical sub-expressions to the left and to the right of 
the '||' operator. qxml.cpp 3249 
The 'name' variable is compared to one and the same string twice. A bit earlier in the code, a similar 
comparison can be found where a variable is compared with the following two strings: 
• http://trolltech.com/xml/features/report-whitespace-only-CharData
• http://qt-project.org/xml/features/report-whitespace-only-CharData 
By analogy, you can conclude that the 'name' variable in the fragment we are discussing should have 
been compared with the following strings: 
• http://trolltech.com/xml/features/report-start-end-entity 
• http://qt-project.org/xml/features/report-start-end-entity 
Typos No.6, No.7, No.8, No.9 
QString DayTimeDuration::stringValue() const 
{ 
.... 
if(!m_hours && !m_minutes && !m_seconds && !m_seconds) 
.... 
} 
PVS-Studio's diagnostic message: V501 There are identical sub-expressions '!m_seconds' to the left and 
to the right of the '&&' operator. qdaytimeduration.cpp 148 
The programmer forgot about milliseconds. Milliseconds are stored in the 'm_mseconds' variable. The 
check should look like this: 
if(!m_hours && !m_minutes && !m_seconds && !m_mseconds) 
There are similar mistakes with milliseconds in three other fragments: 
• qdaytimeduration.cpp 170 
• qduration.cpp 167 
• qduration.cpp 189 
Typo No.10 
QV4::ReturnedValue 
QQuickJSContext2DPrototype::method_getImageData( 
QV4::CallContext *ctx) 
{ 
.... 
qreal x = ctx->callData->args[0].toNumber(); 
qreal y = ctx->callData->args[1].toNumber(); 
qreal w = ctx->callData->args[2].toNumber(); 
qreal h = ctx->callData->args[3].toNumber(); 
if (!qIsFinite(x) || !qIsFinite(y) ||
!qIsFinite(w) || !qIsFinite(w)) 
.... 
} 
PVS-Studio's diagnostic message: V501 There are identical sub-expressions '!qIsFinite(w)' to the left and 
to the right of the '||' operator. qquickcontext2d.cpp 3305 
A check of the 'h' variable is missing. The 'w' variable is checked twice instead. 
Typo No.11 
AtomicComparator::ComparisonResult 
IntegerComparator::compare(const Item &o1, 
const AtomicComparator::Operator, 
const Item &o2) const 
{ 
const Numeric *const num1 = o1.as<Numeric>(); 
const Numeric *const num2 = o1.as<Numeric>(); 
if(num1->isSigned() || num2->isSigned()) 
.... 
} 
V656 Variables 'num1', 'num2' are initialized through the call to the same function. It's probably an error 
or un-optimized code. Consider inspecting the 'o1.as < Numeric > ()' expression. Check lines: 220, 221. 
qatomiccomparators.cpp 221 
The variables 'num1' and 'num2' are initialized to one and the same value. Then both the variables are 
checked, and that is strange: it would be enough to check only one variable. 
The 'num2' variable was most likely meant to be initialized to an expression with the 'o2' argument: 
const Numeric *const num1 = o1.as<Numeric>(); 
const Numeric *const num2 = o2.as<Numeric>(); 
Typo No.12 
void Atlas::uploadBgra(Texture *texture) 
{ 
const QRect &r = texture->atlasSubRect(); 
QImage image = texture->image();
if (image.format() != QImage::Format_ARGB32_Premultiplied || 
image.format() != QImage::Format_RGB32) { 
.... 
} 
V547 Expression is always true. Probably the '&&' operator should be used here. qsgatlastexture.cpp 
271 
The condition in this code is meaningless as it is always true. Here you are a simplified sample to make it 
clearer: 
int a = ...; 
if (a != 1 || a != 2) 
The variable will always be not equal to something. 
I can't say for sure what exactly the correct code should look like. It may be like this: 
if (image.format() == QImage::Format_ARGB32_Premultiplied || 
image.format() == QImage::Format_RGB32) { 
or this: 
if (image.format() != QImage::Format_ARGB32_Premultiplied && 
image.format() != QImage::Format_RGB32) { 
Typo No.13 
void QDeclarativeStateGroupPrivate::setCurrentStateInternal( 
const QString &state, 
bool ignoreTrans) 
{ 
.... 
QDeclarativeTransition *transition = 
(ignoreTrans || ignoreTrans) ? 
0 : findTransition(currentState, state); 
.... 
} 
PVS-Studio's diagnostic message: V501 There are identical sub-expressions to the left and to the right of 
the '||' operator: ignoreTrans || ignoreTrans qdeclarativestategroup.cpp 442
Something is wrong with this code. I can't figure out how exactly the programmer meant to implement 
the check. 
Typo No.14 
QV4::ReturnedValue 
QQuickJSContext2DPrototype::method_createPattern(....) 
{ 
.... 
if (repetition == QStringLiteral("repeat") || 
repetition.isEmpty()) { 
pattern->patternRepeatX = true; 
pattern->patternRepeatY = true; 
} else if (repetition == QStringLiteral("repeat-x")) { 
pattern->patternRepeatX = true; 
} else if (repetition == QStringLiteral("repeat-y")) { 
pattern->patternRepeatY = true; 
} else if (repetition == QStringLiteral("no-repeat")) { 
pattern->patternRepeatY = false; 
pattern->patternRepeatY = false; 
} else { 
//TODO: exception: SYNTAX_ERR 
} 
.... 
} 
PVS-Studio's diagnostic message: V519 The 'pattern->patternRepeatY' variable is assigned values twice 
successively. Perhaps this is a mistake. Check lines: 1775, 1776. qquickcontext2d.cpp 1776 
The 'patternRepeatY' variable is assigned values twice on end: 
pattern->patternRepeatY = false; 
pattern->patternRepeatY = false; 
I guess the correct code should look as follows: 
} else if (repetition == QStringLiteral("no-repeat")) {
pattern->patternRepeatX = false; 
pattern->patternRepeatY = false; 
} else { 
Misuse of the C++ language 
As I've already said, most bugs in this project are ordinary typos. There are almost no errors related to 
misuse of the C++ language. However, the analyzer has caught a couple of these. 
A nice error related to operation priorities 
bool QConfFileSettingsPrivate::readIniLine(....) 
{ 
.... 
char ch; 
while (i < dataLen && 
((ch = data.at(i) != 'n') && ch != 'r')) 
++i; 
.... 
} 
V593 Consider reviewing the expression of the 'A = B != C' kind. The expression is calculated as 
following: 'A = (B != C)'. qsettings.cpp 1702
The loop is designed to find the end of a string. The characters 'n' or 'r' are used as end-of-string 
indicators. 
Inside the condition, a character must be taken and compared against 'n' and 'r'. The error occurs 
because the '!=' operator's priority is higher than that of the '=' operator. Because of this, the 'true' or 
'false' value is written instead of the character code into the 'ch' variable. It makes the 'r' comparison 
meaningless. 
Let's arrange parentheses to make the error clearer: 
while (i < dataLen && 
((ch = (data.at(i) != 'n')) && ch != 'r')) 
Because of the mistake, it is only the 'n' character that is treated as an end-of-string indicator. The 
function won't work correctly for strings ending with 'r'. 
The fixed code should look as follows: 
while (i < dataLen && 
(ch = data.at(i)) != 'n' && ch != 'r') 
Loss of Accuracy 
bool QWindowsTabletSupport::translateTabletPacketEvent() 
{ 
.... 
const double radAzim = 
(packet.pkOrientation.orAzimuth / 10) * (M_PI / 180); 
.... 
} 
V636 The 'packet.pkOrientation.orAzimuth / 10' expression was implicitly casted from 'int' type to 
'double' type. Consider utilizing an explicit type cast to avoid the loss of a fractional part. An example: 
double A = (double)(X) / Y;. qwindowstabletsupport.cpp 467 
The 'packet.pkOrientation.orAzimuth' variable is of the 'int' type. This integer variable is divided by 10. 
What is suspicious about this is that the quotient is then used together with values of the 'double' type. 
The final result is also saved into a variable of the 'double' type. 
Such integer division is not always an error. Perhaps this code is written just the way the programmer 
intended. But practice shows that it is more often than not a mistake causing accuracy loss. 
Suppose, for instance, that the 'packet.pkOrientation.orAzimuth' variable equals 55. Then the 
calculation result will be: 
(55 / 10) * (3.14159... / 180) = 5 * 0,01745... = 0,087266...
The accuracy of these calculations can be significantly improved by just declaring the 10 constant as of 
the double type: "(packet.pkOrientation.orAzimuth / 10.0) * (M_PI / 180)". The result will then be: 
(55 / 10.0) * (3.14159... / 180) = 5.5 * 0,01745... = 0,095993... 
Accuracy losses like that often happen because of programmers being careless about expressions where 
different types are used together. It is also due to this carelessness that many 64-bit errors occur (see 
mixed arithmetic). 
The analyzer has found 51 more suspicious cases of integer division. Some of them may prove less 
accurate than the programmer wanted them to be. I've collected the corresponding diagnostic 
messages in a separate list: qt-v636.txt. 
Meaningless pointer checks 
It has been for a long time now that checking a pointer for being null doesn't make any sense when the 
'new' operator is used to allocate memory. Nowadays, it throws an exception when it fails to allocate 
memory. Of course, you can make the 'new' operator return 0, but we are not speaking of these cases 
now. 
However, programmers sometimes forget about that and write meaningless checks in their code. 
HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone( 
IEnumVARIANT **ppEnum) 
{ 
QWindowsEnumerate *penum = 0; 
*ppEnum = 0; 
penum = new QWindowsEnumerate(array); 
if (!penum) 
return E_OUTOFMEMORY; 
.... 
} 
PVS-Studio's diagnostic message: V668 There is no sense in testing the 'penum' pointer against null, as 
the memory was allocated using the 'new' operator. The exception will be generated in the case of 
memory allocation error. qwindowsmsaaaccessible.cpp 141 
There are some more checks like that in the project: main.cpp 127, qaudiodevicefactory.cpp 236, 
qaudiodevicefactory.cpp 263, qaudiobuffer.cpp 488, mfvideorenderercontrol.cpp 143, 
mfvideorenderercontrol.cpp 158, mfvideorenderercontrol.cpp 1193, mfvideorenderercontrol.cpp 1199, 
qaxserverbase.cpp 1006, positionpollfactory.cpp 60.
The dark side 
There are two code fragments in the Qt project about which I can't say for sure if they are errors or not 
as I'm not familiar with the project architecture and its implementation specifics. But even if they don't 
have errors, they certainly belong to the dark side of the C++ programming practice. 
class Q_CORE_EXPORT QObject 
{ 
.... 
virtual ~QObject(); 
virtual bool event(QEvent *); 
virtual bool eventFilter(QObject *, QEvent *); 
.... 
}; 
QObject *QQmlVME::run(....) 
{ 
.... 
QObject *o = (QObject *)operator 
new(instr.typeSize + sizeof(QQmlData)); 
::memset(static_cast<void *>(o), 0,
instr.typeSize + sizeof(QQmlData)); 
.... 
} 
PVS-Studio's diagnostic message: V598 The 'memset' function is used to nullify the fields of 'QObject' 
class. Virtual method table will be damaged by this. qqmlvme.cpp 658 
The QObject class has virtual functions, which means the object stores a pointer to a virtual methods 
table. I don't find it a good idea to implement such objects through the memset() function. 
One more message of that kind: V598 The 'memset' function is used to nullify the fields of 'QObject' 
class. Virtual method table will be damaged by this. qdeclarativevme.cpp 286 
Null pointer dereferencing 
I guess these errors could be classified as typos, but I like to single them out into a separate group. It 
makes them look somewhat more somber and serious. 
Note. Bug classification is pretty relative; many errors can be usually classified as a typo, a vulnerability, 
an array overrun, and so on. 
But let's get back to null pointers. 
A typo leading to null pointer dereferencing 
QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed( 
QV4::Managed *m, uint index, bool *hasProperty) 
{ 
.... 
if (!m) 
return m->engine()->currentContext()->throwTypeError(); 
.... 
} 
PVS-Studio's diagnostic message: V522 Dereferencing of the null pointer 'm' might take place. 
qquickcontext2d.cpp 3169 
I'm sure the '!' operator is unnecessary here. It's an ordinary typo leading to a serious bug. 
Null pointer dereferencing in an error handler 
void QDocIndexFiles::readIndexSection(....) 
{ 
.... 
DocNode* dn = qdb_->findGroup(groupNames[i]);
if (dn) { 
dn->addMember(node); 
} 
else { 
.... 
qDebug() << "DID NOT FIND GROUP:" << dn->name() 
<< "for:" << node->name(); 
} 
.... 
} 
PVS-Studio's diagnostic message: V522 Dereferencing of the null pointer 'dn' might take place. 
qdocindexfiles.cpp 539 
If an error occurs, the program must print an error message trying to take the name from a nonexistent 
object: dn->name(). 
82 potential null pointer dereferencing errors 
Most project (and Qt is no exception) have null pointer handling issues. The check is often done after 
the pointer has been used. It's not always an error; there are cases when the pointer just can never be 
null. 
But anyway, such fragments need to be attentively checked and refactored. Even if there is no error, an 
excess pointer check confuses the programmer reading the code. 
Have a look at one dangerous code sample: 
static int gray_raster_render(....) 
{ 
const QT_FT_Outline* outline = 
(const QT_FT_Outline*)params->source; 
.... 
/* return immediately if the outline is empty */ 
if ( outline->n_points == 0 || outline->n_contours <= 0 ) 
return 0;
if ( !outline || !outline->contours || !outline->points ) 
return ErrRaster_Invalid_Outline; 
.... 
} 
PVS-Studio's diagnostic message: V595 The 'outline' pointer was utilized before it was verified against 
nullptr. Check lines: 1746, 1749. qgrayraster.c 1746 
I guess the error must have appeared when the programmer was trying to optimize the 
gray_raster_render() function. It seems that the following lines were added later into an already 
complete function code: 
/* return immediately if the outline is empty */ 
if ( outline->n_points == 0 || outline->n_contours <= 0 ) 
return 0; 
The trouble is that the 'outline' pointer may be null, but the necessary check is written after that 
fragment. 
The analyzer has found 81 more potential issues like that. Here is a complete list of them: qt-v595.txt. 
Questions without answers 
There are strange code fragments about whose origin and the programmer's intentions about them you 
can't be sure. They may be typos or incomplete code or unsuccessful refactoring - whatever. 
Double check 
QWindowsFontEngine::~QWindowsFontEngine() 
{ 
.... 
if (QWindowsContext::verboseFonts) 
if (QWindowsContext::verboseFonts) 
qDebug("%s: font='%s", __FUNCTION__, qPrintable(_name)); 
....
} 
PVS-Studio's diagnostic message: V571 Recurring check. The 'if (QWindowsContext::verboseFonts)' 
condition was already verified in line 369. qwindowsfontengine.cpp 370 
What's the use checking one and the same thing twice? One of the checks is probably excess; or 
something else was meant to be checked. 
Double assignment 
void Moc::parse() 
{ 
.... 
index = def.begin + 1; 
namespaceList += def; 
index = rewind; 
.... 
} 
PVS-Studio's diagnostic message: V519 The 'index' variable is assigned values twice successively. 
Perhaps this is a mistake. Check lines: 568, 570. moc.cpp 570 
Why different values are assigned to the 'index' variable? 
There are a few more similar strange code fragments: 
• V519 The 'exitCode' variable is assigned values twice successively. Perhaps this is a mistake. 
Check lines: 807, 815. qprocess.cpp 815 
• V519 The 'detecting' variable is assigned values twice successively. Perhaps this is a mistake. 
Check lines: 163, 164. qhoversensorgesturerecognizer.cpp 164 
• V519 The 'increaseCount' variable is assigned values twice successively. Perhaps this is a 
mistake. Check lines: 185, 186. qtwistsensorgesturerecognizer.cpp 186 
Suspecting a missing 'break' operator 
bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) 
{ 
.... 
switch (key) { 
case Qt::Key_Enter: 
case Qt::Key_Return: 
doneCompletion();
consumed = true; 
case Qt::Key_Escape: 
editor->setFocus(); 
popup->hide(); 
consumed = true; 
case Qt::Key_Up: 
case Qt::Key_Down: 
case Qt::Key_Home: 
case Qt::Key_End: 
case Qt::Key_PageUp: 
case Qt::Key_PageDown: 
break; 
.... 
} 
PVS-Studio's diagnostic message: V519 The 'consumed' variable is assigned values twice successively. 
Perhaps this is a mistake. Check lines: 110, 115. googlesuggest.cpp 115 
So is the break operator missing here or not? 
The analyzer found it strange that the 'consumed' variable was assigned the 'true' value twice on end. It 
suggests a missing break operator, but I'm not sure. It may be just that the first assignment should be 
removed: "consumed = true;". 
Suspecting an excess 'break' operator 
bool QHelpGenerator::registerVirtualFolder(....) 
{ 
.... 
while (d->query->next()) { 
d->namespaceId = d->query->value(0).toInt(); 
break; 
} 
....
} 
PVS-Studio's diagnostic message: V612 An unconditional 'break' within a loop. qhelpgenerator.cpp 429 
Was the 'break' operator really meant to terminate the loop right away? 
One more fragment of that kind can be found here: qhelpgenerator.cpp 642 
Miscellaneous 
Be patient: there's not much left, just a handful of diverse errors. 
Incorrect use of the toLower() function 
int main(int argc, char **argv) 
{ 
.... 
QByteArray arg(argv[a]); 
.... 
arg = arg.mid(1); 
arg.toLower(); 
if (arg == "o") 
.... 
} 
PVS-Studio's diagnostic message: V530 The return value of function 'toLower' is required to be utilized. 
main.cpp 72 
The 'toLower()' function doesn't change the object - it returns a copy of an object that will store lower 
case characters. 
One more defect: V530 The return value of function 'toLower' is required to be utilized. main.cpp 1522 
Array index out of bounds 
It's a complicated issue, so please be attentive. 
There is an enum type in the code: 
typedef enum { 
JNone, 
JCausing, 
JDual, 
JRight,
JTransparent 
} Joining; 
Note that JTransparent == 4 and keep that in mind. 
Now let's examine the getNkoJoining() function: 
static Joining getNkoJoining(unsigned short uc) 
{ 
if (uc < 0x7ca) 
return JNone; 
if (uc <= 0x7ea) 
return JDual; 
if (uc <= 0x7f3) 
return JTransparent; 
if (uc <= 0x7f9) 
return JNone; 
if (uc == 0x7fa) 
return JCausing; 
return JNone; 
} 
What matters to us is that this function may return 'JTransparent', i.e. the function may return 4. 
There is also a two-dimensional array 'joining_table': 
static const JoiningPair joining_table[5][4] = { .... }; 
And here's the piece of code itself where the error may occur: 
static void getNkoProperties(....) 
{ 
.... 
Joining j = getNkoJoining(chars[0]); 
ArabicShape shape = joining_table[XIsolated][j].form2; 
.... 
}
PVS-Studio's diagnostic message: V557 Array overrun is possible. The value of 'j' index could reach 4. 
harfbuzz-arabic.c 516 
As we remember, the getNkoJoining() function may return 4. Thus, we will be addressing the array cell 
joining_table[...][4] in this case, which is illegal because an array overrun will occur. 
Identical conditions 
void Node::setPageType(const QString& t) 
{ 
if ((t == "API") || (t == "api")) 
pageType_ = ApiPage; 
else if (t == "howto") 
pageType_ = HowToPage; 
else if (t == "overview") 
pageType_ = OverviewPage; 
else if (t == "tutorial") 
pageType_ = TutorialPage; 
else if (t == "howto") 
pageType_ = HowToPage; 
else if (t == "article") 
pageType_ = ArticlePage; 
else if (t == "example") 
pageType_ = ExamplePage; 
else if (t == "ditamap") 
pageType_ = DitaMapPage; 
} 
PVS-Studio's diagnostic message: V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There 
is a probability of logical error presence. Check lines: 386, 392. node.cpp 386 
The (t == "howto") check is executed twice. I guess one of the checks is not necessary. 
Here are a couple of other similar warnings: 
• V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical 
error presence. Check lines: 188, 195. qmaintainingreader_tpl_p.h 188
• V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical 
error presence. Check lines: 299, 303. mfmetadatacontrol.cpp 299 
Identical branches are executed 
void 
QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered( 
const QBluetoothDeviceInfo &info) 
{ 
if(mode == QBluetoothServiceDiscoveryAgent::FullDiscovery) { 
for(int i = 0; i < discoveredDevices.count(); i++){ 
if(discoveredDevices.at(i).address() == info.address()){ 
discoveredDevices.removeAt(i); 
} 
} 
discoveredDevices.prepend(info); 
} 
else { 
for(int i = 0; i < discoveredDevices.count(); i++){ 
if(discoveredDevices.at(i).address() == info.address()){ 
discoveredDevices.removeAt(i); 
} 
} 
discoveredDevices.prepend(info); 
} 
} 
PVS-Studio's diagnostic message: V523 The 'then' statement is equivalent to the 'else' statement. 
qbluetoothservicediscoveryagent.cpp 402 
Regardless of the condition, one and the same code branch is executed. 
Other similar defects: pcre_exec.c 5577, ditaxmlgenerator.cpp 1722, htmlgenerator.cpp 388.
Inherited errors 
Qt employs a few third-party libraries. Those also contain errors, therefore they can be said to belong to 
Qt as well. I decided not to describe them in the article, but I should mention them at least. 
I didn't study the reports for the libraries attentively, but I have noted down some bugs: qt-3rdparty.txt. 
Note. Don't assume, however, that I was attentively studying bugs from Qt instead. The project is pretty 
large and even a superficial analysis was enough to collect examples for this article. 
Conclusions 
PVS-Studio is an excellent, powerful analyzer capable of catching bugs even in high-quality and cleaned 
up projects such as the Qt framework. 
It can help a developer team save huge amounts of time by revealing many bugs at the earliest 
development stage. With the incremental analysis mode enabled, errors will be detected immediately 
after compilation. 
References 
1. We regularly check open-source projects. For example: Tor, Chromium, Clang, Firebird, OpenCV. 
All those interested are welcome: "Updatable List of Open-Source Projects Checked with PVS-Studio". 
2. Here you can download the PVS-Studio trial version. For a start you are given 20 clicks to 
navigate through the diagnostic messages. After submitting your personal information, you are 
granted 200 more clicks. 
3. Things are much simpler with the lightweight CppCat analyzer. This tool is an excellent solution 
for small teams and single developers. The trial version is fully functional for 7 days. The license 
costs $250 and can be renewed at $200. We also offer discounts for purchasing several copies at 
once.

More Related Content

What's hot

PVS-Studio features overview (2020)
PVS-Studio features overview (2020)PVS-Studio features overview (2020)
PVS-Studio features overview (2020)
Andrey Karpov
 
Documenting Bugs in Doxygen
Documenting Bugs in DoxygenDocumenting Bugs in Doxygen
Documenting Bugs in Doxygen
PVS-Studio
 
Going On with the Check of Geant4
Going On with the Check of Geant4Going On with the Check of Geant4
Going On with the Check of Geant4
Andrey Karpov
 
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics EditorWaiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
PVS-Studio
 
How to Improve Visual C++ 2017 Libraries Using PVS-Studio
How to Improve Visual C++ 2017 Libraries Using PVS-StudioHow to Improve Visual C++ 2017 Libraries Using PVS-Studio
How to Improve Visual C++ 2017 Libraries Using PVS-Studio
PVS-Studio
 
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code AnalyzerRechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
Andrey Karpov
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
PVS-Studio
 
How to avoid bugs using modern C++
How to avoid bugs using modern C++How to avoid bugs using modern C++
How to avoid bugs using modern C++
PVS-Studio
 
Linux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLiteLinux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLite
PVS-Studio
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
Andrey Karpov
 
PVS-Studio for Visual C++
PVS-Studio for Visual C++PVS-Studio for Visual C++
PVS-Studio for Visual C++
Andrey Karpov
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-Studio
PVS-Studio
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
PVS-Studio
 
Dusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind projectDusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind project
PVS-Studio
 
On technology transfer: experience from the CARP project... and beyond
On technology transfer: experience from the CARP project... and beyondOn technology transfer: experience from the CARP project... and beyond
On technology transfer: experience from the CARP project... and beyond
dividiti
 
64-Bit Code in 2015: New in the Diagnostics of Possible Issues
64-Bit Code in 2015: New in the Diagnostics of Possible Issues64-Bit Code in 2015: New in the Diagnostics of Possible Issues
64-Bit Code in 2015: New in the Diagnostics of Possible Issues
PVS-Studio
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Andrey Karpov
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
PVS-Studio
 
Static Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal EngineStatic Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal Engine
Andrey Karpov
 
Comparing PVS-Studio for C# and a built-in Visual Studio analyzer, using the ...
Comparing PVS-Studio for C# and a built-in Visual Studio analyzer, using the ...Comparing PVS-Studio for C# and a built-in Visual Studio analyzer, using the ...
Comparing PVS-Studio for C# and a built-in Visual Studio analyzer, using the ...
Ekaterina Milovidova
 

What's hot (20)

PVS-Studio features overview (2020)
PVS-Studio features overview (2020)PVS-Studio features overview (2020)
PVS-Studio features overview (2020)
 
Documenting Bugs in Doxygen
Documenting Bugs in DoxygenDocumenting Bugs in Doxygen
Documenting Bugs in Doxygen
 
Going On with the Check of Geant4
Going On with the Check of Geant4Going On with the Check of Geant4
Going On with the Check of Geant4
 
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics EditorWaiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
 
How to Improve Visual C++ 2017 Libraries Using PVS-Studio
How to Improve Visual C++ 2017 Libraries Using PVS-StudioHow to Improve Visual C++ 2017 Libraries Using PVS-Studio
How to Improve Visual C++ 2017 Libraries Using PVS-Studio
 
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code AnalyzerRechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
 
How to avoid bugs using modern C++
How to avoid bugs using modern C++How to avoid bugs using modern C++
How to avoid bugs using modern C++
 
Linux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLiteLinux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLite
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
PVS-Studio for Visual C++
PVS-Studio for Visual C++PVS-Studio for Visual C++
PVS-Studio for Visual C++
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-Studio
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
 
Dusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind projectDusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind project
 
On technology transfer: experience from the CARP project... and beyond
On technology transfer: experience from the CARP project... and beyondOn technology transfer: experience from the CARP project... and beyond
On technology transfer: experience from the CARP project... and beyond
 
64-Bit Code in 2015: New in the Diagnostics of Possible Issues
64-Bit Code in 2015: New in the Diagnostics of Possible Issues64-Bit Code in 2015: New in the Diagnostics of Possible Issues
64-Bit Code in 2015: New in the Diagnostics of Possible Issues
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
Static Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal EngineStatic Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal Engine
 
Comparing PVS-Studio for C# and a built-in Visual Studio analyzer, using the ...
Comparing PVS-Studio for C# and a built-in Visual Studio analyzer, using the ...Comparing PVS-Studio for C# and a built-in Visual Studio analyzer, using the ...
Comparing PVS-Studio for C# and a built-in Visual Studio analyzer, using the ...
 

Similar to Checking the Qt 5 Framework

A fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBoxA fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBox
PVS-Studio
 
Re-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportRe-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large report
PVS-Studio
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
PVS-Studio
 
Heading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th CheckHeading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th Check
PVS-Studio
 
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
Andrey Karpov
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-Studio
PVS-Studio
 
Exploring Microoptimizations Using Tizen Code as an Example
Exploring Microoptimizations Using Tizen Code as an ExampleExploring Microoptimizations Using Tizen Code as an Example
Exploring Microoptimizations Using Tizen Code as an Example
PVS-Studio
 
PVS-Studio and static code analysis technique
PVS-Studio and static code analysis techniquePVS-Studio and static code analysis technique
PVS-Studio and static code analysis technique
Andrey Karpov
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition Software
Andrey Karpov
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project Analyzed
PVS-Studio
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
PVS-Studio
 
Александр Куцан: "Static Code Analysis in C++"
Александр Куцан: "Static Code Analysis in C++" Александр Куцан: "Static Code Analysis in C++"
Александр Куцан: "Static Code Analysis in C++"
Anna Shymchenko
 
The CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitThe CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGit
Andrey Karpov
 
I just had to check ICQ project
I just had to check ICQ projectI just had to check ICQ project
I just had to check ICQ project
PVS-Studio
 
Parallel Lint
Parallel LintParallel Lint
Parallel Lint
PVS-Studio
 
maXbox Starter 45 Robotics
maXbox Starter 45 RoboticsmaXbox Starter 45 Robotics
maXbox Starter 45 Robotics
Max Kleiner
 
PVS-Studio in the Clouds: Azure DevOps
PVS-Studio in the Clouds: Azure DevOpsPVS-Studio in the Clouds: Azure DevOps
PVS-Studio in the Clouds: Azure DevOps
Andrey Karpov
 
PVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckPVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd Check
Andrey Karpov
 
Diving into VS 2015 Day2
Diving into VS 2015 Day2Diving into VS 2015 Day2
Diving into VS 2015 Day2
Akhil Mittal
 
Static Analysis: From Getting Started to Integration
Static Analysis: From Getting Started to IntegrationStatic Analysis: From Getting Started to Integration
Static Analysis: From Getting Started to Integration
Andrey Karpov
 

Similar to Checking the Qt 5 Framework (20)

A fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBoxA fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBox
 
Re-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportRe-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large report
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
 
Heading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th CheckHeading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th Check
 
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-Studio
 
Exploring Microoptimizations Using Tizen Code as an Example
Exploring Microoptimizations Using Tizen Code as an ExampleExploring Microoptimizations Using Tizen Code as an Example
Exploring Microoptimizations Using Tizen Code as an Example
 
PVS-Studio and static code analysis technique
PVS-Studio and static code analysis techniquePVS-Studio and static code analysis technique
PVS-Studio and static code analysis technique
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition Software
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project Analyzed
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
Александр Куцан: "Static Code Analysis in C++"
Александр Куцан: "Static Code Analysis in C++" Александр Куцан: "Static Code Analysis in C++"
Александр Куцан: "Static Code Analysis in C++"
 
The CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitThe CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGit
 
I just had to check ICQ project
I just had to check ICQ projectI just had to check ICQ project
I just had to check ICQ project
 
Parallel Lint
Parallel LintParallel Lint
Parallel Lint
 
maXbox Starter 45 Robotics
maXbox Starter 45 RoboticsmaXbox Starter 45 Robotics
maXbox Starter 45 Robotics
 
PVS-Studio in the Clouds: Azure DevOps
PVS-Studio in the Clouds: Azure DevOpsPVS-Studio in the Clouds: Azure DevOps
PVS-Studio in the Clouds: Azure DevOps
 
PVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckPVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd Check
 
Diving into VS 2015 Day2
Diving into VS 2015 Day2Diving into VS 2015 Day2
Diving into VS 2015 Day2
 
Static Analysis: From Getting Started to Integration
Static Analysis: From Getting Started to IntegrationStatic Analysis: From Getting Started to Integration
Static Analysis: From Getting Started to Integration
 

More from Andrey Karpov

60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста
Andrey Karpov
 
60 terrible tips for a C++ developer
60 terrible tips for a C++ developer60 terrible tips for a C++ developer
60 terrible tips for a C++ developer
Andrey Karpov
 
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Andrey Karpov
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
Andrey Karpov
 
PVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature OverviewPVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature Overview
Andrey Karpov
 
PVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибок
Andrey Karpov
 
PVS-Studio в 2021
PVS-Studio в 2021PVS-Studio в 2021
PVS-Studio в 2021
Andrey Karpov
 
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Andrey Karpov
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
Andrey Karpov
 
Does static analysis need machine learning?
Does static analysis need machine learning?Does static analysis need machine learning?
Does static analysis need machine learning?
Andrey Karpov
 
Typical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and JavaTypical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and Java
Andrey Karpov
 
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
Andrey Karpov
 
Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?
Andrey Karpov
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
Andrey Karpov
 
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source SoftwareThe Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
Andrey Karpov
 
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsSafety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Andrey Karpov
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++
Andrey Karpov
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?
Andrey Karpov
 
Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for you
Andrey Karpov
 
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOpsPVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
Andrey Karpov
 

More from Andrey Karpov (20)

60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста
 
60 terrible tips for a C++ developer
60 terrible tips for a C++ developer60 terrible tips for a C++ developer
60 terrible tips for a C++ developer
 
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
 
PVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature OverviewPVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature Overview
 
PVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибок
 
PVS-Studio в 2021
PVS-Studio в 2021PVS-Studio в 2021
PVS-Studio в 2021
 
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
 
Does static analysis need machine learning?
Does static analysis need machine learning?Does static analysis need machine learning?
Does static analysis need machine learning?
 
Typical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and JavaTypical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and Java
 
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
 
Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source SoftwareThe Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
 
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsSafety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?
 
Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for you
 
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOpsPVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
 

Recently uploaded

8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
kalichargn70th171
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
ICS
 
DevOps Consulting Company | Hire DevOps Services
DevOps Consulting Company | Hire DevOps ServicesDevOps Consulting Company | Hire DevOps Services
DevOps Consulting Company | Hire DevOps Services
seospiralmantra
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
dakas1
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
XfilesPro
 
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
The Third Creative Media
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
 
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptxMigration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
ervikas4
 
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptxOperational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
sandeepmenon62
 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
Yara Milbes
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
Alina Yurenko
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Peter Caitens
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
Tier1 app
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
Patrick Weigel
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
Peter Muessig
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
ShulagnaSarkar2
 

Recently uploaded (20)

8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
 
DevOps Consulting Company | Hire DevOps Services
DevOps Consulting Company | Hire DevOps ServicesDevOps Consulting Company | Hire DevOps Services
DevOps Consulting Company | Hire DevOps Services
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
 
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
 
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptxMigration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
 
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptxOperational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
 

Checking the Qt 5 Framework

  • 1. Checking the Qt 5 Framework Author: Andrey Karpov Date: 18.04.2014 Static code analysis tools can help developers eliminate numbers of bugs as early as at the coding stage. With their help you can, for example, quickly catch and fix any typos. Well, some programmers are sincerely sure they never make typos and silly mistakes. But they are wrong; everyone makes mistakes. This article is a good evidence of that. Typos can be found even in high-quality and well tested projects such as Qt. Qt Qt is a cross-platform application framework that is widely used for developing application software with a graphical user interface (GUI) (in which cases Qt is classified as a widget toolkit), and also used for developing non-GUI programs such as command-line tools and consoles for servers. Qt uses standard C++ but makes extensive use of a special code generator (called the Meta Object Compiler, or moc) together with several macros to enrich the language. Qt can also be used in several other programming languages via language bindings. It runs on the major desktop platforms and some of the mobile platforms. It has extensive internationalization support. Non-GUI features include SQL database access, XML parsing, thread management, network support, and a unified cross-platform application programming interface (API) for file handling. [the source: Wikipedia] Links: • Wikipedia: Qt; • The official website: Qt Project; • The article about Qt 4.7.3's check in 2011. This time we were dealing with Qt 5.2.1. Analysis was done with the PVS-Studio 5.15 analyzer. Please note that PVS-Studio managed to detect bugs despite that the Qt project had been checked before by the Klocwork and Coverity analyzers. I don't know how regularly the project's authors use these tools, but Klocwork and Coverity are mentioned in the bugtracker and ChangeLog-xxx files. I also saw Qt mentioned to be regularly checked with PC-lint.
  • 2. Specifics of the Qt project's analysis Just for a change, we decided to check Qt using a new mechanism recently introduced in PVS-Studio Standalone. Nobody knows of this mechanism yet, so we will remind you about it from time to time in our next articles. Well, what is that mysterious and wonderful mechanism, after all? In certain cases, you may have a difficult time trying to check a project with PVS-Studio - these are the cases when the project is built with nmake and the like. You need to integrate PVS-Studio into the build, which becomes not an easy thing to do. To say the least, quickly trying and making up an opinion about the tool will become impossible. But now PVS-Studio has acquired a new mode which makes it much simpler to work with such projects. The analyzer has learned how to trace compilation parameters and collect all the necessary information for analysis. You just need to tell the analyzer when to start monitoring compiler calls and when to stop it. Compilation monitoring can be controlled both from the GUI application and the command line. To find out more about how it all works and how to use this mode, see the following article: Evgeniy Ryzhkov. PVS-Studio Now Supports Any Build System under Windows and Any Compiler. Easy and Right Out of the Box. It describes the process of checking the Qt project with the monitoring mode launched from the command line. Do read it please to avoid any misconceptions. For example, you should keep in mind that you can't code while project compilation is being monitored: if you compile files from another project, the analyzer will collect the information about these files and check them too. It will result in the analysis report including extraneous messages, the relevant and irrelevant warnings all mixed in one pile. Analysis results My general opinion of Qt's code is this: It is pretty high-quality and is almost free of bugs related to dangerous specifics of the C++ language. On the other hand, it does have quite a lot of ordinary typos. This article is a good illustration of the thesis that every developer makes typos, however skillful he is. Static code analysis has always been and will be topical and useful. Suppose the analyzer has found 10 typos with a one-time check. So it could have prevented hundreds or thousands of bugs by now if it had been used regularly. That makes an enormous amount of time that could have been saved. Therefore it is much more profitable to detect an error right after it has been made than at the stage of code debugging or after user complaints.
  • 3. Welcome to a wondrous world of typos Typo No.1 bool QWindowsUser32DLL::initTouch() { QSystemLibrary library(QStringLiteral("user32"));
  • 4. registerTouchWindow = ....; unregisterTouchWindow = ....; getTouchInputInfo = ....; closeTouchInputHandle = ....; return registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && getTouchInputInfo; } PVS-Studio's diagnostic message: V501 There are identical sub-expressions 'getTouchInputInfo' to the left and to the right of the '&&' operator. qwindowscontext.cpp 216 Values are assigned to four variables, and all the four must be checked. But only 3 are actually checked because of a typo. In the last line, 'closeTouchInputHandle' should be written instead of 'getTouchInputInfo'. Typo No.2 QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(....) { .... int iw = gm.width.toInt(); int ih = gm.height.toInt(); if (iw <= 0 || iw <= 0) return 0; .... } PVS-Studio's diagnostic message: V501 There are identical sub-expressions to the left and to the right of the '||' operator: iw <= 0 || iw <= 0 qwindowsfontengine.cpp 1095 The check of the height parameter stored in the 'ih' variable is missing. Typos No.3, No.4
  • 5. This error was found inside tests. A nice example of how static analysis complements unit tests. To find out more on this topic, see the article: "How to complement TDD with static analysis". inline bool qCompare(QImage const &t1, QImage const &t2, ....) { .... if (t1.width() != t2.width() || t2.height() != t2.height()) { .... } PVS-Studio's diagnostic message: V501 There are identical sub-expressions to the left and to the right of the '!=' operator: t2.height() != t2.height() qtest_gui.h 101 The function to compare two images is incorrectly comparing their heights. Or rather, it doesn't compare them at all. This bug was multiplied through the Copy-Paste method. The same comparison can be found a bit farther in the code in the same file (line 135). Typo No.5 I apologize for the ugly code formatting - the lines were too lengthy. void QXmlSimpleReader::setFeature( const QString& name, bool enable) { .... } else if ( name == QLatin1String( "http://trolltech.com/xml/features/report-start-end-entity") || name == QLatin1String( "http://trolltech.com/xml/features/report-start-end-entity")) { .... } PVS-Studio's diagnostic message: V501 There are identical sub-expressions to the left and to the right of the '||' operator. qxml.cpp 3249 The 'name' variable is compared to one and the same string twice. A bit earlier in the code, a similar comparison can be found where a variable is compared with the following two strings: • http://trolltech.com/xml/features/report-whitespace-only-CharData
  • 6. • http://qt-project.org/xml/features/report-whitespace-only-CharData By analogy, you can conclude that the 'name' variable in the fragment we are discussing should have been compared with the following strings: • http://trolltech.com/xml/features/report-start-end-entity • http://qt-project.org/xml/features/report-start-end-entity Typos No.6, No.7, No.8, No.9 QString DayTimeDuration::stringValue() const { .... if(!m_hours && !m_minutes && !m_seconds && !m_seconds) .... } PVS-Studio's diagnostic message: V501 There are identical sub-expressions '!m_seconds' to the left and to the right of the '&&' operator. qdaytimeduration.cpp 148 The programmer forgot about milliseconds. Milliseconds are stored in the 'm_mseconds' variable. The check should look like this: if(!m_hours && !m_minutes && !m_seconds && !m_mseconds) There are similar mistakes with milliseconds in three other fragments: • qdaytimeduration.cpp 170 • qduration.cpp 167 • qduration.cpp 189 Typo No.10 QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData( QV4::CallContext *ctx) { .... qreal x = ctx->callData->args[0].toNumber(); qreal y = ctx->callData->args[1].toNumber(); qreal w = ctx->callData->args[2].toNumber(); qreal h = ctx->callData->args[3].toNumber(); if (!qIsFinite(x) || !qIsFinite(y) ||
  • 7. !qIsFinite(w) || !qIsFinite(w)) .... } PVS-Studio's diagnostic message: V501 There are identical sub-expressions '!qIsFinite(w)' to the left and to the right of the '||' operator. qquickcontext2d.cpp 3305 A check of the 'h' variable is missing. The 'w' variable is checked twice instead. Typo No.11 AtomicComparator::ComparisonResult IntegerComparator::compare(const Item &o1, const AtomicComparator::Operator, const Item &o2) const { const Numeric *const num1 = o1.as<Numeric>(); const Numeric *const num2 = o1.as<Numeric>(); if(num1->isSigned() || num2->isSigned()) .... } V656 Variables 'num1', 'num2' are initialized through the call to the same function. It's probably an error or un-optimized code. Consider inspecting the 'o1.as < Numeric > ()' expression. Check lines: 220, 221. qatomiccomparators.cpp 221 The variables 'num1' and 'num2' are initialized to one and the same value. Then both the variables are checked, and that is strange: it would be enough to check only one variable. The 'num2' variable was most likely meant to be initialized to an expression with the 'o2' argument: const Numeric *const num1 = o1.as<Numeric>(); const Numeric *const num2 = o2.as<Numeric>(); Typo No.12 void Atlas::uploadBgra(Texture *texture) { const QRect &r = texture->atlasSubRect(); QImage image = texture->image();
  • 8. if (image.format() != QImage::Format_ARGB32_Premultiplied || image.format() != QImage::Format_RGB32) { .... } V547 Expression is always true. Probably the '&&' operator should be used here. qsgatlastexture.cpp 271 The condition in this code is meaningless as it is always true. Here you are a simplified sample to make it clearer: int a = ...; if (a != 1 || a != 2) The variable will always be not equal to something. I can't say for sure what exactly the correct code should look like. It may be like this: if (image.format() == QImage::Format_ARGB32_Premultiplied || image.format() == QImage::Format_RGB32) { or this: if (image.format() != QImage::Format_ARGB32_Premultiplied && image.format() != QImage::Format_RGB32) { Typo No.13 void QDeclarativeStateGroupPrivate::setCurrentStateInternal( const QString &state, bool ignoreTrans) { .... QDeclarativeTransition *transition = (ignoreTrans || ignoreTrans) ? 0 : findTransition(currentState, state); .... } PVS-Studio's diagnostic message: V501 There are identical sub-expressions to the left and to the right of the '||' operator: ignoreTrans || ignoreTrans qdeclarativestategroup.cpp 442
  • 9. Something is wrong with this code. I can't figure out how exactly the programmer meant to implement the check. Typo No.14 QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(....) { .... if (repetition == QStringLiteral("repeat") || repetition.isEmpty()) { pattern->patternRepeatX = true; pattern->patternRepeatY = true; } else if (repetition == QStringLiteral("repeat-x")) { pattern->patternRepeatX = true; } else if (repetition == QStringLiteral("repeat-y")) { pattern->patternRepeatY = true; } else if (repetition == QStringLiteral("no-repeat")) { pattern->patternRepeatY = false; pattern->patternRepeatY = false; } else { //TODO: exception: SYNTAX_ERR } .... } PVS-Studio's diagnostic message: V519 The 'pattern->patternRepeatY' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1775, 1776. qquickcontext2d.cpp 1776 The 'patternRepeatY' variable is assigned values twice on end: pattern->patternRepeatY = false; pattern->patternRepeatY = false; I guess the correct code should look as follows: } else if (repetition == QStringLiteral("no-repeat")) {
  • 10. pattern->patternRepeatX = false; pattern->patternRepeatY = false; } else { Misuse of the C++ language As I've already said, most bugs in this project are ordinary typos. There are almost no errors related to misuse of the C++ language. However, the analyzer has caught a couple of these. A nice error related to operation priorities bool QConfFileSettingsPrivate::readIniLine(....) { .... char ch; while (i < dataLen && ((ch = data.at(i) != 'n') && ch != 'r')) ++i; .... } V593 Consider reviewing the expression of the 'A = B != C' kind. The expression is calculated as following: 'A = (B != C)'. qsettings.cpp 1702
  • 11. The loop is designed to find the end of a string. The characters 'n' or 'r' are used as end-of-string indicators. Inside the condition, a character must be taken and compared against 'n' and 'r'. The error occurs because the '!=' operator's priority is higher than that of the '=' operator. Because of this, the 'true' or 'false' value is written instead of the character code into the 'ch' variable. It makes the 'r' comparison meaningless. Let's arrange parentheses to make the error clearer: while (i < dataLen && ((ch = (data.at(i) != 'n')) && ch != 'r')) Because of the mistake, it is only the 'n' character that is treated as an end-of-string indicator. The function won't work correctly for strings ending with 'r'. The fixed code should look as follows: while (i < dataLen && (ch = data.at(i)) != 'n' && ch != 'r') Loss of Accuracy bool QWindowsTabletSupport::translateTabletPacketEvent() { .... const double radAzim = (packet.pkOrientation.orAzimuth / 10) * (M_PI / 180); .... } V636 The 'packet.pkOrientation.orAzimuth / 10' expression was implicitly casted from 'int' type to 'double' type. Consider utilizing an explicit type cast to avoid the loss of a fractional part. An example: double A = (double)(X) / Y;. qwindowstabletsupport.cpp 467 The 'packet.pkOrientation.orAzimuth' variable is of the 'int' type. This integer variable is divided by 10. What is suspicious about this is that the quotient is then used together with values of the 'double' type. The final result is also saved into a variable of the 'double' type. Such integer division is not always an error. Perhaps this code is written just the way the programmer intended. But practice shows that it is more often than not a mistake causing accuracy loss. Suppose, for instance, that the 'packet.pkOrientation.orAzimuth' variable equals 55. Then the calculation result will be: (55 / 10) * (3.14159... / 180) = 5 * 0,01745... = 0,087266...
  • 12. The accuracy of these calculations can be significantly improved by just declaring the 10 constant as of the double type: "(packet.pkOrientation.orAzimuth / 10.0) * (M_PI / 180)". The result will then be: (55 / 10.0) * (3.14159... / 180) = 5.5 * 0,01745... = 0,095993... Accuracy losses like that often happen because of programmers being careless about expressions where different types are used together. It is also due to this carelessness that many 64-bit errors occur (see mixed arithmetic). The analyzer has found 51 more suspicious cases of integer division. Some of them may prove less accurate than the programmer wanted them to be. I've collected the corresponding diagnostic messages in a separate list: qt-v636.txt. Meaningless pointer checks It has been for a long time now that checking a pointer for being null doesn't make any sense when the 'new' operator is used to allocate memory. Nowadays, it throws an exception when it fails to allocate memory. Of course, you can make the 'new' operator return 0, but we are not speaking of these cases now. However, programmers sometimes forget about that and write meaningless checks in their code. HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone( IEnumVARIANT **ppEnum) { QWindowsEnumerate *penum = 0; *ppEnum = 0; penum = new QWindowsEnumerate(array); if (!penum) return E_OUTOFMEMORY; .... } PVS-Studio's diagnostic message: V668 There is no sense in testing the 'penum' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. qwindowsmsaaaccessible.cpp 141 There are some more checks like that in the project: main.cpp 127, qaudiodevicefactory.cpp 236, qaudiodevicefactory.cpp 263, qaudiobuffer.cpp 488, mfvideorenderercontrol.cpp 143, mfvideorenderercontrol.cpp 158, mfvideorenderercontrol.cpp 1193, mfvideorenderercontrol.cpp 1199, qaxserverbase.cpp 1006, positionpollfactory.cpp 60.
  • 13. The dark side There are two code fragments in the Qt project about which I can't say for sure if they are errors or not as I'm not familiar with the project architecture and its implementation specifics. But even if they don't have errors, they certainly belong to the dark side of the C++ programming practice. class Q_CORE_EXPORT QObject { .... virtual ~QObject(); virtual bool event(QEvent *); virtual bool eventFilter(QObject *, QEvent *); .... }; QObject *QQmlVME::run(....) { .... QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData)); ::memset(static_cast<void *>(o), 0,
  • 14. instr.typeSize + sizeof(QQmlData)); .... } PVS-Studio's diagnostic message: V598 The 'memset' function is used to nullify the fields of 'QObject' class. Virtual method table will be damaged by this. qqmlvme.cpp 658 The QObject class has virtual functions, which means the object stores a pointer to a virtual methods table. I don't find it a good idea to implement such objects through the memset() function. One more message of that kind: V598 The 'memset' function is used to nullify the fields of 'QObject' class. Virtual method table will be damaged by this. qdeclarativevme.cpp 286 Null pointer dereferencing I guess these errors could be classified as typos, but I like to single them out into a separate group. It makes them look somewhat more somber and serious. Note. Bug classification is pretty relative; many errors can be usually classified as a typo, a vulnerability, an array overrun, and so on. But let's get back to null pointers. A typo leading to null pointer dereferencing QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed( QV4::Managed *m, uint index, bool *hasProperty) { .... if (!m) return m->engine()->currentContext()->throwTypeError(); .... } PVS-Studio's diagnostic message: V522 Dereferencing of the null pointer 'm' might take place. qquickcontext2d.cpp 3169 I'm sure the '!' operator is unnecessary here. It's an ordinary typo leading to a serious bug. Null pointer dereferencing in an error handler void QDocIndexFiles::readIndexSection(....) { .... DocNode* dn = qdb_->findGroup(groupNames[i]);
  • 15. if (dn) { dn->addMember(node); } else { .... qDebug() << "DID NOT FIND GROUP:" << dn->name() << "for:" << node->name(); } .... } PVS-Studio's diagnostic message: V522 Dereferencing of the null pointer 'dn' might take place. qdocindexfiles.cpp 539 If an error occurs, the program must print an error message trying to take the name from a nonexistent object: dn->name(). 82 potential null pointer dereferencing errors Most project (and Qt is no exception) have null pointer handling issues. The check is often done after the pointer has been used. It's not always an error; there are cases when the pointer just can never be null. But anyway, such fragments need to be attentively checked and refactored. Even if there is no error, an excess pointer check confuses the programmer reading the code. Have a look at one dangerous code sample: static int gray_raster_render(....) { const QT_FT_Outline* outline = (const QT_FT_Outline*)params->source; .... /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return 0;
  • 16. if ( !outline || !outline->contours || !outline->points ) return ErrRaster_Invalid_Outline; .... } PVS-Studio's diagnostic message: V595 The 'outline' pointer was utilized before it was verified against nullptr. Check lines: 1746, 1749. qgrayraster.c 1746 I guess the error must have appeared when the programmer was trying to optimize the gray_raster_render() function. It seems that the following lines were added later into an already complete function code: /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return 0; The trouble is that the 'outline' pointer may be null, but the necessary check is written after that fragment. The analyzer has found 81 more potential issues like that. Here is a complete list of them: qt-v595.txt. Questions without answers There are strange code fragments about whose origin and the programmer's intentions about them you can't be sure. They may be typos or incomplete code or unsuccessful refactoring - whatever. Double check QWindowsFontEngine::~QWindowsFontEngine() { .... if (QWindowsContext::verboseFonts) if (QWindowsContext::verboseFonts) qDebug("%s: font='%s", __FUNCTION__, qPrintable(_name)); ....
  • 17. } PVS-Studio's diagnostic message: V571 Recurring check. The 'if (QWindowsContext::verboseFonts)' condition was already verified in line 369. qwindowsfontengine.cpp 370 What's the use checking one and the same thing twice? One of the checks is probably excess; or something else was meant to be checked. Double assignment void Moc::parse() { .... index = def.begin + 1; namespaceList += def; index = rewind; .... } PVS-Studio's diagnostic message: V519 The 'index' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 568, 570. moc.cpp 570 Why different values are assigned to the 'index' variable? There are a few more similar strange code fragments: • V519 The 'exitCode' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 807, 815. qprocess.cpp 815 • V519 The 'detecting' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 163, 164. qhoversensorgesturerecognizer.cpp 164 • V519 The 'increaseCount' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 185, 186. qtwistsensorgesturerecognizer.cpp 186 Suspecting a missing 'break' operator bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) { .... switch (key) { case Qt::Key_Enter: case Qt::Key_Return: doneCompletion();
  • 18. consumed = true; case Qt::Key_Escape: editor->setFocus(); popup->hide(); consumed = true; case Qt::Key_Up: case Qt::Key_Down: case Qt::Key_Home: case Qt::Key_End: case Qt::Key_PageUp: case Qt::Key_PageDown: break; .... } PVS-Studio's diagnostic message: V519 The 'consumed' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 110, 115. googlesuggest.cpp 115 So is the break operator missing here or not? The analyzer found it strange that the 'consumed' variable was assigned the 'true' value twice on end. It suggests a missing break operator, but I'm not sure. It may be just that the first assignment should be removed: "consumed = true;". Suspecting an excess 'break' operator bool QHelpGenerator::registerVirtualFolder(....) { .... while (d->query->next()) { d->namespaceId = d->query->value(0).toInt(); break; } ....
  • 19. } PVS-Studio's diagnostic message: V612 An unconditional 'break' within a loop. qhelpgenerator.cpp 429 Was the 'break' operator really meant to terminate the loop right away? One more fragment of that kind can be found here: qhelpgenerator.cpp 642 Miscellaneous Be patient: there's not much left, just a handful of diverse errors. Incorrect use of the toLower() function int main(int argc, char **argv) { .... QByteArray arg(argv[a]); .... arg = arg.mid(1); arg.toLower(); if (arg == "o") .... } PVS-Studio's diagnostic message: V530 The return value of function 'toLower' is required to be utilized. main.cpp 72 The 'toLower()' function doesn't change the object - it returns a copy of an object that will store lower case characters. One more defect: V530 The return value of function 'toLower' is required to be utilized. main.cpp 1522 Array index out of bounds It's a complicated issue, so please be attentive. There is an enum type in the code: typedef enum { JNone, JCausing, JDual, JRight,
  • 20. JTransparent } Joining; Note that JTransparent == 4 and keep that in mind. Now let's examine the getNkoJoining() function: static Joining getNkoJoining(unsigned short uc) { if (uc < 0x7ca) return JNone; if (uc <= 0x7ea) return JDual; if (uc <= 0x7f3) return JTransparent; if (uc <= 0x7f9) return JNone; if (uc == 0x7fa) return JCausing; return JNone; } What matters to us is that this function may return 'JTransparent', i.e. the function may return 4. There is also a two-dimensional array 'joining_table': static const JoiningPair joining_table[5][4] = { .... }; And here's the piece of code itself where the error may occur: static void getNkoProperties(....) { .... Joining j = getNkoJoining(chars[0]); ArabicShape shape = joining_table[XIsolated][j].form2; .... }
  • 21. PVS-Studio's diagnostic message: V557 Array overrun is possible. The value of 'j' index could reach 4. harfbuzz-arabic.c 516 As we remember, the getNkoJoining() function may return 4. Thus, we will be addressing the array cell joining_table[...][4] in this case, which is illegal because an array overrun will occur. Identical conditions void Node::setPageType(const QString& t) { if ((t == "API") || (t == "api")) pageType_ = ApiPage; else if (t == "howto") pageType_ = HowToPage; else if (t == "overview") pageType_ = OverviewPage; else if (t == "tutorial") pageType_ = TutorialPage; else if (t == "howto") pageType_ = HowToPage; else if (t == "article") pageType_ = ArticlePage; else if (t == "example") pageType_ = ExamplePage; else if (t == "ditamap") pageType_ = DitaMapPage; } PVS-Studio's diagnostic message: V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 386, 392. node.cpp 386 The (t == "howto") check is executed twice. I guess one of the checks is not necessary. Here are a couple of other similar warnings: • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 188, 195. qmaintainingreader_tpl_p.h 188
  • 22. • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 299, 303. mfmetadatacontrol.cpp 299 Identical branches are executed void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered( const QBluetoothDeviceInfo &info) { if(mode == QBluetoothServiceDiscoveryAgent::FullDiscovery) { for(int i = 0; i < discoveredDevices.count(); i++){ if(discoveredDevices.at(i).address() == info.address()){ discoveredDevices.removeAt(i); } } discoveredDevices.prepend(info); } else { for(int i = 0; i < discoveredDevices.count(); i++){ if(discoveredDevices.at(i).address() == info.address()){ discoveredDevices.removeAt(i); } } discoveredDevices.prepend(info); } } PVS-Studio's diagnostic message: V523 The 'then' statement is equivalent to the 'else' statement. qbluetoothservicediscoveryagent.cpp 402 Regardless of the condition, one and the same code branch is executed. Other similar defects: pcre_exec.c 5577, ditaxmlgenerator.cpp 1722, htmlgenerator.cpp 388.
  • 23. Inherited errors Qt employs a few third-party libraries. Those also contain errors, therefore they can be said to belong to Qt as well. I decided not to describe them in the article, but I should mention them at least. I didn't study the reports for the libraries attentively, but I have noted down some bugs: qt-3rdparty.txt. Note. Don't assume, however, that I was attentively studying bugs from Qt instead. The project is pretty large and even a superficial analysis was enough to collect examples for this article. Conclusions PVS-Studio is an excellent, powerful analyzer capable of catching bugs even in high-quality and cleaned up projects such as the Qt framework. It can help a developer team save huge amounts of time by revealing many bugs at the earliest development stage. With the incremental analysis mode enabled, errors will be detected immediately after compilation. References 1. We regularly check open-source projects. For example: Tor, Chromium, Clang, Firebird, OpenCV. All those interested are welcome: "Updatable List of Open-Source Projects Checked with PVS-Studio". 2. Here you can download the PVS-Studio trial version. For a start you are given 20 clicks to navigate through the diagnostic messages. After submitting your personal information, you are granted 200 more clicks. 3. Things are much simpler with the lightweight CppCat analyzer. This tool is an excellent solution for small teams and single developers. The trial version is fully functional for 7 days. The license costs $250 and can be renewed at $200. We also offer discounts for purchasing several copies at once.