wcslen() returns incorrect result when pragma pack used

431 views Asked by At

I've found that wcslen() returns incorrect result on gcc(and correct on msvc) when source is wchar_t array, member of packed struct. I know on linux sizeof(wchar_t) == 4 and on windows its 2 but still can't understand how packing affects wcslen() function. If I change wchar_t/wcslen to char/strlen it works as expected.

#include <cstdint>
#include <cwchar>
#include <cstring>

#pragma pack(push, 1)

struct A
{
    uint8_t c;
};

struct B
{
    A  a;
    wchar_t buf[9];
};

#pragma pack(pop)


int main()
{
    const wchar_t* s = L"05.00.06";
    B b{};
    memcpy(b.buf, s, wcslen(s) * sizeof(wchar_t));

    return wcslen(b.buf);
}

Why this code compiled with gcc returns 7? It should return 8(as msvc does). Btw copied bytes are correct(b.buf[7] == '6').

1

There are 1 answers

1
David Schwartz On BEST ANSWER

The behavior of this code is undefined and unpredictable. You're passing the wcslen function an invalid pointer since it doesn't necessarily meet the alignment requirements for its type.

Likely on your platform, the alignment requirement for wchar_t is 2. So the pointer you've passed to wcslen is not valid. You don't see similar behavior with strlen because the alignment requirement is 1 in that case, which means no requirement at all.

Don't operate on packed structures unless you know that you've complied with your platform's alignment requirements. Otherwise, the results are entirely unpredictable. On many platforms, your code will crash.