troydhanson / uthash

C macros for hash tables and more
Other
4.18k stars 926 forks source link

VS 2019 gives compiler warning C26451 for UT Array #198

Open guywyers opened 4 years ago

guywyers commented 4 years ago

Similar to issue 195 for UT Hash:

Warning C26451 Arithmetic overflow: Using operator '*' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '*' to avoid overflow (io.2).

It seems in this case it's the following line causing the warning: #define _utarray_eltptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j))))

Doesn't seem to be dramatic, but would be nice to have it fixed.

Quuxplusone commented 4 years ago

Can you post a very short C source file that demonstrates the issue?

guywyers commented 4 years ago

Here is a snippet:

static const UT_icd ut_int64_icd UTARRAY_UNUSED = { sizeof(uint64_t),NULL,NULL,NULL };

int main(int argc, char* argv[])
{
    UT_array* part1;
    UT_array* part2;

    utarray_new(part1, &ut_int64_icd);
    utarray_new(part2, &ut_int64_icd);

    uint64_t i;
    for (i = 1; i < 5; ++i)
        utarray_push_back(part1, &i);

    for (; i < 20; ++i)
        utarray_push_back(part2, &i);

    utarray_concat(part1, part2);
}

The last line triggers the warning. I have spend a bit of time tracing it back and ended up in the _utarray_eltptr macro. However, as I said, I do not consider it "life-threatening" so I gave up after about 30 min, so I could be wrong.

Quuxplusone commented 4 years ago

Darn, I thought that with a test case I'd be able to reproduce it in Godbolt, but it seems not. https://godbolt.org/z/x-HB64

Can you simplify that test case at all? For example, is this source file enough to trigger the warning?

#include "utarray.h"
void test(UT_array* part1) {
    int i;
    utarray_push_back(part1, &i);
}

EDIT: @guywyers, how about this one?

#include "utarray.h"
void test(UT_array* part1) {
    utarray_concat(part1, part1);
}

And re compiler options: well, make sure you're using whatever options you were using when you saw the warning before. On Godbolt I was trying to use -W4, but (in MSVC 2017) that wasn't enough to trigger it. Your real project might have some custom options. Make sure you're using the same options as in your real project (and find out what they are, and post them here).

guywyers commented 4 years ago

Nope, that snippet doesn't trigger the warning. Maybe it's some compiler or preprocessor option which is causing this?

guywyers commented 4 years ago

@Quuxplusone: the second snippet triggered the warning. My comiler options are: /JMC /permissive- /GS /W4 /Zc:wchar_t /ZI /Gm- /Od /sdl /Fd"x64\Debug\vc142.pdb" /Zc:inline /fp:precise /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /FC /Fa"x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Fp"x64\Debug\error.pch" /diagnostics:column

Small correction by the way: the warning code is the same (C26451), but the actual message mentions a sum (Using operator '+' etc) and not *

guywyers commented 4 years ago

I had the problem on some other lines of code as well, so I dug a little deeper. The problem comes from size_t. VS2019 typedefs this to unsigned long long and any operation that mixes the use of size_t and unsigned (which is actually unsigned long) will trigger the warning. So the fix would be to replace all occurences of unsigned (as type specification) by size_t. I tried this in my configuration and it fixed the problem.