clang looks at this code:
line 175:
if (!pehdr && dend>0xf8+0x28) {
cli_dbgmsg("UPX: no luck - scanning for PE\n");
pehdr = &dst[dend-0xf8-0x28];
while (pehdr>dst) {
if ((sections=checkpe(dst, *dsize, pehdr, &valign, §cnt)))
break;
pehdr--;
}
line 183: if (!(realstuffsz = pehdr-dst)) pehdr=NULL;
}
And it concludes that you can exit the while loop (Loop condition is false execution continues on line 183), and at line 183 you take the false branch.
But that can't happen.
dend > 0xf8+0x28 => pehdr > dst to begin with.
Then you loop once through the while (pehdr > dst) {... pehdr--;} loop, and break out because the loop condition is false => pehdr == dst.
Now pehdr - dst = 0 => !(realstuffsz = pehdr-dst) => true => you can only take the true branch (if you've broken out of the loop because loop condition was false).
Extended Description
See https://wwws.clamav.net/bugzilla/show_bug.cgi?id=1910
clang looks at this code: line 175: if (!pehdr && dend>0xf8+0x28) { cli_dbgmsg("UPX: no luck - scanning for PE\n"); pehdr = &dst[dend-0xf8-0x28]; while (pehdr>dst) { if ((sections=checkpe(dst, *dsize, pehdr, &valign, §cnt))) break; pehdr--; } line 183: if (!(realstuffsz = pehdr-dst)) pehdr=NULL; }
And it concludes that you can exit the while loop (Loop condition is false execution continues on line 183), and at line 183 you take the false branch.
But that can't happen.
dend > 0xf8+0x28 => pehdr > dst to begin with. Then you loop once through the while (pehdr > dst) {... pehdr--;} loop, and break out because the loop condition is false => pehdr == dst. Now pehdr - dst = 0 => !(realstuffsz = pehdr-dst) => true => you can only take the true branch (if you've broken out of the loop because loop condition was false).