SlideShare ist ein Scribd-Unternehmen logo
1 von 37
Downloaden Sie, um offline zu lesen
Re-checking	the	ReactOS	project	-	a	large	
report
Author: Andrey Karpov
Date: 02.04.2013
The ReactOS project is rapidly developing. One of the developers participating in this project suggested
that we re-analyzed the source code, as the code base is growing fast. We were glad to do that. We like
this project, and we'll be happy if this article helps the developers to eliminate some bugs. Analysis was
performed with the PVS-Studio 5.02 code analyzer.
Let me remind you what ReactOS is. This is a free and open-source operating system based on the
Windows NT architecture principles. The system was developed from scratch and therefore is not based
on Linux and doesn't have anything in common with the UNIX architecture. The main aim of the ReactOS
project is to create a Windows binary-compatible operating system that would allow users to execute
Windows-compatible applications and drivers as if they were executed in Windows itself.
We analyzed this project once some time ago. The results of that check were described in the post "PVS-
Studio: analyzing ReactOS's code". After re-checking the project, we have found a lot of new bugs and
suspicious code fragments. This fact proves very well that static code analysis should be performed
regularly, not occasionally! Doing it that way will help you to significantly reduce the number of errors
at the stage of coding already, which means that errors detected will take much less time to eliminate.
Note that the article describes far not all the fragments worth considering. ReactOS has become a big
boy now: the solution includes 803 projects. For those, the PVS-Studio analyzer has generated a good
deal of general warnings:
1. 1320 first-level warnings;
2. 814 second-level warnings;
3. 2753 third-level warnings.
It was natural that I didn't find enough courage just to sit down and study all these warnings in detail.
So, I'll only point at the most suspicious fragments that caught my glance. There certainly must be other
warnings that should be examined as attentively; and there are also diagnostics related to 64-bit errors
and micro-optimizations which I didn't examine at all.
The PVS-Studio demo version will be insufficient to examine all the 4887 warnings. However, we are
friendly to open-source projects: if the ReactOS developers ask us, we'll give them our tool for free for a
while.
Misprints
PVS-Studio is good at detecting various misprints. We may call it its "hobbyhorse". This is a very useful
function, as misprints inevitably exist in any project. Let's see what ReactOS has to show us in this field.
Variable overwrite
NTSTATUS NTAPI CreateCdRomDeviceObject(....)
{
....
cddata->XAFlags &= ~XA_USE_6_BYTE;
cddata->XAFlags = XA_USE_READ_CD | XA_USE_10_BYTE;
....
}
V519 The 'cddata->XAFlags' variable is assigned values twice successively. Perhaps this is a mistake.
Check lines: 1290, 1291. cdrom.c 1291
The assignment operation overwrites the previous value of the XAFlags term. The following text should
be most likely written instead: cddata->XAFlags |= XA_USE_READ_CD | XA_USE_10_BYTE;. But of course
I can't be quite sure, as I don't know the logic of this code.
Repetition in condition
void util_blit_pixels_writemask(....)
{
....
if ((src_tex == dst_surface->texture &&
dst_surface->u.tex.level == src_level &&
dst_surface->u.tex.first_layer == srcZ0) ||
(src_tex->target != PIPE_TEXTURE_2D &&
src_tex->target != PIPE_TEXTURE_2D &&
src_tex->target != PIPE_TEXTURE_RECT))
....
}
V501 There are identical sub-expressions 'src_tex->target != PIPE_TEXTURE_2D' to the left and to the
right of the '&&' operator. u_blit.c 421
The check "src_tex->target != PIPE_TEXTURE_2D" is executed twice. It's another constant that the
'target' term must be compared to for the second time. Otherwise this comparison is unnecessary.
Here's another error of this kind:
static boolean is_legal_int_format_combo(
const struct util_format_description *src,
const struct util_format_description *dst )
{
....
for (i = 0; i < nr; i++) {
/* The signs must match. */
if (src->channel[i].type != src->channel[i].type) {
return FALSE;
}
....
}
V501 There are identical sub-expressions 'src->channel[i].type' to the left and to the right of the '!='
operator. translate_generic.c 776
The correct check seems to be as follows: src->channel[i].type != dst->channel[i].type.
And one more similar error:
static GpStatus draw_poly(....)
{
....
if((i + 2 >= count) ||
!(types[i + 1] & PathPointTypeBezier) ||
!(types[i + 1] & PathPointTypeBezier))
{
ERR("Bad bezier pointsn");
goto end;
}
....
}
V501 There are identical sub-expressions '!(types[i + 1] & PathPointTypeBezier)' to the left and to the
right of the '||' operator. graphics.c 1912
One more:
static inline BOOL is_unc_path(const WCHAR *str) {
return (str[0] == '' && str[0] == '');
}
V501 There are identical sub-expressions to the left and to the right of the '&&' operator: str[0] == ''
&& str[0] == '' uri.c 273
By the way, this particular bug remains unfixed since the previous check. I didn't describe it in the
previous article, although it is included into my error samples base. Don't remember why I didn't
mention it - perhaps I was concerned about not making the article too large. The developers must have
never run PVS-Studio on their project, and the bug has successfully survived inside the code for at least a
couple of years.
One more:
VOID NTAPI UniAtaReadLunConfig(....)
{
if(!LunExt->IdentifyData.SectorsPerTrack ||
!LunExt->IdentifyData.NumberOfCylinders ||
!LunExt->IdentifyData.SectorsPerTrack)
....
}
V501 There are identical sub-expressions '!LunExt->IdentifyData.SectorsPerTrack' to the left and to the
right of the '||' operator. id_init.cpp 1528
The error is quite obvious, I believe. Don't know how to fix it.
Be patient - I have some other twin bugs to show you. And I can't help it... You see, these are very
typical software bugs.
ir_visitor_status
ir_validate::visit_leave(ir_loop *ir)
{
if (ir->counter != NULL) {
if ((ir->from == NULL) || (ir->from == NULL) ||
(ir->increment == NULL)) {
....
}
V501 There are identical sub-expressions to the left and to the right of the '||' operator: (ir->from == 0)
|| (ir->from == 0) ir_validate.cpp 123
One of the "ir->from == 0" comparisons must be replaced with "ir->to == NULL".
The same error, caused through the copy-paste technology, can be found here: V501 There are identical
sub-expressions to the left and to the right of the '||' operator: (ir->from != 0) || (ir->from != 0)
ir_validate.cpp 139
Unnecessary semicolon
We have finally got to another class of misprints - the unnecessary semicolon ';' that spoils everything.
int BlockEnvToEnvironA(void)
{
....
for (envptr--; envptr >= _environ; envptr--);
free(*envptr);
....
}
V529 Odd semicolon ';' after 'for' operator. environ.c 67
Note the ';' character after the 'for' operator. It results in the free() function being called only once,
which leads to memory leaks. It also causes releasing a memory area that wasn't intended to be
released. This is how the incorrect code works in its present state:
free(envptr >= _environ ? _environ[-1] : envptr);
The same semicolons can be found here:
• V529 Odd semicolon ';' after 'for' operator. environ.c 119
• V529 Odd semicolon ';' after 'for' operator. environ.c 171
Incorrect expression
static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(
...., DWORD dwEnabledOptions)
{
....
This->safeopt = dwEnabledOptions & dwEnabledOptions;
return S_OK;
}
V501 There are identical sub-expressions to the left and to the right of the '&' operator:
dwEnabledOptions & dwEnabledOptions jscript.c 905
One of the operands seems to have an incorrectly defined name in the expression.
Here's a misprint that causes the size of a rectangle to be calculated incorrectly.
GpStatus WINGDIPAPI GdipGetRegionBoundsI(....)
{
....
status = GdipGetRegionBounds(region, graphics, &rectf);
if (status == Ok){
rect->X = gdip_round(rectf.X);
rect->Y = gdip_round(rectf.X);
rect->Width = gdip_round(rectf.Width);
rect->Height = gdip_round(rectf.Height);
}
return status;
}
V656 Variables 'rect->X', 'rect->Y' are initialized through the call to the same function. It's probably an
error or un-optimized code. Consider inspecting the 'gdip_round(rectf.X)' expression. Check lines: 718,
719. region.c 719
I'm almost sure that the following code must be written here: "rect->Y = gdip_round(rectf.Y);". If it's not
so, there should be some comment on this.
The following is a code fragment where a variable is assigned to itself:
DWORD WINAPI
DdGetDriverInfo(LPDDHAL_GETDRIVERINFODATA pData)
{
....
pUserColorControl->dwFlags = pUserColorControl->dwFlags;
....
}
V570 The 'pUserColorControl->dwFlags' variable is assigned to itself. gdientry.c 1029
The assignment is meaningless. The expression must be incomplete, or something is messed up. The
same error here:
V570 The 'Irp->IoStatus.Information' variable is assigned to itself. hidclass.c 461
Let's talk about null pointers
If you have a C/C++ application, you have troubles with pointers. This is the price we have to pay for the
language's efficiency. However, C++ and especially C++11 offer a number of ways to avoid handling wild
pointers. But that is a subject to be discussed individually.
Let's see what can be found in ReactOS regarding this kind of bugs.
Null pointer dereferencing
static void acpi_bus_notify (....)
{
struct acpi_device *device = NULL;
....
switch (type) {
....
case ACPI_NOTIFY_EJECT_REQUEST:
DPRINT1("Received EJECT REQUEST "
"notification for device [%s]n",
device->pnp.bus_id);
break;
....
}
}
V522 Dereferencing of the null pointer 'device' might take place. bus.c 762
If the "case ACPI_NOTIFY_EJECT_REQUEST:" branch is chosen in the 'switch' operator, the 'device'
pointer will still be equal to zero at the moment. Dereferencing it in the "device->pnp.bus_id"
expression will have unpleasant consequences.
In the same bad way the 'device' variable is used in some other fragments:
• V522 Dereferencing of the null pointer 'device' might take place. bus.c 768
• V522 Dereferencing of the null pointer 'device' might take place. bus.c 774
• V522 Dereferencing of the null pointer 'device' might take place. bus.c 780
• V522 Dereferencing of the null pointer 'device' might take place. bus.c 786
Here's another code fragment where a variable remains equal to zero by the moment it must be used:
ir_texture *ir_reader::read_texture(s_expression *expr)
{
s_symbol *tag = NULL;
....
} else if (MATCH(expr, other_pattern)) {
op = ir_texture::get_opcode(tag->value());
if (op == -1)
return NULL;
}
....
}
V522 Dereferencing of the null pointer 'tag' might take place. ir_reader.cpp 904
At the moment of calling the value() function, the 'tag' variable will still equal zero. That's no good.
There are some other similar null pointer dereferencing bugs found in ReactOS:
• V522 Dereferencing of the null pointer 's_shadow' might take place. ir_reader.cpp 964
• V522 Dereferencing of the null pointer 'BootSectorInfo' might take place. disksup.c 1750
• V522 Dereferencing of the null pointer 'BootSectorInfo' might take place. disksup.c 1751
• V522 Dereferencing of the null pointer 'BootSectorInfo' might take place. disksup.c 1754
Passing a null pointer into a function
BOOL GetEventCategory(....)
{
....
if (lpMsgBuf)
{
....
}
else
{
wcscpy(CategoryName, (LPCWSTR)lpMsgBuf);
}
....
}
V575 The null pointer is passed into 'wcscpy' function. Inspect the second argument. eventvwr.c 270
The wcscpy() function is called only if the 'lpMsgBuf' variable equals zero. This variable is passed as an
argument into the 'wcscpy' function. It's hooliganism to pass zero into the 'wcscpy' function.
Here, another hooligan is torturing a cat the strstr() function:
VOID WinLdrSetupEms(IN PCHAR BootOptions)
{
PCHAR RedirectPort;
....
if (RedirectPort)
{
....
}
else
{
RedirectPort = strstr(RedirectPort, "usebiossettings");
....
}
V575 The null pointer is passed into 'strstr' function. Inspect the first argument. headless.c 263
The _wcsicmp() function has suffered for company as well:
DWORD ParseReasonCode(LPCWSTR code)
{
LPWSTR tmpPrefix = NULL;
....
for (reasonptr = shutdownReason ; reasonptr->prefix ; reasonptr++)
{
if ((majorCode == reasonptr->major) &&
(minorCode == reasonptr->minor) &&
(_wcsicmp(tmpPrefix, reasonptr->prefix) != 0))
{
return reasonptr->flag;
}
}
....
}
V575 The null pointer is passed into '_wcsicmp' function. Inspect the first argument. misc.c 150
By the time the _wcsicmp() function must be called, the pointer tmpPrefix is still a null pointer.
Dereferencing a possible null pointer
There are very many code fragments where the pointer is first dereferenced and only then is checked
for being a null pointer. It's not always an error. Perhaps the pointer simply cannot be a null pointer, and
the check is just unnecessary. But such code usually appears due to inattention and is incorrect. It works
only until the unhappy pointer suddenly becomes a null pointer through a coincidence.
I will cite only one simple example here:
static BOOL LookupSidInformation(....)
{
....
DomainName = &PolicyAccountDomainInfo->DomainName;
SidNameUse = (PolicyAccountDomainInfo != NULL ?
SidTypeGroup : SidTypeUser);
....
}
V595 The 'PolicyAccountDomainInfo' pointer was utilized before it was verified against nullptr. Check
lines: 254, 257. sidcache.c 254
Look, the 'PolicyAccountDomainInfo' pointer is dereferenced first. And then it is suddenly checked for
being a null pointer. Such a code is usually created as a result of swift refactoring. Variables are starting
to be used when there are not checked yet.
The reason why I'm describing only one error of this kind is that they all look much alike. And also
because they are AWFULLY NUMEROUS. I'm not interested in examining and describing each individual
case. Moreover, it's impossible to include them all into the article - it would then be a reference book
instead. That's why I'll just cite the diagnostic messages for you:
• V595 The 'oldRelations' pointer was utilized before it was verified against nullptr. Check lines:
216, 246. pnp.c 216
• V595 The 'Op->Common.Value.Arg' pointer was utilized before it was verified against nullptr.
Check lines: 531, 554. dswload.c 531
• V595 The 'OutOp' pointer was utilized before it was verified against nullptr. Check lines: 325,
346. dswexec.c 325
• V595 The 'Poll' pointer was utilized before it was verified against nullptr. Check lines: 63, 66.
select.c 63
• V595 The 'pEdit' pointer was utilized before it was verified against nullptr. Check lines: 480, 491.
editstream.c 480
• V595 The 'plpOptions[curStream]' pointer was utilized before it was verified against nullptr.
Check lines: 1629, 1630. api.c 1629
• V595 The 'pThis' pointer was utilized before it was verified against nullptr. Check lines: 454, 461.
atlwin.h 454
• V595 The 'pThis' pointer was utilized before it was verified against nullptr. Check lines: 639, 646.
atlwin.h 639
• V595 The 'DeviceObject' pointer was utilized before it was verified against nullptr. Check lines:
6870, 6877. class.c 6870
• V595 The 'extName' pointer was utilized before it was verified against nullptr. Check lines: 128,
141. assoc.c 128
• V595 The 'FileList' pointer was utilized before it was verified against nullptr. Check lines: 775,
791. filecomp.c 775
• V595 The 'ident' pointer was utilized before it was verified against nullptr. Check lines: 449, 462.
set.c 449
• V595 The 'psp' pointer was utilized before it was verified against nullptr. Check lines: 2705,
2714. propsheet.c 2705
• V595 The 'lpItem' pointer was utilized before it was verified against nullptr. Check lines: 4256,
4269. listview.c 4256
• V595 The 'lpFindInfo' pointer was utilized before it was verified against nullptr. Check lines:
6199, 6203. listview.c 6199
• V595 The 'item' pointer was utilized before it was verified against nullptr. Check lines: 1461,
1463. treeview.c 1461
• V595 The 'file' pointer was utilized before it was verified against nullptr. Check lines: 2799, 2802.
file.c 2799
• V595 The 'context' pointer was utilized before it was verified against nullptr. Check lines: 976,
1006. cryptnet_main.c 976
• V595 The 'advanced' pointer was utilized before it was verified against nullptr. Check lines: 436,
451. main.c 436
• V595 The 'compiland' pointer was utilized before it was verified against nullptr. Check lines: 389,
396. symbol.c 389
• V595 The 'func' pointer was utilized before it was verified against nullptr. Check lines: 468, 471.
symbol.c 468
• V595 The 'compiland' pointer was utilized before it was verified against nullptr. Check lines: 589,
594. symbol.c 589
• V595 The 'pMapper' pointer was utilized before it was verified against nullptr. Check lines: 822,
847. createdevenum.c 822
• V595 The 'psh.phpage' pointer was utilized before it was verified against nullptr. Check lines:
2475, 2494. advprop.c 2475
• V595 The 'DevAdvPropInfo' pointer was utilized before it was verified against nullptr. Check
lines: 2480, 2508. advprop.c 2480
• V595 The 'DeviceID' pointer was utilized before it was verified against nullptr. Check lines: 296,
303. enumdevices.c 296
• V595 The 'DeviceObject' pointer was utilized before it was verified against nullptr. Check lines:
4279, 4284. disk.c 4279
• V595 The 'device->hwbuf' pointer was utilized before it was verified against nullptr. Check lines:
917, 927. mixer.c 917
• V595 The 'PtrNewFileObject' pointer was utilized before it was verified against nullptr. Check
lines: 306, 322. create.c 306
• V595 The 'PtrSourceFCB->FCBName' pointer was utilized before it was verified against nullptr.
Check lines: 2793, 2812. metadata.c 2793
• V595 The 'FileObject' pointer was utilized before it was verified against nullptr. Check lines: 54,
60. fastio.c 54
• V595 The 'FileObject' pointer was utilized before it was verified against nullptr. Check lines: 663,
680. fastio.c 663
• V595 The 'FileObject' pointer was utilized before it was verified against nullptr. Check lines: 733,
749. fastio.c 733
• V595 The 'PtrCCB' pointer was utilized before it was verified against nullptr. Check lines: 1018,
1021. fastio.c 1018
• V595 The 'PtrCCB' pointer was utilized before it was verified against nullptr. Check lines: 1093,
1102. fastio.c 1093
• V595 The 'pData' pointer was utilized before it was verified against nullptr. Check lines: 330,
340. inode.c 330
• V595 The 'ext2_bdl' pointer was utilized before it was verified against nullptr. Check lines: 532,
537. inode.c 532
• V595 The 'ext2_bdl' pointer was utilized before it was verified against nullptr. Check lines: 600,
615. inode.c 600
• V595 The 'IrpContext' pointer was utilized before it was verified against nullptr. Check lines: 922,
925. finfo.c 922
• V595 The 'IrpContext' pointer was utilized before it was verified against nullptr. Check lines: 396,
399. volume.c 396
• V595 The 'rwContext' pointer was utilized before it was verified against nullptr. Check lines: 224,
235. fbtrwr.c 224
• V595 The 'DataSize' pointer was utilized before it was verified against nullptr. Check lines: 695,
699. registry.c 695
• V595 The 'DataSize' pointer was utilized before it was verified against nullptr. Check lines: 733,
737. registry.c 733
• V595 The 'mm' pointer was utilized before it was verified against nullptr. Check lines: 287, 290.
pb_bufmgr_mm.c 287
• V595 The 'pool' pointer was utilized before it was verified against nullptr. Check lines: 315, 320.
pb_bufmgr_pool.c 315
• V595 The 'cache' pointer was utilized before it was verified against nullptr. Check lines: 186,
189. u_cache.c 186
• V595 The 'cache' pointer was utilized before it was verified against nullptr. Check lines: 221,
224. u_cache.c 221
• V595 The 'src' pointer was utilized before it was verified against nullptr. Check lines: 163, 166.
u_surface.c 163
• V595 The 'graphics' pointer was utilized before it was verified against nullptr. Check lines: 2239,
2255. graphics.c 2239
• V595 The 'vlist' pointer was utilized before it was verified against nullptr. Check lines: 69, 73.
trimvertpool.cc 69
• V595 The 'vlist' pointer was utilized before it was verified against nullptr. Check lines: 88, 93.
trimvertpool.cc 88
• V595 The 'LocalItemState' pointer was utilized before it was verified against nullptr. Check lines:
64, 70. parser.c 64
• V595 The 'sd->zone_mgr' pointer was utilized before it was verified against nullptr. Check lines:
246, 249. security.c 246
• V595 The 'entitySet' pointer was utilized before it was verified against nullptr. Check lines: 519,
535. ipstats_reactos.c 519
• V595 The 'disp' pointer was utilized before it was verified against nullptr. Check lines: 509, 515.
jscript.c 509
• V595 The 'a_cBuffer' pointer was utilized before it was verified against nullptr. Check lines: 888,
893. debugger.c 888
• V595 The 'AutomationTableB' pointer was utilized before it was verified against nullptr. Check
lines: 1903, 1905. api.c 1903
• V595 The 'AutomationTableB' pointer was utilized before it was verified against nullptr. Check
lines: 1952, 1954. api.c 1952
• V595 The 'AutomationTableB' pointer was utilized before it was verified against nullptr. Check
lines: 2001, 2003. api.c 2001
• V595 The 'AutomationTableB' pointer was utilized before it was verified against nullptr. Check
lines: 2347, 2350. api.c 2347
• V595 The 'IoStack->FileObject' pointer was utilized before it was verified against nullptr. Check
lines: 611, 622. device.c 611
• V595 The 'Ctx' pointer was utilized before it was verified against nullptr. Check lines: 425, 430.
event.c 425
• V595 The 'BusDeviceExtension' pointer was utilized before it was verified against nullptr. Check
lines: 1388, 1390. swenum.c 1388
• V595 The 'path' pointer was utilized before it was verified against nullptr. Check lines: 3250,
3254. catalog.c 3250
• V595 The 'str2' pointer was utilized before it was verified against nullptr. Check lines: 395, 396.
c14n.c 395
• V595 The 'atts' pointer was utilized before it was verified against nullptr. Check lines: 3763,
3775. htmlparser.c 3763
• V595 The 'ctxt' pointer was utilized before it was verified against nullptr. Check lines: 3674,
3676. htmlparser.c 3674
• V595 The 'ctxt->input' pointer was utilized before it was verified against nullptr. Check lines:
6693, 6697. htmlparser.c 6693
• V595 The 'name' pointer was utilized before it was verified against nullptr. Check lines: 123, 131.
hash.c 123
• V595 The 'ctxt->nsTab' pointer was utilized before it was verified against nullptr. Check lines:
1546, 1553. parser.c 1546
• V595 The 'ctxt->input' pointer was utilized before it was verified against nullptr. Check lines:
6690, 6698. parser.c 6690
• V595 The 'ctxt->input' pointer was utilized before it was verified against nullptr. Check lines:
6750, 6758. parser.c 6750
• V595 The 'atts' pointer was utilized before it was verified against nullptr. Check lines: 8477,
8486. parser.c 8477
• V595 The 'ctxt->input' pointer was utilized before it was verified against nullptr. Check lines:
11113, 11116. parser.c 11113
• V595 The 'ctx->myDoc' pointer was utilized before it was verified against nullptr. Check lines:
12784, 12787. parser.c 12784
• V595 The 'ctxt->myDoc' pointer was utilized before it was verified against nullptr. Check lines:
13341, 13357. parser.c 13341
• V595 The 'oldctxt' pointer was utilized before it was verified against nullptr. Check lines: 13349,
13367. parser.c 13349
• V595 The 'tmp' pointer was utilized before it was verified against nullptr. Check lines: 1536,
1537. relaxng.c 1536
• V595 The 'lib' pointer was utilized before it was verified against nullptr. Check lines: 8598, 8604.
relaxng.c 8598
• V595 The 'ctxt->myDoc' pointer was utilized before it was verified against nullptr. Check lines:
984, 986. sax2.c 984
• V595 The 'ctxt->incTab' pointer was utilized before it was verified against nullptr. Check lines:
392, 400. xinclude.c 392
• V595 The 'href' pointer was utilized before it was verified against nullptr. Check lines: 518, 529.
xinclude.c 518
• V595 The 'ctxt' pointer was utilized before it was verified against nullptr. Check lines: 1129,
1130. xinclude.c 1129
• V595 The 'ctxt->incTab[nr]' pointer was utilized before it was verified against nullptr. Check
lines: 1419, 1428. xinclude.c 1419
• V595 The 'p' pointer was utilized before it was verified against nullptr. Check lines: 586, 589.
xmlmemory.c 586
• V595 The 'node' pointer was utilized before it was verified against nullptr. Check lines: 2819,
2829. xmlschemastypes.c 2819
• V595 The 'attr' pointer was utilized before it was verified against nullptr. Check lines: 2858,
2862. xmlschemas.c 2858
• V595 The 'uses' pointer was utilized before it was verified against nullptr. Check lines: 14498,
14508. xmlschemas.c 14498
• V595 The 'atom->ranges' pointer was utilized before it was verified against nullptr. Check lines:
817, 818. xmlregexp.c 817
• V595 The 'exec->state' pointer was utilized before it was verified against nullptr. Check lines:
4263, 4273. xmlregexp.c 4263
• V595 The 'res' pointer was utilized before it was verified against nullptr. Check lines: 14032,
14054. xpath.c 14032
• V595 The 'msg' pointer was utilized before it was verified against nullptr. Check lines: 361, 363.
rostcp.c 361
• V595 The 'msg' pointer was utilized before it was verified against nullptr. Check lines: 469, 473.
rostcp.c 469
• V595 The 'last_unsent' pointer was utilized before it was verified against nullptr. Check lines:
632, 661. tcp_out.c 632
• V595 The 'att->Renderbuffer' pointer was utilized before it was verified against nullptr. Check
lines: 790, 798. fbobject.c 790
• V595 The 'sub_prims' pointer was utilized before it was verified against nullptr. Check lines: 852,
859. st_draw.c 852
• V595 The 'height' pointer was utilized before it was verified against nullptr. Check lines: 2471,
2474. teximage.c 2471
• V595 The 'WorkItem' pointer was utilized before it was verified against nullptr. Check lines: 745,
753. notify.c 745
• V595 The 'lpErrno' pointer was utilized before it was verified against nullptr. Check lines: 425,
439. dllmain.c 425
• V595 The 'pServiceFailureActions' pointer was utilized before it was verified against nullptr.
Check lines: 175, 184. srvpage.c 175
• V595 The 'This->pITextStoreACP' pointer was utilized before it was verified against nullptr.
Check lines: 143, 147. context.c 143
• V595 The 'sidsize' pointer was utilized before it was verified against nullptr. Check lines: 1998,
2002. registry.c 1998
• V595 The 'locator->pParserCtxt' pointer was utilized before it was verified against nullptr. Check
lines: 2290, 2301. saxreader.c 2290
• V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 100,
101. buffer.c 100
• V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 159,
160. buffer.c 159
• V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 264,
265. buffer.c 264
• V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 275,
276. buffer.c 275
• V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 627,
628. buffer.c 627
• V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 638,
639. buffer.c 638
• V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines:
1249, 1250. buffer.c 1249
• V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 1262,
1263. buffer.c 1262
• V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 1047,
1048. 8390.c 1047
• V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 899,
900. main.c 899
• V595 The 'EnumContext' pointer was utilized before it was verified against nullptr. Check lines:
596, 599. local_group.c 596
• V595 The 'EnumContext' pointer was utilized before it was verified against nullptr. Check lines:
1344, 1347. user.c 1344
• V595 The '* ptr' pointer was utilized before it was verified against nullptr. Check lines: 85, 88.
nbnamecache.c 85
• V595 The 'wki' pointer was utilized before it was verified against nullptr. Check lines: 129, 133.
netid.c 129
• V595 The 'wki' pointer was utilized before it was verified against nullptr. Check lines: 163, 167.
netid.c 163
• V595 The 'wki' pointer was utilized before it was verified against nullptr. Check lines: 299, 302.
netid.c 299
• V595 The 'SafeParams' pointer was utilized before it was verified against nullptr. Check lines:
608, 624. harderr.c 608
• V595 The 'ObjectCreateInfo' pointer was utilized before it was verified against nullptr. Check
lines: 707, 732. oblife.c 707
• V595 The 'ListHead' pointer was utilized before it was verified against nullptr. Check lines: 103,
104. pfnlist.c 103
• V595 The 'ImpersonationInfo' pointer was utilized before it was verified against nullptr. Check
lines: 56, 60. security.c 56
• V595 The 'CapturedPrivileges' pointer was utilized before it was verified against nullptr. Check
lines: 2256, 2277. token.c 2256
• V595 The 'pv' pointer was utilized before it was verified against nullptr. Check lines: 809, 831.
variant.c 809
• V595 The 'result' pointer was utilized before it was verified against nullptr. Check lines: 3394,
3401. variant.c 3394
• V595 The 'result' pointer was utilized before it was verified against nullptr. Check lines: 3585,
3592. variant.c 3585
• V595 The 'pVarOut' pointer was utilized before it was verified against nullptr. Check lines: 5248,
5251. variant.c 5248
• V595 The 'typeInfo' pointer was utilized before it was verified against nullptr. Check lines: 867,
869. typelib.c 867
• V595 The 'subtypeinfo' pointer was utilized before it was verified against nullptr. Check lines:
4960, 4965. typelib.c 4960
• V595 The 'pTLib' pointer was utilized before it was verified against nullptr. Check lines: 7082,
7084. typelib.c 7082
• V595 The 'DeviceObject' pointer was utilized before it was verified against nullptr. Check lines:
612, 624. fdo.c 612
• V595 The 'Package' pointer was utilized before it was verified against nullptr. Check lines: 170,
187. init.c 170
• V595 The 'Package' pointer was utilized before it was verified against nullptr. Check lines: 462,
469. init.c 462
• V595 The 'Adapter' pointer was utilized before it was verified against nullptr. Check lines: 998,
1004. pcnet.c 998
• V595 The 'm_pInterruptSync' pointer was utilized before it was verified against nullptr. Check
lines: 1610, 1627. miniport_dmus.cpp 1610
• V595 The 'DSImpl->dsbuffer' pointer was utilized before it was verified against nullptr. Check
lines: 882, 898. dsoundrender.c 882
• V595 The 'pcFetched' pointer was utilized before it was verified against nullptr. Check lines: 199,
204. enummedia.c 199
• V595 The 'pParser' pointer was utilized before it was verified against nullptr. Check lines: 868,
872. filtermapper.c 868
• V595 The 'pPropBag' pointer was utilized before it was verified against nullptr. Check lines: 920,
928. filtermapper.c 920
• V595 The 'pPropBagCat' pointer was utilized before it was verified against nullptr. Check lines:
1342, 1366. filtermapper.c 1342
• V595 The 'pPropBagCat' pointer was utilized before it was verified against nullptr. Check lines:
784, 797. filtergraph.c 784
• V595 The 'pFM2' pointer was utilized before it was verified against nullptr. Check lines: 644,
654. regsvr.c 644
• V595 The 'pAlloc' pointer was utilized before it was verified against nullptr. Check lines: 900,
905. pin.c 900
• V595 The 'pMemConnected' pointer was utilized before it was verified against nullptr. Check
lines: 941, 947. pin.c 941
• V595 The 'pAlloc' pointer was utilized before it was verified against nullptr. Check lines: 970,
972. pin.c 970
• V595 The 'pAlloc' pointer was utilized before it was verified against nullptr. Check lines: 999,
1001. pin.c 999
• V595 The 'pAlloc' pointer was utilized before it was verified against nullptr. Check lines: 1028,
1030. pin.c 1028
• V595 The 'pMemAlloc' pointer was utilized before it was verified against nullptr. Check lines:
1704, 1709. pin.c 1704
• V595 The 'This->pMemInputPin' pointer was utilized before it was verified against nullptr. Check
lines: 1716, 1725. pin.c 1716
• V595 The 's' pointer was utilized before it was verified against nullptr. Check lines: 778, 799.
recyclebin_v5.c 778
• V595 The 'prbel' pointer was utilized before it was verified against nullptr. Check lines: 230, 248.
recyclebin.c 230
• V595 The 'ppszNames' pointer was utilized before it was verified against nullptr. Check lines:
238, 245. find.c 238
• V595 The 'ppszNames' pointer was utilized before it was verified against nullptr. Check lines:
464, 485. find.c 464
• V595 The 'para' pointer was utilized before it was verified against nullptr. Check lines: 211, 213.
caret.c 211
• V595 The 'lpObject' pointer was utilized before it was verified against nullptr. Check lines: 1151,
1173. editor.c 1151
• V595 The 'lpDataObject' pointer was utilized before it was verified against nullptr. Check lines:
1152, 1176. editor.c 1152
• V595 The 'lpOleCache' pointer was utilized before it was verified against nullptr. Check lines:
1150, 1177. editor.c 1150
• V595 The 'argv' pointer was utilized before it was verified against nullptr. Check lines: 354, 358.
rundll32.c 354
• V595 The 'pServiceStatus' pointer was utilized before it was verified against nullptr. Check lines:
131, 144. query.c 131
• V595 The 'pServiceStatus' pointer was utilized before it was verified against nullptr. Check lines:
191, 197. query.c 191
• V595 The 'oleobj' pointer was utilized before it was verified against nullptr. Check lines: 357,
365. dochost.c 357
• V595 The 'urlfile' pointer was utilized before it was verified against nullptr. Check lines: 220,
235. iexplore.c 220
• V595 The 'urlobj' pointer was utilized before it was verified against nullptr. Check lines: 223,
238. iexplore.c 223
• V595 The 'pDrvDefExt' pointer was utilized before it was verified against nullptr. Check lines:
161, 177. drive.cpp 161
• V595 The 'pszList' pointer was utilized before it was verified against nullptr. Check lines: 589,
606. dialogs.cpp 589
• V595 The 'pFileDefExt' pointer was utilized before it was verified against nullptr. Check lines:
142, 157. fprop.cpp 142
• V595 The 'pidl' pointer was utilized before it was verified against nullptr. Check lines: 757, 760.
pidl.cpp 757
• V595 The 'pidlInOut' pointer was utilized before it was verified against nullptr. Check lines: 136,
156. shlfolder.cpp 136
• V595 The 'cm' pointer was utilized before it was verified against nullptr. Check lines: 1296, 1303.
shlexec.cpp 1296
• V595 The 'pcchOut' pointer was utilized before it was verified against nullptr. Check lines: 2238,
2240. url.c 2238
• V595 The 'NewSubsystem' pointer was utilized before it was verified against nullptr. Check lines:
500, 502. smsubsys.c 500
• V595 The 'OutputMdl' pointer was utilized before it was verified against nullptr. Check lines:
1382, 1408. dispatch.c 1382
• V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 100,
101. buffer.c 100
• V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 159,
160. buffer.c 159
• V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 266,
267. buffer.c 266
• V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 277,
278. buffer.c 277
• V595 The 'lpszTemp' pointer was utilized before it was verified against nullptr. Check lines: 997,
1000. taskmgr.c 997
• V595 The 'AtaReq' pointer was utilized before it was verified against nullptr. Check lines: 4944,
4972. id_ata.cpp 4944
• V595 The 'AtaReq' pointer was utilized before it was verified against nullptr. Check lines: 4899,
4925. id_ata.cpp 4899
• V595 The 'Srb' pointer was utilized before it was verified against nullptr. Check lines: 9664,
9666. id_ata.cpp 9664
• V595 The 'Srb' pointer was utilized before it was verified against nullptr. Check lines: 9652,
9666. id_ata.cpp 9652
• V595 The 'builder->uri' pointer was utilized before it was verified against nullptr. Check lines:
5250, 5262. uri.c 5250
• V595 The 'pInstance' pointer was utilized before it was verified against nullptr. Check lines: 387,
388. ddeserver.c 387
• V595 The 'current_line' pointer was utilized before it was verified against nullptr. Check lines:
524, 529. edit.c 524
• V595 The 'es' pointer was utilized before it was verified against nullptr. Check lines: 5195, 5214.
edit.c 5195
• V595 The 'pBSMInfo' pointer was utilized before it was verified against nullptr. Check lines:
3146, 3158. message.c 3146
• V595 The 'pHwnd' pointer was utilized before it was verified against nullptr. Check lines: 673,
679. window.c 673
• V595 The 'levels' pointer was utilized before it was verified against nullptr. Check lines: 1572,
1578. usp10.c 1572
• V595 The '* root' pointer was utilized before it was verified against nullptr. Check lines: 548,
553. check.c 548
• V595 The 'VbeInfo' pointer was utilized before it was verified against nullptr. Check lines: 206,
207. vbemodes.c 206
• V595 The 'pClient->hPins' pointer was utilized before it was verified against nullptr. Check lines:
237, 242. entry.c 237
• V595 The 'Context.ProcessData' pointer was utilized before it was verified against nullptr. Check
lines: 853, 861. exitros.c 853
• V595 The 'pstrLibName' pointer was utilized before it was verified against nullptr. Check lines:
136, 140. callback.c 136
• V595 The 'psurfColor' pointer was utilized before it was verified against nullptr. Check lines:
1176, 1182. cursoricon.c 1176
• V595 The 'DestRect' pointer was utilized before it was verified against nullptr. Check lines: 33,
36. copybits.c 33
• V595 The 'SourcePoint' pointer was utilized before it was verified against nullptr. Check lines:
34, 36. copybits.c 34
• V595 The 'pdesk->pDeskInfo->spwnd' pointer was utilized before it was verified against nullptr.
Check lines: 148, 150. desktop.c 148
• V595 The 'psurfPattern' pointer was utilized before it was verified against nullptr. Check lines:
342, 365. engbrush.c 342
• V595 The 'WndPrev' pointer was utilized before it was verified against nullptr. Check lines: 62,
65. focus.c 62
• V595 The 'Wnd' pointer was utilized before it was verified against nullptr. Check lines: 374, 384.
focus.c 374
• V595 The 'pti->rpdesk' pointer was utilized before it was verified against nullptr. Check lines:
358, 364. input.c 358
• V595 The 'pStrokes' pointer was utilized before it was verified against nullptr. Check lines: 1941,
1947. path.c 1941
• V595 The 'dc' pointer was utilized before it was verified against nullptr. Check lines: 933, 958.
palette.c 933
• V595 The 'SourceRect' pointer was utilized before it was verified against nullptr. Check lines:
402, 430. stretchblt.c 402
• V595 The 'Wnd' pointer was utilized before it was verified against nullptr. Check lines: 390, 403.
windc.c 390
• V595 The 'pPatterns' pointer was utilized before it was verified against nullptr. Check lines: 512,
533. info.c 512
• V595 The 'converter' pointer was utilized before it was verified against nullptr. Check lines:
2164, 2172. info.c 2164
• V595 The 'context' pointer was utilized before it was verified against nullptr. Check lines: 95,
100. texture.c 95
• V595 The 'Globals.win_list' pointer was utilized before it was verified against nullptr. Check
lines: 560, 583. winhelp.c 560
• V595 The 'lpwh' pointer was utilized before it was verified against nullptr. Check lines: 1400,
1414. ftp.c 1400
• V595 The 'optval' pointer was utilized before it was verified against nullptr. Check lines: 284,
296. sockctrl.c 284
Macros
Macros are bad - of that I'm still dead sure. You should use regular functions wherever possible.
Someone felt too lazy to make a full-fledged function stat64_to_stat() in ReactOS and contented
himself/herself with creating a shit-macro. This is what it looks like:
#define stat64_to_stat(buf64, buf) 
buf->st_dev = (buf64)->st_dev; 
buf->st_ino = (buf64)->st_ino; 
buf->st_mode = (buf64)->st_mode; 
buf->st_nlink = (buf64)->st_nlink; 
buf->st_uid = (buf64)->st_uid; 
buf->st_gid = (buf64)->st_gid; 
buf->st_rdev = (buf64)->st_rdev; 
buf->st_size = (_off_t)(buf64)->st_size; 
buf->st_atime = (time_t)(buf64)->st_atime;
buf->st_mtime = (time_t)(buf64)->st_mtime; 
buf->st_ctime = (time_t)(buf64)->st_ctime; 
Let's see how this macro is used in the _tstat function:
int CDECL _tstat(const _TCHAR* path, struct _stat * buf)
{
int ret;
struct __stat64 buf64;
ret = _tstat64(path, &buf64);
if (!ret)
stat64_to_stat(&buf64, buf);
return ret;
}
Do you think the 'stat64_to_stat' macro is executed if the 'ret' variable equals zero? It is absolutely not.
The macro is expanded into a set of separate lines. That's why only the "buf->st_dev = (buf64)-
>st_dev;" line refers to the 'if' operator, while all the other lines will be executed all the time!
There are other fragments that employ this incorrect macro:
• V640 The code's operational logic does not correspond with its formatting. The second
statement will always be executed. It is possible that curly brackets are missing. stat.c 35
• V640 The code's operational logic does not correspond with its formatting. The second
statement will always be executed. It is possible that curly brackets are missing. stat.c 47
• V640 The code's operational logic does not correspond with its formatting. The second
statement will always be executed. It is possible that curly brackets are missing. stat.c 58
Conditions which are always true/false
Here's an issue when an always true condition might cause an infinite loop.
#define DISKREADBUFFER_SIZE HEX(10000)
typedef unsigned short USHORT, *PUSHORT;
static VOID DetectBiosDisks(....)
{
USHORT i;
....
Changed = FALSE;
for (i = 0; ! Changed && i < DISKREADBUFFER_SIZE; i++)
{
Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
}
....
}
V547 Expression 'i < 0x10000' is always true. The value range of unsigned short type: [0, 65535].
xboxhw.c 358
The loop is meant to search through the DISKREADBUFFER array for a byte whose value doesn't equal
'0xCD'. If such a byte doesn't exist, the 'Changed' variable always has the FALSE value. In this case, the "i
< DISKREADBUFFER_SIZE" expression is the truncation condition. As this expression is always true, the
program will start iterating an infinite loop.
The error is this: the 'i' variable has the 'unsigned short' type. It can take values within the range from 0
to 65535. These values are always below '0x10000'.
A typical error I often see in many projects is the assumption that SOCKET is a signed variable. It's not so.
To be more exact, it depends on the library implementation.
typedef UINT_PTR SOCKET;
#define ADNS_SOCKET SOCKET
struct adns__state {
....
ADNS_SOCKET udpsocket, tcpsocket;
....
};
static int init_finish(adns_state ads) {
....
if (ads->udpsocket<0) { r= errno; goto x_free; }
....
}
V547 Expression 'ads->udpsocket < 0' is always false. Unsigned type value is never < 0. setup.c 539
The 'udpsocket' variable is unsigned, which means that the 'ads->udpsocket < 0' condition is always
false. To figure out where the error has occurred we need to use the SOCKET_ERROR constant.
Similar socket handling errors can be found here:
• V547 Expression 'fd < 0' is always false. Unsigned type value is never < 0. event.c 117
• V547 Expression 'ads->udpsocket >= 0' is always true. Unsigned type value is always >= 0.
check.c 105
• V547 Expression 'ads->tcpsocket >= 0' is always true. Unsigned type value is always >= 0. check.c
114
• V547 Expression 'ads->tcpsocket >= 0' is always true. Unsigned type value is always >= 0. check.c
123
Incorrect checks may lead to buffer overflows and, consequently, to undefined behavior. Here's a
sample where the exception handler fails.
BOOL PrepareService(LPCTSTR ServiceName)
{
DWORD LeftOfBuffer = sizeof(ServiceKeyBuffer) /
sizeof(ServiceKeyBuffer[0]);
....
LeftOfBuffer -= _tcslen(SERVICE_KEY);
....
LeftOfBuffer -= _tcslen(ServiceName);
....
LeftOfBuffer -= _tcslen(PARAMETERS_KEY);
....
if (LeftOfBuffer < 0)
{
DPRINT1("Buffer overflow for service name: '%s'n",
ServiceName);
return FALSE;
}
....
}
V547 Expression 'LeftOfBuffer < 0' is always false. Unsigned type value is never < 0. svchost.c 51
The 'LeftOfBuffer' variable should most likely be a signed one.
It often happens that unsigned variables cause function return values to be checked incorrectly. Here's
such a code:
static INT FASTCALL
MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
{
UINT Id;
....
Id = NtUserMenuItemFromPoint(....);
....
if (0 <= Id &&
MenuGetRosMenuItemInfo(MenuInfo.Self, Id, &ItemInfo) &&
MenuInfo.FocusedItem == Id)
....
}
V547 Expression '0 <= Id' is always true. Unsigned type value is always >= 0. menu.c 2663
The NtUserMenuItemFromPoint() function can return the negative value (-1). The error occurs because
of the 'Id' variable being unsigned. That results in the '0 <= Id' check being meaningless.
A function parameter is checked incorrectly in the following code fragment.
typedef unsigned int GLuint;
const GLubyte *_mesa_get_enabled_extension(
struct gl_context *ctx, GLuint index)
{
const GLboolean *base;
size_t n;
const struct extension *i;
if (index < 0)
return NULL;
....
}
V547 Expression 'index < 0' is always false. Unsigned type value is never < 0. extensions.c 936
It's not interesting to discuss V547 warnings any further, so let me just cite the remaining fragments I've
noticed:
• V547 Expression 'index >= 0' is always true. Unsigned type value is always >= 0.
st_glsl_to_tgsi.cpp 4013
• V547 Expression 'index >= 0' is always true. Unsigned type value is always >= 0.
st_glsl_to_tgsi.cpp 4023
• V547 Expression 'index < 0' is always false. Unsigned type value is never < 0. st_glsl_to_tgsi.cpp
4027
• V547 Expression '(src[i]) < (0)' is always false. Unsigned type value is never < 0. texstore.c 3692
• V547 Expression '(src[i]) < (0)' is always false. Unsigned type value is never < 0. texstore.c 3759
• V547 Expression 'CommitReduction >= 0' is always true. Unsigned type value is always >= 0.
virtual.c 4784
• V547 Expression 'Info->nPage < 0' is always false. Unsigned type value is never < 0. scrollbar.c
428
• V547 Expression 'Entry->Id <= 0xffff' is always true. The value range of unsigned short type: [0,
65535]. res.c 312
Undefined behavior and Unspecified behavior.
You must not shift negative numbers - even if the code that has these shifts seems to work successfully
for a long time. It is incorrect. It leads to undefined or unspecified behavior. The issue may reveal itself
when you start using another platform or another compiler or change optimization switches. I discussed
negative number shifts in detail in the article "Wade not in unknown waters. Part three".
This is an incorrect code sample:
static INLINE int wrap(short f, int shift)
{
....
if (f < (-16 << shift))
....
}
V610 Undefined behavior. Check the shift operator '<<. The left operand '-16' is negative.
vl_mpeg12_bitstream.c 653
No one knows what the (-16 << shift) expression is equal to. Other similar fragile code samples can be
found in the following fragments:
• V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative.
jdarith.c 460
• V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative.
jdhuff.c 930
• V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative.
layer1.c 86
• V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative.
layer1.c 90
• V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative.
layer1.c 97
• V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative.
layer1.c 118
• V610 Unspecified behavior. Check the shift operator '>>. The left operand is negative ('i' = [-
4096..4095]). tabinit.c 269
• V610 Unspecified behavior. Check the shift operator '>>. The left operand is negative ('i' = [-
4096..4095]). tabinit.c 274
• V610 Undefined behavior. Check the shift operator '<<. The left operand '-1' is negative. mppc.c
351
Incorrect format specifier
Let's have a look at several samples demonstrating incorrect ways of using variadic functions to print
variable values.
UINT64 Size;
static HRESULT STDMETHODCALLTYPE
CBindStatusCallback_OnProgress(....)
{
....
_tprintf(_T("Length: %ulln"), This->Size);
....
}
V576 Incorrect format. Consider checking the second actual argument of the 'wprintf' function. The
argument is expected to be not greater than 32-bit. dwnl.c 228
You should write "%llu" instead of "%ull" to print a 64-bit variable.
Using "%u" is one more incorrect way to print the pointer value. There exists the "%p" specifier for this
purpose. However, the programmer must have made a misprint in the code below, and it is "%s" that
should have been written there.
BOOL CALLBACK EnumPickIconResourceProc(
HMODULE hModule, LPCWSTR lpszType,
LPWSTR lpszName, LONG_PTR lParam)
{
....
swprintf(szName, L"%u", lpszName);
....
}
V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function. To print
the value of pointer the '%p' should be used. dialogs.cpp 66
The errors when Unicode and non-Unicode strings are used together are very frequent. For example, if
you need to print a UNICODE character in the fprintf() function, you should use '%C', not '%c'. Here's an
incorrect code sample with that error:
int WINAPI WinMain(....)
{
LPWSTR *argvW = NULL;
....
fprintf(stderr,
"Unknown option "%c" in Repair moden",
argvW[i][j]);
....
}
V576 Incorrect format. Consider checking the third actual argument of the 'fprintf' function. The char
type argument is expected. msiexec.c 655
The same bugs can be found in the following fragments:
• V576 Incorrect format. Consider checking the third actual argument of the 'fprintf' function. The
char type argument is expected. msiexec.c 705
• V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function.
The pointer to string of wchar_t type symbols is expected. sminit.c 1831
• V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function.
The pointer to string of char type symbols is expected. bootsup.c 600
• V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function.
The pointer to string of char type symbols is expected. guiconsole.c 328
• V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function.
The pointer to string of char type symbols is expected. guiconsole.c 332
• V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function.
The pointer to string of char type symbols is expected. guiconsole.c 378
• V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function.
The pointer to string of char type symbols is expected. guiconsole.c 382
Operation priorities
I've found several errors related to operation priorities confusion.
static HRESULT BindStatusCallback_create(....)
{
HRESULT hr;
....
if ((hr = SafeArrayGetUBound(sa, 1, &size) != S_OK))
{
SafeArrayUnaccessData(sa);
return hr;
}
....
}
V593 Consider reviewing the expression of the 'A = B != C' kind. The expression is calculated as
following: 'A = (B != C)'. httprequest.c 692
According to operation priorities in C/C++, the "SafeArrayGetUBound(sa, 1, &size) != S_OK" comparison
is executed in the first place, while it is only then that assignment is performed. However, the condition
will work well. The incorrect thing is that the 'hr' variable will store 0 or 1 instead of the status. The
function will therefore return an incorrect status.
Here is another very similar error:
static void symt_fill_sym_info(....)
{
....
if (sym->tag != SymTagPublicSymbol ||
!(dbghelp_options & SYMOPT_UNDNAME) ||
(sym_info->NameLen =
UnDecorateSymbolName(name, sym_info->Name,
sym_info->MaxNameLen, UNDNAME_NAME_ONLY) == 0))
....
}
V593 Consider reviewing the expression of the 'A = B == C' kind. The expression is calculated as
following: 'A = (B == C)'. symbol.c 801
The code is difficult to read. But if you look close, you'll notice that the UnDecorateSymbolName()
function's return result is compared to zero first, then the comparison result is put into the 'sym_info-
>NameLen' variable.
Array index out of bounds
FF_T_WCHAR FileName[FF_MAX_FILENAME];
FF_T_UINT32 FF_FindEntryInDir(....) {
....
FF_T_WCHAR *lastPtr = pDirent->FileName + sizeof(pDirent->FileName);
....
lastPtr[-1] = '0';
....
}
V594 The pointer steps out of array's bounds. ff_dir.c 260
The programmer intended 'lastPtr' to point at a memory cell after that last character in the string. That
won't happen though. The string consists of WCHAR characters. It means that it's the buffer size that is
added, not the number of characters. And that value is twice larger than necessary. When writing the
null character, the array index out of bounds error with all its implications will occur.
This is what the fixed code looks like:
FF_T_WCHAR *lastPtr = pDirent->FileName +
sizeof(pDirent->FileName) / sizeof(pDirent->FileName[0]);
The strncat() function is pretty dangerous regarding this class of bugs. The reason is that it's not the total
buffer size that the last argument should specify, but how many more characters can be put into it.
Because of misunderstanding this thing, programmers write unsafe code:
void shell(int argc, const char *argv[])
{
char CmdLine[MAX_PATH];
....
strcpy( CmdLine, ShellCmd );
if (argc > 1)
{
strncat(CmdLine, " /C", MAX_PATH);
}
for (i=1; i<argc; i++)
{
strncat(CmdLine, " ", MAX_PATH);
strncat(CmdLine, argv[i], MAX_PATH);
}
....
}
V645 The 'strncat' function call could lead to the 'CmdLine' buffer overflow. The bounds should not
contain the size of the buffer, but a number of characters it can hold. cmds.c 1314
V645 The 'strncat' function call could lead to the 'CmdLine' buffer overflow. The bounds should not
contain the size of the buffer, but a number of characters it can hold. cmds.c 1319
V645 The 'strncat' function call could lead to the 'CmdLine' buffer overflow. The bounds should not
contain the size of the buffer, but a number of characters it can hold. cmds.c 1320
It cannot be guaranteed that no buffer overflow occurs. To learn more about this class of errors, see the
documentation (V645 diagnostic).
A similar trouble can be found here:
V645 The 'wcsncat' function call could lead to the 'szFileName' buffer overflow. The bounds should not
contain the size of the buffer, but a number of characters it can hold. logfile.c 50
Repetitions
Repetitions are related to conditions and can be of two types.
Type one. The same operations are executed regardless of the condition. For example:
void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal)
{
....
if(fNormal)
hOld = SelectObject(hdc, hhi);
else
hOld = SelectObject(hdc, hhi);
....
}
V523 The 'then' statement is equivalent to the 'else' statement. cardbutton.cpp 86
Another example:
NTSTATUS NTAPI
CPortPinWavePci::HandleKsStream(IN PIRP Irp)
{
....
if (m_Capture)
m_Position.WriteOffset += Data;
else
m_Position.WriteOffset += Data;
....
}
V523 The 'then' statement is equivalent to the 'else' statement. pin_wavepci.cpp 562
One more repetition of a large code fragment can be found here:
V523 The 'then' statement is equivalent to the 'else' statement. tab.c 1043
Type two. A condition is repeated. It appears that the second condition will never hold. For example:
#define LOCALE_SSHORTDATE 31
#define LOCALE_SLONGDATE 32
MSVCRT__locale_t CDECL MSVCRT__create_locale(....)
{
....
if (time_data[i]==
LOCALE_SSHORTDATE && !lcid[LC_TIME]) {
size += ....;
} else if(time_data[i]==
LOCALE_SSHORTDATE && !lcid[LC_TIME]) {
size += ....;
} else {
....
}
V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error
presence. Check lines: 1193, 1195. locale.c 1193
I suppose that the second check should have been written in the following way:
if (time_data[i]==LOCALE_SLONGDATE && !lcid[LC_TIME])
Other similar repeating checks can be found here:
• V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical
error presence. Check lines: 1225, 1228. locale.c 1225
• V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical
error presence. Check lines: 1241, 1244. locale.c 1241
Miscellaneous
Now let's have a look at diverse bugs.
Incorrect calculation of the characters number
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
UNICODE_STRING DosDevices =
RTL_CONSTANT_STRING(L"DosDevices");
NTSTATUS CreateNewDriveLetterName(....)
{
....
DriveLetter->Buffer[
sizeof(DosDevices.Buffer) / sizeof(WCHAR)] =
(WCHAR)Letter;
....
}
V514 Dividing sizeof a pointer 'sizeof (DosDevices.Buffer)' by another value. There is a probability of
logical error presence. mountmgr.c 164
It seems that the "sizeof(DosDevices.Buffer) / sizeof(WCHAR)" expression was intended to calculate the
number of characters in a string. But 'DosDevices.Buffer' is just a pointer. As a result, the pointer size is
divided by 'sizeof(WCHAR)'. Other similar errors can be found here:
• V514 Dividing sizeof a pointer 'sizeof (DosDevices.Buffer)' by another value. There is a
probability of logical error presence. mountmgr.c 190
• V514 Dividing sizeof a pointer 'sizeof (DosDevices.Buffer)' by another value. There is a
probability of logical error presence. symlink.c 937
Here's another case of incorrect calculation of the number of characters in strings. In the following
sample it's multiplication instead of division:
VOID DisplayEvent(HWND hDlg)
{
WCHAR szEventType[MAX_PATH];
WCHAR szTime[MAX_PATH];
WCHAR szDate[MAX_PATH];
WCHAR szUser[MAX_PATH];
WCHAR szComputer[MAX_PATH];
....
ListView_GetItemText(...., sizeof(szEventType)*sizeof(WCHAR));
ListView_GetItemText(...., sizeof(szDate)*sizeof(WCHAR));
ListView_GetItemText(...., sizeof(szTime)*sizeof(WCHAR));
ListView_GetItemText(...., sizeof(szSource)*sizeof(WCHAR));
ListView_GetItemText(...., sizeof(szCategory)*sizeof(WCHAR));
ListView_GetItemText(...., sizeof(szEventID)*sizeof(WCHAR));
ListView_GetItemText(...., sizeof(szUser)*sizeof(WCHAR));
ListView_GetItemText(...., sizeof(szComputer)*sizeof(WCHAR));
....
}
It results in the ListView_GetItemText() function assuming that the buffer size is larger than it actually is.
It may potentially cause a buffer overflow.
Function return result not used
#define strcmpW(s1,s2) wcscmp((s1),(s2))
static HRESULT WINAPI IEnumDMO_fnNext(....)
{
....
if (Names[count])
strcmpW(Names[count], szValue);
....
}
V530 The return value of function 'wcscmp' is required to be utilized. dmoreg.c 621
Uninitialized variable
HRESULT WINAPI
INetCfgComponentControl_fnApplyRegistryChanges(
INetCfgComponentControl * iface)
{
HKEY hKey;
....
if (RegCreateKeyExW(hKey,
L"SYSTEMCurrentControlSet....",
....) == ERROR_SUCCESS)
....
}
V614 Uninitialized pointer 'hKey' used. Consider checking the first actual argument of the
'RegCreateKeyExW' function. tcpipconf_notify.c 3138
While calling the RegCreateKeyExW() function, the 'hKey' variable is not initialized yet.
High-order bits that may be significant get truncated
HRESULT WINAPI CRecycleBin::CompareIDs(....)
{
....
return MAKE_HRESULT(SEVERITY_SUCCESS, 0,
(unsigned short)memcmp(pidl1->mkid.abID,
pidl2->mkid.abID,
pidl1->mkid.cb));
}
V642 Saving the 'memcmp' function result inside the 'unsigned short' type variable is inappropriate. The
significant bits could be lost breaking the program's logic. recyclebin.cpp 542
This type of errors is very much unobvious. I suggest that you read the description of the V642
diagnostic to understand the point. To put it briefly, the trouble is that the memcmp() function doesn't
necessarily return only values -1, 0, and 1. It may well return, for instance, number 0x100000. When
casting this number to the "unsigned short" type, it will turn into 0.
One-time loops
I've encountered several very strange loops. They don't have the 'continue' operator yet have the
unconditional operator 'break'. It means that the loop bodies are executed only once. Here's an example
of that kind.
VOID NTAPI IKsPin_PinCentricWorker(IN PVOID Parameter)
{
....
do
{
DPRINT("IKsPin_PinCentricWorker calling "
"Pin Process Routinen");
Status =
This->Pin.Descriptor->Dispatch->Process(&This->Pin);
DPRINT("IKsPin_PinCentricWorker Status %lx, "
"Offset %lu Length %lun", Status,
This->LeadingEdgeStreamPointer.Offset,
This->LeadingEdgeStreamPointer.Length);
break;
} while(This->IrpCount);
}
V612 An unconditional 'break' within a loop. pin.c 1839
Other similar strange loops:
• V612 An unconditional 'break' within a loop. regexp.c 3633
• V612 An unconditional 'break' within a loop. hlpfile.c 1131
Strange things
There are code fragments which are probably not bugs. They are simply very strange. For example:
BOOLEAN NTAPI Ext2MakeNewDirectoryEntry(....)
{
....
MinLength = HeaderLength + NameLength;
MinLength = (HeaderLength + NameLength + 3) & 0xfffffffc;
....
}
V519 The 'MinLength' variable is assigned values twice successively. Perhaps this is a mistake. Check
lines: 948, 949. metadata.c 949
The 'MinLength' variable is assigned different values twice in a row. Perhaps it somehow helps in
debugging - I don't know. I would consider this an error, but there are many fragments of that kind
throughout the code. I won't mention them, as the post is already huge enough.
Conclusion
I fail to make any wise conclusions. ReactOS is a rapidly growing and developing project. Hence it
contains quite a lot of errors. As you can see from this article, static analysis can catch a good deal of
them in a project like that. If one used it regularly, the benefit would be just invaluable.
Follow us on Twitter to keep track of PVS-Studio's new interesting feats in its struggle against bugs.
There we also post links to interesting articles on C/C++ programming and related subjects.

Weitere ähnliche Inhalte

Was ist angesagt?

Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioAndrey 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
 
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 AnalyzerAndrey Karpov
 
Errors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 librariesErrors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 librariesPVS-Studio
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioPVS-Studio
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionPVS-Studio
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codeAndrey Karpov
 
Checking Notepad++: five years later
Checking Notepad++: five years laterChecking Notepad++: five years later
Checking Notepad++: five years laterPVS-Studio
 
Discussing Errors in Unity3D's Open-Source Components
Discussing Errors in Unity3D's Open-Source ComponentsDiscussing Errors in Unity3D's Open-Source Components
Discussing Errors in Unity3D's Open-Source ComponentsPVS-Studio
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That CouldPVS-Studio
 
A Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCatA Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCatAndrey Karpov
 
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 VirtualBoxPVS-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 projectPVS-Studio
 
Checking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzerChecking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzerPVS-Studio
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggyAndrey Karpov
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggyPVS-Studio
 
PVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernelPVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernelPVS-Studio
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio
 
Top 10 C# projects errors found in 2016
Top 10 C# projects errors found in 2016Top 10 C# projects errors found in 2016
Top 10 C# projects errors found in 2016PVS-Studio
 
Documenting Bugs in Doxygen
Documenting Bugs in DoxygenDocumenting Bugs in Doxygen
Documenting Bugs in DoxygenPVS-Studio
 

Was ist angesagt? (20)

Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with 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...
 
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
 
Errors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 librariesErrors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 libraries
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-Studio
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correction
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
 
Checking Notepad++: five years later
Checking Notepad++: five years laterChecking Notepad++: five years later
Checking Notepad++: five years later
 
Discussing Errors in Unity3D's Open-Source Components
Discussing Errors in Unity3D's Open-Source ComponentsDiscussing Errors in Unity3D's Open-Source Components
Discussing Errors in Unity3D's Open-Source Components
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
 
A Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCatA Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCat
 
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
 
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
 
Checking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzerChecking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzer
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
 
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 delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernelPVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernel
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave
 
Top 10 C# projects errors found in 2016
Top 10 C# projects errors found in 2016Top 10 C# projects errors found in 2016
Top 10 C# projects errors found in 2016
 
Documenting Bugs in Doxygen
Documenting Bugs in DoxygenDocumenting Bugs in Doxygen
Documenting Bugs in Doxygen
 

Andere mochten auch

la celula 2
la celula 2 la celula 2
la celula 2 katyellen
 
Materiales didácticos digitales
Materiales didácticos digitalesMateriales didácticos digitales
Materiales didácticos digitalesWilson Defaz
 
Bitácoras de tecnologia 1 periodo
Bitácoras de tecnologia 1 periodoBitácoras de tecnologia 1 periodo
Bitácoras de tecnologia 1 periodosantiagocb
 
Presentacion DefinicióN De Objetivos Financieros
Presentacion DefinicióN De Objetivos FinancierosPresentacion DefinicióN De Objetivos Financieros
Presentacion DefinicióN De Objetivos Financieroscesar11411452
 

Andere mochten auch (9)

Estructura del Aula
Estructura del AulaEstructura del Aula
Estructura del Aula
 
Objeto de Aprendizaje
Objeto de Aprendizaje Objeto de Aprendizaje
Objeto de Aprendizaje
 
la celula 2
la celula 2 la celula 2
la celula 2
 
Materiales didácticos digitales
Materiales didácticos digitalesMateriales didácticos digitales
Materiales didácticos digitales
 
Isirp
IsirpIsirp
Isirp
 
Bitácoras de tecnologia 1 periodo
Bitácoras de tecnologia 1 periodoBitácoras de tecnologia 1 periodo
Bitácoras de tecnologia 1 periodo
 
Etica en los negocios
Etica en los negociosEtica en los negocios
Etica en los negocios
 
Ponenciasangra
PonenciasangraPonenciasangra
Ponenciasangra
 
Presentacion DefinicióN De Objetivos Financieros
Presentacion DefinicióN De Objetivos FinancierosPresentacion DefinicióN De Objetivos Financieros
Presentacion DefinicióN De Objetivos Financieros
 

Ähnlich wie Re-checking the ReactOS project - a large report

LibRaw, Coverity SCAN, PVS-Studio
LibRaw, Coverity SCAN, PVS-StudioLibRaw, Coverity SCAN, PVS-Studio
LibRaw, Coverity SCAN, PVS-StudioAndrey Karpov
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionAndrey Karpov
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionPVS-Studio
 
Brief analysis of Media Portal 2 bugs
Brief analysis of Media Portal 2 bugsBrief analysis of Media Portal 2 bugs
Brief analysis of Media Portal 2 bugsPVS-Studio
 
Analysis of Godot Engine's Source Code
Analysis of Godot Engine's Source CodeAnalysis of Godot Engine's Source Code
Analysis of Godot Engine's Source CodePVS-Studio
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project AnalyzedPVS-Studio
 
Firefox Easily Analyzed by PVS-Studio Standalone
Firefox Easily Analyzed by PVS-Studio StandaloneFirefox Easily Analyzed by PVS-Studio Standalone
Firefox Easily Analyzed by PVS-Studio StandaloneAndrey Karpov
 
Checking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzerChecking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzerPVS-Studio
 
Consequences of using the Copy-Paste method in C++ programming and how to dea...
Consequences of using the Copy-Paste method in C++ programming and how to dea...Consequences of using the Copy-Paste method in C++ programming and how to dea...
Consequences of using the Copy-Paste method in C++ programming and how to dea...Andrey Karpov
 
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' RequestChecking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' RequestPVS-Studio
 
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer HumankindAccord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer HumankindPVS-Studio
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckAndrey 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 CheckAndrey Karpov
 
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017Andrey Karpov
 

Ähnlich wie Re-checking the ReactOS project - a large report (15)

LibRaw, Coverity SCAN, PVS-Studio
LibRaw, Coverity SCAN, PVS-StudioLibRaw, Coverity SCAN, PVS-Studio
LibRaw, Coverity SCAN, PVS-Studio
 
PVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's codePVS-Studio: analyzing ReactOS's code
PVS-Studio: analyzing ReactOS's code
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correction
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correction
 
Brief analysis of Media Portal 2 bugs
Brief analysis of Media Portal 2 bugsBrief analysis of Media Portal 2 bugs
Brief analysis of Media Portal 2 bugs
 
Analysis of Godot Engine's Source Code
Analysis of Godot Engine's Source CodeAnalysis of Godot Engine's Source Code
Analysis of Godot Engine's Source Code
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project Analyzed
 
Firefox Easily Analyzed by PVS-Studio Standalone
Firefox Easily Analyzed by PVS-Studio StandaloneFirefox Easily Analyzed by PVS-Studio Standalone
Firefox Easily Analyzed by PVS-Studio Standalone
 
Checking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzerChecking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzer
 
Consequences of using the Copy-Paste method in C++ programming and how to dea...
Consequences of using the Copy-Paste method in C++ programming and how to dea...Consequences of using the Copy-Paste method in C++ programming and how to dea...
Consequences of using the Copy-Paste method in C++ programming and how to dea...
 
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' RequestChecking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
 
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer HumankindAccord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
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
 
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
 

Kürzlich hochgeladen

What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 

Kürzlich hochgeladen (20)

What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 

Re-checking the ReactOS project - a large report

  • 1. Re-checking the ReactOS project - a large report Author: Andrey Karpov Date: 02.04.2013 The ReactOS project is rapidly developing. One of the developers participating in this project suggested that we re-analyzed the source code, as the code base is growing fast. We were glad to do that. We like this project, and we'll be happy if this article helps the developers to eliminate some bugs. Analysis was performed with the PVS-Studio 5.02 code analyzer. Let me remind you what ReactOS is. This is a free and open-source operating system based on the Windows NT architecture principles. The system was developed from scratch and therefore is not based on Linux and doesn't have anything in common with the UNIX architecture. The main aim of the ReactOS project is to create a Windows binary-compatible operating system that would allow users to execute Windows-compatible applications and drivers as if they were executed in Windows itself. We analyzed this project once some time ago. The results of that check were described in the post "PVS- Studio: analyzing ReactOS's code". After re-checking the project, we have found a lot of new bugs and suspicious code fragments. This fact proves very well that static code analysis should be performed regularly, not occasionally! Doing it that way will help you to significantly reduce the number of errors at the stage of coding already, which means that errors detected will take much less time to eliminate. Note that the article describes far not all the fragments worth considering. ReactOS has become a big boy now: the solution includes 803 projects. For those, the PVS-Studio analyzer has generated a good deal of general warnings: 1. 1320 first-level warnings; 2. 814 second-level warnings; 3. 2753 third-level warnings. It was natural that I didn't find enough courage just to sit down and study all these warnings in detail. So, I'll only point at the most suspicious fragments that caught my glance. There certainly must be other warnings that should be examined as attentively; and there are also diagnostics related to 64-bit errors and micro-optimizations which I didn't examine at all.
  • 2. The PVS-Studio demo version will be insufficient to examine all the 4887 warnings. However, we are friendly to open-source projects: if the ReactOS developers ask us, we'll give them our tool for free for a while. Misprints PVS-Studio is good at detecting various misprints. We may call it its "hobbyhorse". This is a very useful function, as misprints inevitably exist in any project. Let's see what ReactOS has to show us in this field. Variable overwrite NTSTATUS NTAPI CreateCdRomDeviceObject(....) { .... cddata->XAFlags &= ~XA_USE_6_BYTE; cddata->XAFlags = XA_USE_READ_CD | XA_USE_10_BYTE; .... } V519 The 'cddata->XAFlags' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1290, 1291. cdrom.c 1291 The assignment operation overwrites the previous value of the XAFlags term. The following text should be most likely written instead: cddata->XAFlags |= XA_USE_READ_CD | XA_USE_10_BYTE;. But of course I can't be quite sure, as I don't know the logic of this code. Repetition in condition void util_blit_pixels_writemask(....) { .... if ((src_tex == dst_surface->texture && dst_surface->u.tex.level == src_level && dst_surface->u.tex.first_layer == srcZ0) || (src_tex->target != PIPE_TEXTURE_2D && src_tex->target != PIPE_TEXTURE_2D && src_tex->target != PIPE_TEXTURE_RECT)) .... }
  • 3. V501 There are identical sub-expressions 'src_tex->target != PIPE_TEXTURE_2D' to the left and to the right of the '&&' operator. u_blit.c 421 The check "src_tex->target != PIPE_TEXTURE_2D" is executed twice. It's another constant that the 'target' term must be compared to for the second time. Otherwise this comparison is unnecessary. Here's another error of this kind: static boolean is_legal_int_format_combo( const struct util_format_description *src, const struct util_format_description *dst ) { .... for (i = 0; i < nr; i++) { /* The signs must match. */ if (src->channel[i].type != src->channel[i].type) { return FALSE; } .... } V501 There are identical sub-expressions 'src->channel[i].type' to the left and to the right of the '!=' operator. translate_generic.c 776 The correct check seems to be as follows: src->channel[i].type != dst->channel[i].type. And one more similar error: static GpStatus draw_poly(....) { .... if((i + 2 >= count) || !(types[i + 1] & PathPointTypeBezier) || !(types[i + 1] & PathPointTypeBezier)) { ERR("Bad bezier pointsn"); goto end;
  • 4. } .... } V501 There are identical sub-expressions '!(types[i + 1] & PathPointTypeBezier)' to the left and to the right of the '||' operator. graphics.c 1912 One more: static inline BOOL is_unc_path(const WCHAR *str) { return (str[0] == '' && str[0] == ''); } V501 There are identical sub-expressions to the left and to the right of the '&&' operator: str[0] == '' && str[0] == '' uri.c 273 By the way, this particular bug remains unfixed since the previous check. I didn't describe it in the previous article, although it is included into my error samples base. Don't remember why I didn't mention it - perhaps I was concerned about not making the article too large. The developers must have never run PVS-Studio on their project, and the bug has successfully survived inside the code for at least a couple of years. One more: VOID NTAPI UniAtaReadLunConfig(....) { if(!LunExt->IdentifyData.SectorsPerTrack || !LunExt->IdentifyData.NumberOfCylinders || !LunExt->IdentifyData.SectorsPerTrack) .... } V501 There are identical sub-expressions '!LunExt->IdentifyData.SectorsPerTrack' to the left and to the right of the '||' operator. id_init.cpp 1528 The error is quite obvious, I believe. Don't know how to fix it. Be patient - I have some other twin bugs to show you. And I can't help it... You see, these are very typical software bugs.
  • 5. ir_visitor_status ir_validate::visit_leave(ir_loop *ir) { if (ir->counter != NULL) { if ((ir->from == NULL) || (ir->from == NULL) || (ir->increment == NULL)) { .... } V501 There are identical sub-expressions to the left and to the right of the '||' operator: (ir->from == 0) || (ir->from == 0) ir_validate.cpp 123 One of the "ir->from == 0" comparisons must be replaced with "ir->to == NULL". The same error, caused through the copy-paste technology, can be found here: V501 There are identical sub-expressions to the left and to the right of the '||' operator: (ir->from != 0) || (ir->from != 0) ir_validate.cpp 139 Unnecessary semicolon We have finally got to another class of misprints - the unnecessary semicolon ';' that spoils everything. int BlockEnvToEnvironA(void) { .... for (envptr--; envptr >= _environ; envptr--); free(*envptr); .... } V529 Odd semicolon ';' after 'for' operator. environ.c 67 Note the ';' character after the 'for' operator. It results in the free() function being called only once, which leads to memory leaks. It also causes releasing a memory area that wasn't intended to be released. This is how the incorrect code works in its present state: free(envptr >= _environ ? _environ[-1] : envptr); The same semicolons can be found here: • V529 Odd semicolon ';' after 'for' operator. environ.c 119 • V529 Odd semicolon ';' after 'for' operator. environ.c 171
  • 6. Incorrect expression static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions( ...., DWORD dwEnabledOptions) { .... This->safeopt = dwEnabledOptions & dwEnabledOptions; return S_OK; } V501 There are identical sub-expressions to the left and to the right of the '&' operator: dwEnabledOptions & dwEnabledOptions jscript.c 905 One of the operands seems to have an incorrectly defined name in the expression. Here's a misprint that causes the size of a rectangle to be calculated incorrectly. GpStatus WINGDIPAPI GdipGetRegionBoundsI(....) { .... status = GdipGetRegionBounds(region, graphics, &rectf); if (status == Ok){ rect->X = gdip_round(rectf.X); rect->Y = gdip_round(rectf.X); rect->Width = gdip_round(rectf.Width); rect->Height = gdip_round(rectf.Height); } return status; } V656 Variables 'rect->X', 'rect->Y' are initialized through the call to the same function. It's probably an error or un-optimized code. Consider inspecting the 'gdip_round(rectf.X)' expression. Check lines: 718, 719. region.c 719 I'm almost sure that the following code must be written here: "rect->Y = gdip_round(rectf.Y);". If it's not so, there should be some comment on this.
  • 7. The following is a code fragment where a variable is assigned to itself: DWORD WINAPI DdGetDriverInfo(LPDDHAL_GETDRIVERINFODATA pData) { .... pUserColorControl->dwFlags = pUserColorControl->dwFlags; .... } V570 The 'pUserColorControl->dwFlags' variable is assigned to itself. gdientry.c 1029 The assignment is meaningless. The expression must be incomplete, or something is messed up. The same error here: V570 The 'Irp->IoStatus.Information' variable is assigned to itself. hidclass.c 461 Let's talk about null pointers If you have a C/C++ application, you have troubles with pointers. This is the price we have to pay for the language's efficiency. However, C++ and especially C++11 offer a number of ways to avoid handling wild pointers. But that is a subject to be discussed individually. Let's see what can be found in ReactOS regarding this kind of bugs. Null pointer dereferencing static void acpi_bus_notify (....) { struct acpi_device *device = NULL; .... switch (type) { .... case ACPI_NOTIFY_EJECT_REQUEST: DPRINT1("Received EJECT REQUEST " "notification for device [%s]n", device->pnp.bus_id); break; .... }
  • 8. } V522 Dereferencing of the null pointer 'device' might take place. bus.c 762 If the "case ACPI_NOTIFY_EJECT_REQUEST:" branch is chosen in the 'switch' operator, the 'device' pointer will still be equal to zero at the moment. Dereferencing it in the "device->pnp.bus_id" expression will have unpleasant consequences. In the same bad way the 'device' variable is used in some other fragments: • V522 Dereferencing of the null pointer 'device' might take place. bus.c 768 • V522 Dereferencing of the null pointer 'device' might take place. bus.c 774 • V522 Dereferencing of the null pointer 'device' might take place. bus.c 780 • V522 Dereferencing of the null pointer 'device' might take place. bus.c 786 Here's another code fragment where a variable remains equal to zero by the moment it must be used: ir_texture *ir_reader::read_texture(s_expression *expr) { s_symbol *tag = NULL; .... } else if (MATCH(expr, other_pattern)) { op = ir_texture::get_opcode(tag->value()); if (op == -1) return NULL; } .... } V522 Dereferencing of the null pointer 'tag' might take place. ir_reader.cpp 904 At the moment of calling the value() function, the 'tag' variable will still equal zero. That's no good. There are some other similar null pointer dereferencing bugs found in ReactOS: • V522 Dereferencing of the null pointer 's_shadow' might take place. ir_reader.cpp 964 • V522 Dereferencing of the null pointer 'BootSectorInfo' might take place. disksup.c 1750 • V522 Dereferencing of the null pointer 'BootSectorInfo' might take place. disksup.c 1751 • V522 Dereferencing of the null pointer 'BootSectorInfo' might take place. disksup.c 1754 Passing a null pointer into a function BOOL GetEventCategory(....) {
  • 9. .... if (lpMsgBuf) { .... } else { wcscpy(CategoryName, (LPCWSTR)lpMsgBuf); } .... } V575 The null pointer is passed into 'wcscpy' function. Inspect the second argument. eventvwr.c 270 The wcscpy() function is called only if the 'lpMsgBuf' variable equals zero. This variable is passed as an argument into the 'wcscpy' function. It's hooliganism to pass zero into the 'wcscpy' function. Here, another hooligan is torturing a cat the strstr() function: VOID WinLdrSetupEms(IN PCHAR BootOptions) { PCHAR RedirectPort; .... if (RedirectPort) { .... } else { RedirectPort = strstr(RedirectPort, "usebiossettings"); .... } V575 The null pointer is passed into 'strstr' function. Inspect the first argument. headless.c 263
  • 10. The _wcsicmp() function has suffered for company as well: DWORD ParseReasonCode(LPCWSTR code) { LPWSTR tmpPrefix = NULL; .... for (reasonptr = shutdownReason ; reasonptr->prefix ; reasonptr++) { if ((majorCode == reasonptr->major) && (minorCode == reasonptr->minor) && (_wcsicmp(tmpPrefix, reasonptr->prefix) != 0)) { return reasonptr->flag; } } .... } V575 The null pointer is passed into '_wcsicmp' function. Inspect the first argument. misc.c 150 By the time the _wcsicmp() function must be called, the pointer tmpPrefix is still a null pointer. Dereferencing a possible null pointer There are very many code fragments where the pointer is first dereferenced and only then is checked for being a null pointer. It's not always an error. Perhaps the pointer simply cannot be a null pointer, and the check is just unnecessary. But such code usually appears due to inattention and is incorrect. It works only until the unhappy pointer suddenly becomes a null pointer through a coincidence. I will cite only one simple example here: static BOOL LookupSidInformation(....) { .... DomainName = &PolicyAccountDomainInfo->DomainName; SidNameUse = (PolicyAccountDomainInfo != NULL ? SidTypeGroup : SidTypeUser);
  • 11. .... } V595 The 'PolicyAccountDomainInfo' pointer was utilized before it was verified against nullptr. Check lines: 254, 257. sidcache.c 254 Look, the 'PolicyAccountDomainInfo' pointer is dereferenced first. And then it is suddenly checked for being a null pointer. Such a code is usually created as a result of swift refactoring. Variables are starting to be used when there are not checked yet. The reason why I'm describing only one error of this kind is that they all look much alike. And also because they are AWFULLY NUMEROUS. I'm not interested in examining and describing each individual case. Moreover, it's impossible to include them all into the article - it would then be a reference book instead. That's why I'll just cite the diagnostic messages for you: • V595 The 'oldRelations' pointer was utilized before it was verified against nullptr. Check lines: 216, 246. pnp.c 216 • V595 The 'Op->Common.Value.Arg' pointer was utilized before it was verified against nullptr. Check lines: 531, 554. dswload.c 531 • V595 The 'OutOp' pointer was utilized before it was verified against nullptr. Check lines: 325, 346. dswexec.c 325 • V595 The 'Poll' pointer was utilized before it was verified against nullptr. Check lines: 63, 66. select.c 63 • V595 The 'pEdit' pointer was utilized before it was verified against nullptr. Check lines: 480, 491. editstream.c 480 • V595 The 'plpOptions[curStream]' pointer was utilized before it was verified against nullptr. Check lines: 1629, 1630. api.c 1629 • V595 The 'pThis' pointer was utilized before it was verified against nullptr. Check lines: 454, 461. atlwin.h 454 • V595 The 'pThis' pointer was utilized before it was verified against nullptr. Check lines: 639, 646. atlwin.h 639 • V595 The 'DeviceObject' pointer was utilized before it was verified against nullptr. Check lines: 6870, 6877. class.c 6870 • V595 The 'extName' pointer was utilized before it was verified against nullptr. Check lines: 128, 141. assoc.c 128 • V595 The 'FileList' pointer was utilized before it was verified against nullptr. Check lines: 775, 791. filecomp.c 775 • V595 The 'ident' pointer was utilized before it was verified against nullptr. Check lines: 449, 462. set.c 449 • V595 The 'psp' pointer was utilized before it was verified against nullptr. Check lines: 2705, 2714. propsheet.c 2705 • V595 The 'lpItem' pointer was utilized before it was verified against nullptr. Check lines: 4256, 4269. listview.c 4256 • V595 The 'lpFindInfo' pointer was utilized before it was verified against nullptr. Check lines: 6199, 6203. listview.c 6199 • V595 The 'item' pointer was utilized before it was verified against nullptr. Check lines: 1461, 1463. treeview.c 1461
  • 12. • V595 The 'file' pointer was utilized before it was verified against nullptr. Check lines: 2799, 2802. file.c 2799 • V595 The 'context' pointer was utilized before it was verified against nullptr. Check lines: 976, 1006. cryptnet_main.c 976 • V595 The 'advanced' pointer was utilized before it was verified against nullptr. Check lines: 436, 451. main.c 436 • V595 The 'compiland' pointer was utilized before it was verified against nullptr. Check lines: 389, 396. symbol.c 389 • V595 The 'func' pointer was utilized before it was verified against nullptr. Check lines: 468, 471. symbol.c 468 • V595 The 'compiland' pointer was utilized before it was verified against nullptr. Check lines: 589, 594. symbol.c 589 • V595 The 'pMapper' pointer was utilized before it was verified against nullptr. Check lines: 822, 847. createdevenum.c 822 • V595 The 'psh.phpage' pointer was utilized before it was verified against nullptr. Check lines: 2475, 2494. advprop.c 2475 • V595 The 'DevAdvPropInfo' pointer was utilized before it was verified against nullptr. Check lines: 2480, 2508. advprop.c 2480 • V595 The 'DeviceID' pointer was utilized before it was verified against nullptr. Check lines: 296, 303. enumdevices.c 296 • V595 The 'DeviceObject' pointer was utilized before it was verified against nullptr. Check lines: 4279, 4284. disk.c 4279 • V595 The 'device->hwbuf' pointer was utilized before it was verified against nullptr. Check lines: 917, 927. mixer.c 917 • V595 The 'PtrNewFileObject' pointer was utilized before it was verified against nullptr. Check lines: 306, 322. create.c 306 • V595 The 'PtrSourceFCB->FCBName' pointer was utilized before it was verified against nullptr. Check lines: 2793, 2812. metadata.c 2793 • V595 The 'FileObject' pointer was utilized before it was verified against nullptr. Check lines: 54, 60. fastio.c 54 • V595 The 'FileObject' pointer was utilized before it was verified against nullptr. Check lines: 663, 680. fastio.c 663 • V595 The 'FileObject' pointer was utilized before it was verified against nullptr. Check lines: 733, 749. fastio.c 733 • V595 The 'PtrCCB' pointer was utilized before it was verified against nullptr. Check lines: 1018, 1021. fastio.c 1018 • V595 The 'PtrCCB' pointer was utilized before it was verified against nullptr. Check lines: 1093, 1102. fastio.c 1093 • V595 The 'pData' pointer was utilized before it was verified against nullptr. Check lines: 330, 340. inode.c 330 • V595 The 'ext2_bdl' pointer was utilized before it was verified against nullptr. Check lines: 532, 537. inode.c 532 • V595 The 'ext2_bdl' pointer was utilized before it was verified against nullptr. Check lines: 600, 615. inode.c 600 • V595 The 'IrpContext' pointer was utilized before it was verified against nullptr. Check lines: 922, 925. finfo.c 922
  • 13. • V595 The 'IrpContext' pointer was utilized before it was verified against nullptr. Check lines: 396, 399. volume.c 396 • V595 The 'rwContext' pointer was utilized before it was verified against nullptr. Check lines: 224, 235. fbtrwr.c 224 • V595 The 'DataSize' pointer was utilized before it was verified against nullptr. Check lines: 695, 699. registry.c 695 • V595 The 'DataSize' pointer was utilized before it was verified against nullptr. Check lines: 733, 737. registry.c 733 • V595 The 'mm' pointer was utilized before it was verified against nullptr. Check lines: 287, 290. pb_bufmgr_mm.c 287 • V595 The 'pool' pointer was utilized before it was verified against nullptr. Check lines: 315, 320. pb_bufmgr_pool.c 315 • V595 The 'cache' pointer was utilized before it was verified against nullptr. Check lines: 186, 189. u_cache.c 186 • V595 The 'cache' pointer was utilized before it was verified against nullptr. Check lines: 221, 224. u_cache.c 221 • V595 The 'src' pointer was utilized before it was verified against nullptr. Check lines: 163, 166. u_surface.c 163 • V595 The 'graphics' pointer was utilized before it was verified against nullptr. Check lines: 2239, 2255. graphics.c 2239 • V595 The 'vlist' pointer was utilized before it was verified against nullptr. Check lines: 69, 73. trimvertpool.cc 69 • V595 The 'vlist' pointer was utilized before it was verified against nullptr. Check lines: 88, 93. trimvertpool.cc 88 • V595 The 'LocalItemState' pointer was utilized before it was verified against nullptr. Check lines: 64, 70. parser.c 64 • V595 The 'sd->zone_mgr' pointer was utilized before it was verified against nullptr. Check lines: 246, 249. security.c 246 • V595 The 'entitySet' pointer was utilized before it was verified against nullptr. Check lines: 519, 535. ipstats_reactos.c 519 • V595 The 'disp' pointer was utilized before it was verified against nullptr. Check lines: 509, 515. jscript.c 509 • V595 The 'a_cBuffer' pointer was utilized before it was verified against nullptr. Check lines: 888, 893. debugger.c 888 • V595 The 'AutomationTableB' pointer was utilized before it was verified against nullptr. Check lines: 1903, 1905. api.c 1903 • V595 The 'AutomationTableB' pointer was utilized before it was verified against nullptr. Check lines: 1952, 1954. api.c 1952 • V595 The 'AutomationTableB' pointer was utilized before it was verified against nullptr. Check lines: 2001, 2003. api.c 2001 • V595 The 'AutomationTableB' pointer was utilized before it was verified against nullptr. Check lines: 2347, 2350. api.c 2347 • V595 The 'IoStack->FileObject' pointer was utilized before it was verified against nullptr. Check lines: 611, 622. device.c 611 • V595 The 'Ctx' pointer was utilized before it was verified against nullptr. Check lines: 425, 430. event.c 425
  • 14. • V595 The 'BusDeviceExtension' pointer was utilized before it was verified against nullptr. Check lines: 1388, 1390. swenum.c 1388 • V595 The 'path' pointer was utilized before it was verified against nullptr. Check lines: 3250, 3254. catalog.c 3250 • V595 The 'str2' pointer was utilized before it was verified against nullptr. Check lines: 395, 396. c14n.c 395 • V595 The 'atts' pointer was utilized before it was verified against nullptr. Check lines: 3763, 3775. htmlparser.c 3763 • V595 The 'ctxt' pointer was utilized before it was verified against nullptr. Check lines: 3674, 3676. htmlparser.c 3674 • V595 The 'ctxt->input' pointer was utilized before it was verified against nullptr. Check lines: 6693, 6697. htmlparser.c 6693 • V595 The 'name' pointer was utilized before it was verified against nullptr. Check lines: 123, 131. hash.c 123 • V595 The 'ctxt->nsTab' pointer was utilized before it was verified against nullptr. Check lines: 1546, 1553. parser.c 1546 • V595 The 'ctxt->input' pointer was utilized before it was verified against nullptr. Check lines: 6690, 6698. parser.c 6690 • V595 The 'ctxt->input' pointer was utilized before it was verified against nullptr. Check lines: 6750, 6758. parser.c 6750 • V595 The 'atts' pointer was utilized before it was verified against nullptr. Check lines: 8477, 8486. parser.c 8477 • V595 The 'ctxt->input' pointer was utilized before it was verified against nullptr. Check lines: 11113, 11116. parser.c 11113 • V595 The 'ctx->myDoc' pointer was utilized before it was verified against nullptr. Check lines: 12784, 12787. parser.c 12784 • V595 The 'ctxt->myDoc' pointer was utilized before it was verified against nullptr. Check lines: 13341, 13357. parser.c 13341 • V595 The 'oldctxt' pointer was utilized before it was verified against nullptr. Check lines: 13349, 13367. parser.c 13349 • V595 The 'tmp' pointer was utilized before it was verified against nullptr. Check lines: 1536, 1537. relaxng.c 1536 • V595 The 'lib' pointer was utilized before it was verified against nullptr. Check lines: 8598, 8604. relaxng.c 8598 • V595 The 'ctxt->myDoc' pointer was utilized before it was verified against nullptr. Check lines: 984, 986. sax2.c 984 • V595 The 'ctxt->incTab' pointer was utilized before it was verified against nullptr. Check lines: 392, 400. xinclude.c 392 • V595 The 'href' pointer was utilized before it was verified against nullptr. Check lines: 518, 529. xinclude.c 518 • V595 The 'ctxt' pointer was utilized before it was verified against nullptr. Check lines: 1129, 1130. xinclude.c 1129 • V595 The 'ctxt->incTab[nr]' pointer was utilized before it was verified against nullptr. Check lines: 1419, 1428. xinclude.c 1419 • V595 The 'p' pointer was utilized before it was verified against nullptr. Check lines: 586, 589. xmlmemory.c 586
  • 15. • V595 The 'node' pointer was utilized before it was verified against nullptr. Check lines: 2819, 2829. xmlschemastypes.c 2819 • V595 The 'attr' pointer was utilized before it was verified against nullptr. Check lines: 2858, 2862. xmlschemas.c 2858 • V595 The 'uses' pointer was utilized before it was verified against nullptr. Check lines: 14498, 14508. xmlschemas.c 14498 • V595 The 'atom->ranges' pointer was utilized before it was verified against nullptr. Check lines: 817, 818. xmlregexp.c 817 • V595 The 'exec->state' pointer was utilized before it was verified against nullptr. Check lines: 4263, 4273. xmlregexp.c 4263 • V595 The 'res' pointer was utilized before it was verified against nullptr. Check lines: 14032, 14054. xpath.c 14032 • V595 The 'msg' pointer was utilized before it was verified against nullptr. Check lines: 361, 363. rostcp.c 361 • V595 The 'msg' pointer was utilized before it was verified against nullptr. Check lines: 469, 473. rostcp.c 469 • V595 The 'last_unsent' pointer was utilized before it was verified against nullptr. Check lines: 632, 661. tcp_out.c 632 • V595 The 'att->Renderbuffer' pointer was utilized before it was verified against nullptr. Check lines: 790, 798. fbobject.c 790 • V595 The 'sub_prims' pointer was utilized before it was verified against nullptr. Check lines: 852, 859. st_draw.c 852 • V595 The 'height' pointer was utilized before it was verified against nullptr. Check lines: 2471, 2474. teximage.c 2471 • V595 The 'WorkItem' pointer was utilized before it was verified against nullptr. Check lines: 745, 753. notify.c 745 • V595 The 'lpErrno' pointer was utilized before it was verified against nullptr. Check lines: 425, 439. dllmain.c 425 • V595 The 'pServiceFailureActions' pointer was utilized before it was verified against nullptr. Check lines: 175, 184. srvpage.c 175 • V595 The 'This->pITextStoreACP' pointer was utilized before it was verified against nullptr. Check lines: 143, 147. context.c 143 • V595 The 'sidsize' pointer was utilized before it was verified against nullptr. Check lines: 1998, 2002. registry.c 1998 • V595 The 'locator->pParserCtxt' pointer was utilized before it was verified against nullptr. Check lines: 2290, 2301. saxreader.c 2290 • V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 100, 101. buffer.c 100 • V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 159, 160. buffer.c 159 • V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 264, 265. buffer.c 264 • V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 275, 276. buffer.c 275 • V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 627, 628. buffer.c 627
  • 16. • V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 638, 639. buffer.c 638 • V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 1249, 1250. buffer.c 1249 • V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 1262, 1263. buffer.c 1262 • V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 1047, 1048. 8390.c 1047 • V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 899, 900. main.c 899 • V595 The 'EnumContext' pointer was utilized before it was verified against nullptr. Check lines: 596, 599. local_group.c 596 • V595 The 'EnumContext' pointer was utilized before it was verified against nullptr. Check lines: 1344, 1347. user.c 1344 • V595 The '* ptr' pointer was utilized before it was verified against nullptr. Check lines: 85, 88. nbnamecache.c 85 • V595 The 'wki' pointer was utilized before it was verified against nullptr. Check lines: 129, 133. netid.c 129 • V595 The 'wki' pointer was utilized before it was verified against nullptr. Check lines: 163, 167. netid.c 163 • V595 The 'wki' pointer was utilized before it was verified against nullptr. Check lines: 299, 302. netid.c 299 • V595 The 'SafeParams' pointer was utilized before it was verified against nullptr. Check lines: 608, 624. harderr.c 608 • V595 The 'ObjectCreateInfo' pointer was utilized before it was verified against nullptr. Check lines: 707, 732. oblife.c 707 • V595 The 'ListHead' pointer was utilized before it was verified against nullptr. Check lines: 103, 104. pfnlist.c 103 • V595 The 'ImpersonationInfo' pointer was utilized before it was verified against nullptr. Check lines: 56, 60. security.c 56 • V595 The 'CapturedPrivileges' pointer was utilized before it was verified against nullptr. Check lines: 2256, 2277. token.c 2256 • V595 The 'pv' pointer was utilized before it was verified against nullptr. Check lines: 809, 831. variant.c 809 • V595 The 'result' pointer was utilized before it was verified against nullptr. Check lines: 3394, 3401. variant.c 3394 • V595 The 'result' pointer was utilized before it was verified against nullptr. Check lines: 3585, 3592. variant.c 3585 • V595 The 'pVarOut' pointer was utilized before it was verified against nullptr. Check lines: 5248, 5251. variant.c 5248 • V595 The 'typeInfo' pointer was utilized before it was verified against nullptr. Check lines: 867, 869. typelib.c 867 • V595 The 'subtypeinfo' pointer was utilized before it was verified against nullptr. Check lines: 4960, 4965. typelib.c 4960 • V595 The 'pTLib' pointer was utilized before it was verified against nullptr. Check lines: 7082, 7084. typelib.c 7082
  • 17. • V595 The 'DeviceObject' pointer was utilized before it was verified against nullptr. Check lines: 612, 624. fdo.c 612 • V595 The 'Package' pointer was utilized before it was verified against nullptr. Check lines: 170, 187. init.c 170 • V595 The 'Package' pointer was utilized before it was verified against nullptr. Check lines: 462, 469. init.c 462 • V595 The 'Adapter' pointer was utilized before it was verified against nullptr. Check lines: 998, 1004. pcnet.c 998 • V595 The 'm_pInterruptSync' pointer was utilized before it was verified against nullptr. Check lines: 1610, 1627. miniport_dmus.cpp 1610 • V595 The 'DSImpl->dsbuffer' pointer was utilized before it was verified against nullptr. Check lines: 882, 898. dsoundrender.c 882 • V595 The 'pcFetched' pointer was utilized before it was verified against nullptr. Check lines: 199, 204. enummedia.c 199 • V595 The 'pParser' pointer was utilized before it was verified against nullptr. Check lines: 868, 872. filtermapper.c 868 • V595 The 'pPropBag' pointer was utilized before it was verified against nullptr. Check lines: 920, 928. filtermapper.c 920 • V595 The 'pPropBagCat' pointer was utilized before it was verified against nullptr. Check lines: 1342, 1366. filtermapper.c 1342 • V595 The 'pPropBagCat' pointer was utilized before it was verified against nullptr. Check lines: 784, 797. filtergraph.c 784 • V595 The 'pFM2' pointer was utilized before it was verified against nullptr. Check lines: 644, 654. regsvr.c 644 • V595 The 'pAlloc' pointer was utilized before it was verified against nullptr. Check lines: 900, 905. pin.c 900 • V595 The 'pMemConnected' pointer was utilized before it was verified against nullptr. Check lines: 941, 947. pin.c 941 • V595 The 'pAlloc' pointer was utilized before it was verified against nullptr. Check lines: 970, 972. pin.c 970 • V595 The 'pAlloc' pointer was utilized before it was verified against nullptr. Check lines: 999, 1001. pin.c 999 • V595 The 'pAlloc' pointer was utilized before it was verified against nullptr. Check lines: 1028, 1030. pin.c 1028 • V595 The 'pMemAlloc' pointer was utilized before it was verified against nullptr. Check lines: 1704, 1709. pin.c 1704 • V595 The 'This->pMemInputPin' pointer was utilized before it was verified against nullptr. Check lines: 1716, 1725. pin.c 1716 • V595 The 's' pointer was utilized before it was verified against nullptr. Check lines: 778, 799. recyclebin_v5.c 778 • V595 The 'prbel' pointer was utilized before it was verified against nullptr. Check lines: 230, 248. recyclebin.c 230 • V595 The 'ppszNames' pointer was utilized before it was verified against nullptr. Check lines: 238, 245. find.c 238 • V595 The 'ppszNames' pointer was utilized before it was verified against nullptr. Check lines: 464, 485. find.c 464
  • 18. • V595 The 'para' pointer was utilized before it was verified against nullptr. Check lines: 211, 213. caret.c 211 • V595 The 'lpObject' pointer was utilized before it was verified against nullptr. Check lines: 1151, 1173. editor.c 1151 • V595 The 'lpDataObject' pointer was utilized before it was verified against nullptr. Check lines: 1152, 1176. editor.c 1152 • V595 The 'lpOleCache' pointer was utilized before it was verified against nullptr. Check lines: 1150, 1177. editor.c 1150 • V595 The 'argv' pointer was utilized before it was verified against nullptr. Check lines: 354, 358. rundll32.c 354 • V595 The 'pServiceStatus' pointer was utilized before it was verified against nullptr. Check lines: 131, 144. query.c 131 • V595 The 'pServiceStatus' pointer was utilized before it was verified against nullptr. Check lines: 191, 197. query.c 191 • V595 The 'oleobj' pointer was utilized before it was verified against nullptr. Check lines: 357, 365. dochost.c 357 • V595 The 'urlfile' pointer was utilized before it was verified against nullptr. Check lines: 220, 235. iexplore.c 220 • V595 The 'urlobj' pointer was utilized before it was verified against nullptr. Check lines: 223, 238. iexplore.c 223 • V595 The 'pDrvDefExt' pointer was utilized before it was verified against nullptr. Check lines: 161, 177. drive.cpp 161 • V595 The 'pszList' pointer was utilized before it was verified against nullptr. Check lines: 589, 606. dialogs.cpp 589 • V595 The 'pFileDefExt' pointer was utilized before it was verified against nullptr. Check lines: 142, 157. fprop.cpp 142 • V595 The 'pidl' pointer was utilized before it was verified against nullptr. Check lines: 757, 760. pidl.cpp 757 • V595 The 'pidlInOut' pointer was utilized before it was verified against nullptr. Check lines: 136, 156. shlfolder.cpp 136 • V595 The 'cm' pointer was utilized before it was verified against nullptr. Check lines: 1296, 1303. shlexec.cpp 1296 • V595 The 'pcchOut' pointer was utilized before it was verified against nullptr. Check lines: 2238, 2240. url.c 2238 • V595 The 'NewSubsystem' pointer was utilized before it was verified against nullptr. Check lines: 500, 502. smsubsys.c 500 • V595 The 'OutputMdl' pointer was utilized before it was verified against nullptr. Check lines: 1382, 1408. dispatch.c 1382 • V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 100, 101. buffer.c 100 • V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 159, 160. buffer.c 159 • V595 The 'DstBuffer' pointer was utilized before it was verified against nullptr. Check lines: 266, 267. buffer.c 266 • V595 The 'SrcBuffer' pointer was utilized before it was verified against nullptr. Check lines: 277, 278. buffer.c 277
  • 19. • V595 The 'lpszTemp' pointer was utilized before it was verified against nullptr. Check lines: 997, 1000. taskmgr.c 997 • V595 The 'AtaReq' pointer was utilized before it was verified against nullptr. Check lines: 4944, 4972. id_ata.cpp 4944 • V595 The 'AtaReq' pointer was utilized before it was verified against nullptr. Check lines: 4899, 4925. id_ata.cpp 4899 • V595 The 'Srb' pointer was utilized before it was verified against nullptr. Check lines: 9664, 9666. id_ata.cpp 9664 • V595 The 'Srb' pointer was utilized before it was verified against nullptr. Check lines: 9652, 9666. id_ata.cpp 9652 • V595 The 'builder->uri' pointer was utilized before it was verified against nullptr. Check lines: 5250, 5262. uri.c 5250 • V595 The 'pInstance' pointer was utilized before it was verified against nullptr. Check lines: 387, 388. ddeserver.c 387 • V595 The 'current_line' pointer was utilized before it was verified against nullptr. Check lines: 524, 529. edit.c 524 • V595 The 'es' pointer was utilized before it was verified against nullptr. Check lines: 5195, 5214. edit.c 5195 • V595 The 'pBSMInfo' pointer was utilized before it was verified against nullptr. Check lines: 3146, 3158. message.c 3146 • V595 The 'pHwnd' pointer was utilized before it was verified against nullptr. Check lines: 673, 679. window.c 673 • V595 The 'levels' pointer was utilized before it was verified against nullptr. Check lines: 1572, 1578. usp10.c 1572 • V595 The '* root' pointer was utilized before it was verified against nullptr. Check lines: 548, 553. check.c 548 • V595 The 'VbeInfo' pointer was utilized before it was verified against nullptr. Check lines: 206, 207. vbemodes.c 206 • V595 The 'pClient->hPins' pointer was utilized before it was verified against nullptr. Check lines: 237, 242. entry.c 237 • V595 The 'Context.ProcessData' pointer was utilized before it was verified against nullptr. Check lines: 853, 861. exitros.c 853 • V595 The 'pstrLibName' pointer was utilized before it was verified against nullptr. Check lines: 136, 140. callback.c 136 • V595 The 'psurfColor' pointer was utilized before it was verified against nullptr. Check lines: 1176, 1182. cursoricon.c 1176 • V595 The 'DestRect' pointer was utilized before it was verified against nullptr. Check lines: 33, 36. copybits.c 33 • V595 The 'SourcePoint' pointer was utilized before it was verified against nullptr. Check lines: 34, 36. copybits.c 34 • V595 The 'pdesk->pDeskInfo->spwnd' pointer was utilized before it was verified against nullptr. Check lines: 148, 150. desktop.c 148 • V595 The 'psurfPattern' pointer was utilized before it was verified against nullptr. Check lines: 342, 365. engbrush.c 342 • V595 The 'WndPrev' pointer was utilized before it was verified against nullptr. Check lines: 62, 65. focus.c 62
  • 20. • V595 The 'Wnd' pointer was utilized before it was verified against nullptr. Check lines: 374, 384. focus.c 374 • V595 The 'pti->rpdesk' pointer was utilized before it was verified against nullptr. Check lines: 358, 364. input.c 358 • V595 The 'pStrokes' pointer was utilized before it was verified against nullptr. Check lines: 1941, 1947. path.c 1941 • V595 The 'dc' pointer was utilized before it was verified against nullptr. Check lines: 933, 958. palette.c 933 • V595 The 'SourceRect' pointer was utilized before it was verified against nullptr. Check lines: 402, 430. stretchblt.c 402 • V595 The 'Wnd' pointer was utilized before it was verified against nullptr. Check lines: 390, 403. windc.c 390 • V595 The 'pPatterns' pointer was utilized before it was verified against nullptr. Check lines: 512, 533. info.c 512 • V595 The 'converter' pointer was utilized before it was verified against nullptr. Check lines: 2164, 2172. info.c 2164 • V595 The 'context' pointer was utilized before it was verified against nullptr. Check lines: 95, 100. texture.c 95 • V595 The 'Globals.win_list' pointer was utilized before it was verified against nullptr. Check lines: 560, 583. winhelp.c 560 • V595 The 'lpwh' pointer was utilized before it was verified against nullptr. Check lines: 1400, 1414. ftp.c 1400 • V595 The 'optval' pointer was utilized before it was verified against nullptr. Check lines: 284, 296. sockctrl.c 284 Macros Macros are bad - of that I'm still dead sure. You should use regular functions wherever possible. Someone felt too lazy to make a full-fledged function stat64_to_stat() in ReactOS and contented himself/herself with creating a shit-macro. This is what it looks like: #define stat64_to_stat(buf64, buf) buf->st_dev = (buf64)->st_dev; buf->st_ino = (buf64)->st_ino; buf->st_mode = (buf64)->st_mode; buf->st_nlink = (buf64)->st_nlink; buf->st_uid = (buf64)->st_uid; buf->st_gid = (buf64)->st_gid; buf->st_rdev = (buf64)->st_rdev; buf->st_size = (_off_t)(buf64)->st_size; buf->st_atime = (time_t)(buf64)->st_atime;
  • 21. buf->st_mtime = (time_t)(buf64)->st_mtime; buf->st_ctime = (time_t)(buf64)->st_ctime; Let's see how this macro is used in the _tstat function: int CDECL _tstat(const _TCHAR* path, struct _stat * buf) { int ret; struct __stat64 buf64; ret = _tstat64(path, &buf64); if (!ret) stat64_to_stat(&buf64, buf); return ret; } Do you think the 'stat64_to_stat' macro is executed if the 'ret' variable equals zero? It is absolutely not. The macro is expanded into a set of separate lines. That's why only the "buf->st_dev = (buf64)- >st_dev;" line refers to the 'if' operator, while all the other lines will be executed all the time! There are other fragments that employ this incorrect macro: • V640 The code's operational logic does not correspond with its formatting. The second statement will always be executed. It is possible that curly brackets are missing. stat.c 35 • V640 The code's operational logic does not correspond with its formatting. The second statement will always be executed. It is possible that curly brackets are missing. stat.c 47 • V640 The code's operational logic does not correspond with its formatting. The second statement will always be executed. It is possible that curly brackets are missing. stat.c 58 Conditions which are always true/false Here's an issue when an always true condition might cause an infinite loop. #define DISKREADBUFFER_SIZE HEX(10000) typedef unsigned short USHORT, *PUSHORT; static VOID DetectBiosDisks(....) { USHORT i; ....
  • 22. Changed = FALSE; for (i = 0; ! Changed && i < DISKREADBUFFER_SIZE; i++) { Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd; } .... } V547 Expression 'i < 0x10000' is always true. The value range of unsigned short type: [0, 65535]. xboxhw.c 358 The loop is meant to search through the DISKREADBUFFER array for a byte whose value doesn't equal '0xCD'. If such a byte doesn't exist, the 'Changed' variable always has the FALSE value. In this case, the "i < DISKREADBUFFER_SIZE" expression is the truncation condition. As this expression is always true, the program will start iterating an infinite loop. The error is this: the 'i' variable has the 'unsigned short' type. It can take values within the range from 0 to 65535. These values are always below '0x10000'. A typical error I often see in many projects is the assumption that SOCKET is a signed variable. It's not so. To be more exact, it depends on the library implementation. typedef UINT_PTR SOCKET; #define ADNS_SOCKET SOCKET struct adns__state { .... ADNS_SOCKET udpsocket, tcpsocket; .... }; static int init_finish(adns_state ads) { .... if (ads->udpsocket<0) { r= errno; goto x_free; } .... } V547 Expression 'ads->udpsocket < 0' is always false. Unsigned type value is never < 0. setup.c 539
  • 23. The 'udpsocket' variable is unsigned, which means that the 'ads->udpsocket < 0' condition is always false. To figure out where the error has occurred we need to use the SOCKET_ERROR constant. Similar socket handling errors can be found here: • V547 Expression 'fd < 0' is always false. Unsigned type value is never < 0. event.c 117 • V547 Expression 'ads->udpsocket >= 0' is always true. Unsigned type value is always >= 0. check.c 105 • V547 Expression 'ads->tcpsocket >= 0' is always true. Unsigned type value is always >= 0. check.c 114 • V547 Expression 'ads->tcpsocket >= 0' is always true. Unsigned type value is always >= 0. check.c 123 Incorrect checks may lead to buffer overflows and, consequently, to undefined behavior. Here's a sample where the exception handler fails. BOOL PrepareService(LPCTSTR ServiceName) { DWORD LeftOfBuffer = sizeof(ServiceKeyBuffer) / sizeof(ServiceKeyBuffer[0]); .... LeftOfBuffer -= _tcslen(SERVICE_KEY); .... LeftOfBuffer -= _tcslen(ServiceName); .... LeftOfBuffer -= _tcslen(PARAMETERS_KEY); .... if (LeftOfBuffer < 0) { DPRINT1("Buffer overflow for service name: '%s'n", ServiceName); return FALSE; } .... }
  • 24. V547 Expression 'LeftOfBuffer < 0' is always false. Unsigned type value is never < 0. svchost.c 51 The 'LeftOfBuffer' variable should most likely be a signed one. It often happens that unsigned variables cause function return values to be checked incorrectly. Here's such a code: static INT FASTCALL MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) { UINT Id; .... Id = NtUserMenuItemFromPoint(....); .... if (0 <= Id && MenuGetRosMenuItemInfo(MenuInfo.Self, Id, &ItemInfo) && MenuInfo.FocusedItem == Id) .... } V547 Expression '0 <= Id' is always true. Unsigned type value is always >= 0. menu.c 2663 The NtUserMenuItemFromPoint() function can return the negative value (-1). The error occurs because of the 'Id' variable being unsigned. That results in the '0 <= Id' check being meaningless. A function parameter is checked incorrectly in the following code fragment. typedef unsigned int GLuint; const GLubyte *_mesa_get_enabled_extension( struct gl_context *ctx, GLuint index) { const GLboolean *base; size_t n; const struct extension *i;
  • 25. if (index < 0) return NULL; .... } V547 Expression 'index < 0' is always false. Unsigned type value is never < 0. extensions.c 936 It's not interesting to discuss V547 warnings any further, so let me just cite the remaining fragments I've noticed: • V547 Expression 'index >= 0' is always true. Unsigned type value is always >= 0. st_glsl_to_tgsi.cpp 4013 • V547 Expression 'index >= 0' is always true. Unsigned type value is always >= 0. st_glsl_to_tgsi.cpp 4023 • V547 Expression 'index < 0' is always false. Unsigned type value is never < 0. st_glsl_to_tgsi.cpp 4027 • V547 Expression '(src[i]) < (0)' is always false. Unsigned type value is never < 0. texstore.c 3692 • V547 Expression '(src[i]) < (0)' is always false. Unsigned type value is never < 0. texstore.c 3759 • V547 Expression 'CommitReduction >= 0' is always true. Unsigned type value is always >= 0. virtual.c 4784 • V547 Expression 'Info->nPage < 0' is always false. Unsigned type value is never < 0. scrollbar.c 428 • V547 Expression 'Entry->Id <= 0xffff' is always true. The value range of unsigned short type: [0, 65535]. res.c 312 Undefined behavior and Unspecified behavior. You must not shift negative numbers - even if the code that has these shifts seems to work successfully for a long time. It is incorrect. It leads to undefined or unspecified behavior. The issue may reveal itself when you start using another platform or another compiler or change optimization switches. I discussed negative number shifts in detail in the article "Wade not in unknown waters. Part three". This is an incorrect code sample: static INLINE int wrap(short f, int shift) { .... if (f < (-16 << shift)) .... }
  • 26. V610 Undefined behavior. Check the shift operator '<<. The left operand '-16' is negative. vl_mpeg12_bitstream.c 653 No one knows what the (-16 << shift) expression is equal to. Other similar fragile code samples can be found in the following fragments: • V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative. jdarith.c 460 • V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative. jdhuff.c 930 • V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative. layer1.c 86 • V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative. layer1.c 90 • V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative. layer1.c 97 • V610 Undefined behavior. Check the shift operator '<<. The left operand '(- 1)' is negative. layer1.c 118 • V610 Unspecified behavior. Check the shift operator '>>. The left operand is negative ('i' = [- 4096..4095]). tabinit.c 269 • V610 Unspecified behavior. Check the shift operator '>>. The left operand is negative ('i' = [- 4096..4095]). tabinit.c 274 • V610 Undefined behavior. Check the shift operator '<<. The left operand '-1' is negative. mppc.c 351 Incorrect format specifier Let's have a look at several samples demonstrating incorrect ways of using variadic functions to print variable values. UINT64 Size; static HRESULT STDMETHODCALLTYPE CBindStatusCallback_OnProgress(....) { .... _tprintf(_T("Length: %ulln"), This->Size); .... } V576 Incorrect format. Consider checking the second actual argument of the 'wprintf' function. The argument is expected to be not greater than 32-bit. dwnl.c 228 You should write "%llu" instead of "%ull" to print a 64-bit variable.
  • 27. Using "%u" is one more incorrect way to print the pointer value. There exists the "%p" specifier for this purpose. However, the programmer must have made a misprint in the code below, and it is "%s" that should have been written there. BOOL CALLBACK EnumPickIconResourceProc( HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam) { .... swprintf(szName, L"%u", lpszName); .... } V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function. To print the value of pointer the '%p' should be used. dialogs.cpp 66 The errors when Unicode and non-Unicode strings are used together are very frequent. For example, if you need to print a UNICODE character in the fprintf() function, you should use '%C', not '%c'. Here's an incorrect code sample with that error: int WINAPI WinMain(....) { LPWSTR *argvW = NULL; .... fprintf(stderr, "Unknown option "%c" in Repair moden", argvW[i][j]); .... } V576 Incorrect format. Consider checking the third actual argument of the 'fprintf' function. The char type argument is expected. msiexec.c 655 The same bugs can be found in the following fragments: • V576 Incorrect format. Consider checking the third actual argument of the 'fprintf' function. The char type argument is expected. msiexec.c 705 • V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function. The pointer to string of wchar_t type symbols is expected. sminit.c 1831
  • 28. • V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function. The pointer to string of char type symbols is expected. bootsup.c 600 • V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function. The pointer to string of char type symbols is expected. guiconsole.c 328 • V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function. The pointer to string of char type symbols is expected. guiconsole.c 332 • V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function. The pointer to string of char type symbols is expected. guiconsole.c 378 • V576 Incorrect format. Consider checking the third actual argument of the 'swprintf' function. The pointer to string of char type symbols is expected. guiconsole.c 382 Operation priorities I've found several errors related to operation priorities confusion. static HRESULT BindStatusCallback_create(....) { HRESULT hr; .... if ((hr = SafeArrayGetUBound(sa, 1, &size) != S_OK)) { SafeArrayUnaccessData(sa); return hr; } .... } V593 Consider reviewing the expression of the 'A = B != C' kind. The expression is calculated as following: 'A = (B != C)'. httprequest.c 692 According to operation priorities in C/C++, the "SafeArrayGetUBound(sa, 1, &size) != S_OK" comparison is executed in the first place, while it is only then that assignment is performed. However, the condition will work well. The incorrect thing is that the 'hr' variable will store 0 or 1 instead of the status. The function will therefore return an incorrect status. Here is another very similar error: static void symt_fill_sym_info(....) { ....
  • 29. if (sym->tag != SymTagPublicSymbol || !(dbghelp_options & SYMOPT_UNDNAME) || (sym_info->NameLen = UnDecorateSymbolName(name, sym_info->Name, sym_info->MaxNameLen, UNDNAME_NAME_ONLY) == 0)) .... } V593 Consider reviewing the expression of the 'A = B == C' kind. The expression is calculated as following: 'A = (B == C)'. symbol.c 801 The code is difficult to read. But if you look close, you'll notice that the UnDecorateSymbolName() function's return result is compared to zero first, then the comparison result is put into the 'sym_info- >NameLen' variable. Array index out of bounds FF_T_WCHAR FileName[FF_MAX_FILENAME]; FF_T_UINT32 FF_FindEntryInDir(....) { .... FF_T_WCHAR *lastPtr = pDirent->FileName + sizeof(pDirent->FileName); .... lastPtr[-1] = '0'; .... } V594 The pointer steps out of array's bounds. ff_dir.c 260 The programmer intended 'lastPtr' to point at a memory cell after that last character in the string. That won't happen though. The string consists of WCHAR characters. It means that it's the buffer size that is added, not the number of characters. And that value is twice larger than necessary. When writing the null character, the array index out of bounds error with all its implications will occur. This is what the fixed code looks like: FF_T_WCHAR *lastPtr = pDirent->FileName + sizeof(pDirent->FileName) / sizeof(pDirent->FileName[0]);
  • 30. The strncat() function is pretty dangerous regarding this class of bugs. The reason is that it's not the total buffer size that the last argument should specify, but how many more characters can be put into it. Because of misunderstanding this thing, programmers write unsafe code: void shell(int argc, const char *argv[]) { char CmdLine[MAX_PATH]; .... strcpy( CmdLine, ShellCmd ); if (argc > 1) { strncat(CmdLine, " /C", MAX_PATH); } for (i=1; i<argc; i++) { strncat(CmdLine, " ", MAX_PATH); strncat(CmdLine, argv[i], MAX_PATH); } .... } V645 The 'strncat' function call could lead to the 'CmdLine' buffer overflow. The bounds should not contain the size of the buffer, but a number of characters it can hold. cmds.c 1314 V645 The 'strncat' function call could lead to the 'CmdLine' buffer overflow. The bounds should not contain the size of the buffer, but a number of characters it can hold. cmds.c 1319 V645 The 'strncat' function call could lead to the 'CmdLine' buffer overflow. The bounds should not contain the size of the buffer, but a number of characters it can hold. cmds.c 1320 It cannot be guaranteed that no buffer overflow occurs. To learn more about this class of errors, see the documentation (V645 diagnostic). A similar trouble can be found here: V645 The 'wcsncat' function call could lead to the 'szFileName' buffer overflow. The bounds should not contain the size of the buffer, but a number of characters it can hold. logfile.c 50
  • 31. Repetitions Repetitions are related to conditions and can be of two types. Type one. The same operations are executed regardless of the condition. For example: void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal) { .... if(fNormal) hOld = SelectObject(hdc, hhi); else hOld = SelectObject(hdc, hhi); .... } V523 The 'then' statement is equivalent to the 'else' statement. cardbutton.cpp 86 Another example: NTSTATUS NTAPI CPortPinWavePci::HandleKsStream(IN PIRP Irp) { .... if (m_Capture) m_Position.WriteOffset += Data; else m_Position.WriteOffset += Data; .... } V523 The 'then' statement is equivalent to the 'else' statement. pin_wavepci.cpp 562 One more repetition of a large code fragment can be found here: V523 The 'then' statement is equivalent to the 'else' statement. tab.c 1043
  • 32. Type two. A condition is repeated. It appears that the second condition will never hold. For example: #define LOCALE_SSHORTDATE 31 #define LOCALE_SLONGDATE 32 MSVCRT__locale_t CDECL MSVCRT__create_locale(....) { .... if (time_data[i]== LOCALE_SSHORTDATE && !lcid[LC_TIME]) { size += ....; } else if(time_data[i]== LOCALE_SSHORTDATE && !lcid[LC_TIME]) { size += ....; } else { .... } V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 1193, 1195. locale.c 1193 I suppose that the second check should have been written in the following way: if (time_data[i]==LOCALE_SLONGDATE && !lcid[LC_TIME]) Other similar repeating checks can be found here: • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 1225, 1228. locale.c 1225 • V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 1241, 1244. locale.c 1241 Miscellaneous Now let's have a look at diverse bugs. Incorrect calculation of the characters number typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength;
  • 33. PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; UNICODE_STRING DosDevices = RTL_CONSTANT_STRING(L"DosDevices"); NTSTATUS CreateNewDriveLetterName(....) { .... DriveLetter->Buffer[ sizeof(DosDevices.Buffer) / sizeof(WCHAR)] = (WCHAR)Letter; .... } V514 Dividing sizeof a pointer 'sizeof (DosDevices.Buffer)' by another value. There is a probability of logical error presence. mountmgr.c 164 It seems that the "sizeof(DosDevices.Buffer) / sizeof(WCHAR)" expression was intended to calculate the number of characters in a string. But 'DosDevices.Buffer' is just a pointer. As a result, the pointer size is divided by 'sizeof(WCHAR)'. Other similar errors can be found here: • V514 Dividing sizeof a pointer 'sizeof (DosDevices.Buffer)' by another value. There is a probability of logical error presence. mountmgr.c 190 • V514 Dividing sizeof a pointer 'sizeof (DosDevices.Buffer)' by another value. There is a probability of logical error presence. symlink.c 937 Here's another case of incorrect calculation of the number of characters in strings. In the following sample it's multiplication instead of division: VOID DisplayEvent(HWND hDlg) { WCHAR szEventType[MAX_PATH]; WCHAR szTime[MAX_PATH]; WCHAR szDate[MAX_PATH]; WCHAR szUser[MAX_PATH];
  • 34. WCHAR szComputer[MAX_PATH]; .... ListView_GetItemText(...., sizeof(szEventType)*sizeof(WCHAR)); ListView_GetItemText(...., sizeof(szDate)*sizeof(WCHAR)); ListView_GetItemText(...., sizeof(szTime)*sizeof(WCHAR)); ListView_GetItemText(...., sizeof(szSource)*sizeof(WCHAR)); ListView_GetItemText(...., sizeof(szCategory)*sizeof(WCHAR)); ListView_GetItemText(...., sizeof(szEventID)*sizeof(WCHAR)); ListView_GetItemText(...., sizeof(szUser)*sizeof(WCHAR)); ListView_GetItemText(...., sizeof(szComputer)*sizeof(WCHAR)); .... } It results in the ListView_GetItemText() function assuming that the buffer size is larger than it actually is. It may potentially cause a buffer overflow. Function return result not used #define strcmpW(s1,s2) wcscmp((s1),(s2)) static HRESULT WINAPI IEnumDMO_fnNext(....) { .... if (Names[count]) strcmpW(Names[count], szValue); .... } V530 The return value of function 'wcscmp' is required to be utilized. dmoreg.c 621 Uninitialized variable HRESULT WINAPI INetCfgComponentControl_fnApplyRegistryChanges( INetCfgComponentControl * iface) {
  • 35. HKEY hKey; .... if (RegCreateKeyExW(hKey, L"SYSTEMCurrentControlSet....", ....) == ERROR_SUCCESS) .... } V614 Uninitialized pointer 'hKey' used. Consider checking the first actual argument of the 'RegCreateKeyExW' function. tcpipconf_notify.c 3138 While calling the RegCreateKeyExW() function, the 'hKey' variable is not initialized yet. High-order bits that may be significant get truncated HRESULT WINAPI CRecycleBin::CompareIDs(....) { .... return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (unsigned short)memcmp(pidl1->mkid.abID, pidl2->mkid.abID, pidl1->mkid.cb)); } V642 Saving the 'memcmp' function result inside the 'unsigned short' type variable is inappropriate. The significant bits could be lost breaking the program's logic. recyclebin.cpp 542 This type of errors is very much unobvious. I suggest that you read the description of the V642 diagnostic to understand the point. To put it briefly, the trouble is that the memcmp() function doesn't necessarily return only values -1, 0, and 1. It may well return, for instance, number 0x100000. When casting this number to the "unsigned short" type, it will turn into 0. One-time loops I've encountered several very strange loops. They don't have the 'continue' operator yet have the unconditional operator 'break'. It means that the loop bodies are executed only once. Here's an example of that kind. VOID NTAPI IKsPin_PinCentricWorker(IN PVOID Parameter) { .... do
  • 36. { DPRINT("IKsPin_PinCentricWorker calling " "Pin Process Routinen"); Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin); DPRINT("IKsPin_PinCentricWorker Status %lx, " "Offset %lu Length %lun", Status, This->LeadingEdgeStreamPointer.Offset, This->LeadingEdgeStreamPointer.Length); break; } while(This->IrpCount); } V612 An unconditional 'break' within a loop. pin.c 1839 Other similar strange loops: • V612 An unconditional 'break' within a loop. regexp.c 3633 • V612 An unconditional 'break' within a loop. hlpfile.c 1131 Strange things There are code fragments which are probably not bugs. They are simply very strange. For example: BOOLEAN NTAPI Ext2MakeNewDirectoryEntry(....) { .... MinLength = HeaderLength + NameLength; MinLength = (HeaderLength + NameLength + 3) & 0xfffffffc; .... } V519 The 'MinLength' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 948, 949. metadata.c 949 The 'MinLength' variable is assigned different values twice in a row. Perhaps it somehow helps in debugging - I don't know. I would consider this an error, but there are many fragments of that kind throughout the code. I won't mention them, as the post is already huge enough.
  • 37. Conclusion I fail to make any wise conclusions. ReactOS is a rapidly growing and developing project. Hence it contains quite a lot of errors. As you can see from this article, static analysis can catch a good deal of them in a project like that. If one used it regularly, the benefit would be just invaluable. Follow us on Twitter to keep track of PVS-Studio's new interesting feats in its struggle against bugs. There we also post links to interesting articles on C/C++ programming and related subjects.