int main(void) {
uint32_t hk=100*1000;
uint64_t hk2 = hk * hk;
uint64_t hk2c = (uint64_t)hk * hk;
int same = (hk2==hk2c); // V547
printf("%u^2 = %lu %s %lu\n", hk, hk2c, same ? "==" : "!=", hk2);
return same==0;
}
On Ubuntu 22.10 both GCC and clang generate programs which output
100000^2 = 10000000000 != 1410065408
PVS-Studio give warnings:
General Analysis 100k_squared.c:9 High V547 Expression 'hk2 == hk2c' is always false.
General Analysis 100k_squared.c:10 Medium V547 Expression 'same' is always false.
cppcheck v2.9, however, reports
100k_squared.c:10:45: style: Condition 'same' is always true [knownConditionTrueFalse]
printf("%u^2 = %lu %s %lu\n", hk, hk2c, same ? "==" : "!=", hk2);
... ...
(so PVS says same is always false but cppcheck says it is always true).
The issue is that (sadly, but probably in line with the standards)
the RHS of
uint64_t hk2 = hk * hk;
is evaluated as a uint32_t and then assigned, but cppcheck seems to
miss this subtlety.
All quoted results appear to be the same if this program, but with
static_casts, is considered as C++.
Thanks,
--
Andrew C. Aitchison Kendal, UK
andrew@aitchison.me.uk
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks. I am replying here because I am uneasy about putting passwords into random websites to generate an .htpasswd, so cannot reply to the ticket.
I am not sure I have explained my issue clearly enough.
The real bug as I see it is in the C/C++ standards: (uint32) * (uint32) should generate a (uint64)
(to avoid overflow). Since that is not what the language does, my bug is to expect
uint32 a = 100000;
uint64_t b = a * a;
to set b to 10^10
I would like cppcheck to warn me that although b could hold the un-truncated product, the product has been truncated to a lower precision than b before being stored.
I do not particularly expect a warning when on
unit32 c = a * a;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I would like cppcheck to warn me that although b could hold the un-truncated product, the product has been truncated to a lower precision than b before being stored.
Thanks for pointing that out! I agree. hmm.. Cppcheck has such a checking. See this test case:
I am looking at this C program
include <stdio.h></stdio.h>
include <stdint.h></stdint.h>
int main(void) {
uint32_t hk=100*1000;
uint64_t hk2 = hk * hk;
uint64_t hk2c = (uint64_t)hk * hk;
int same = (hk2==hk2c); // V547
printf("%u^2 = %lu %s %lu\n", hk, hk2c, same ? "==" : "!=", hk2);
return same==0;
}
On Ubuntu 22.10 both GCC and clang generate programs which output
100000^2 = 10000000000 != 1410065408
PVS-Studio give warnings:
General Analysis 100k_squared.c:9 High V547 Expression 'hk2 == hk2c' is always false.
General Analysis 100k_squared.c:10 Medium V547 Expression 'same' is always false.
cppcheck v2.9, however, reports
100k_squared.c:10:45: style: Condition 'same' is always true [knownConditionTrueFalse]
printf("%u^2 = %lu %s %lu\n", hk, hk2c, same ? "==" : "!=", hk2);
... ...
(so PVS says same is always false but cppcheck says it is always true).
The issue is that (sadly, but probably in line with the standards)
the RHS of
uint64_t hk2 = hk * hk;
is evaluated as a uint32_t and then assigned, but cppcheck seems to
miss this subtlety.
All quoted results appear to be the same if this program, but with
static_casts, is considered as C++.
Thanks,
--
Andrew C. Aitchison Kendal, UK
andrew@aitchison.me.uk
Thanks for reporting, ticket is here: https://trac.cppcheck.net/ticket/11503
Thanks. I am replying here because I am uneasy about putting passwords into random websites to generate an .htpasswd, so cannot reply to the ticket.
I am not sure I have explained my issue clearly enough.
The real bug as I see it is in the C/C++ standards: (uint32) * (uint32) should generate a (uint64)
(to avoid overflow). Since that is not what the language does, my bug is to expect
uint32 a = 100000;
uint64_t b = a * a;
to set b to 10^10
I would like cppcheck to warn me that although b could hold the un-truncated product, the product has been truncated to a lower precision than b before being stored.
I do not particularly expect a warning when on
unit32 c = a * a;
Thanks for pointing that out! I agree. hmm.. Cppcheck has such a checking. See this test case:
https://github.com/danmar/cppcheck/blob/main/test/testtype.cpp#L340
I am not sure why it doesn't warn. It seems like a false negative.
That check is specific to type
long
for some reason, see https://trac.cppcheck.net/ticket/11389#comment:2Thanks CHR. I agree with what you say in that ticket. It should check for any such widening conversion.