I have this snippet of code (lets name it problem.cpp
):
#include <string>
using str = std::wstring;
static str foo(str text = str())
{
text.resize(4);
return text;
}
int main()
{
str a = foo();
return 0;
}
GCC (version 12.2.1) called with -O1
and C++20 conformity (g++ problem.cpp -Werror -O1 -std=c++20
) leads to this error:
In file included from /usr/include/features.h:490,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/x86_64-pc-linux-gnu/bits/os_defines.h:39,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/x86_64-pc-linux-gnu/bits/c++config.h:655,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/string:38,
from problem.cpp:1:
In function ‘wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t)’,
inlined from ‘static constexpr std::char_traits<wchar_t>::char_type* std::char_traits<wchar_t>::copy(char_type*, const char_type*, std::size_t)’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/bits/char_traits.h:558:16,
inlined from ‘constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = wchar_t; _Traits = std::char_traits<wchar_t>; _Alloc = std::allocator<wchar_t>]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/bits/basic_string.h:675:23,
inlined from ‘str foo(str)’ at problem.cpp:7:9,
inlined from ‘int main()’ at problem.cpp:12:14:
/usr/include/bits/wchar2.h:39:10: error: call to ‘__wmemcpy_chk_warn’ declared with attribute warning: wmemcpy called with length bigger than size of destination buffer [-Werror=attribute-warning]
39 | return __glibc_fortify_n (wmemcpy, __n, sizeof (wchar_t),
| ^~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
Interestingly, I cannot trigger this error, either by using std::string
(in contrast to std::wstring
), using lower resize values, or anything below C++20 or O1
.
To me, this snippet of code does not look suspicious. Unfortunately, I can't reproduce this with Godbolt. Maybe Godbolt uses another and/or not fortified glibc version? I'm using glibc version 2.36 on Gentoo Linux, but I have seen this on Ubuntu as well. However, before I suspect a bug in glibc or the compiler, I'm reaching out here, if this is in fact a false positive.
Any ideas?
EDIT: In the meantime, I could reproduce a similar error using Godbolt: https://godbolt.org/z/joPaYKK11
g++ -O -D_FORTIFY_SOURCE=2 -std=c++20
– Discardwmemcpy
call is going to be invalid if called and the compiler knows this, because it sees the length being set. However, in realityg
, which is invisible, guarantees that theif
condition is not satisfied. But glibc uses__attribute__(warning)
whenever the object sizes and length argument are known at compile time to not match. The attribute produces a warning whenever the code is not eliminated by optimization. – Ogpuf()
is basically what you get after inlining of thestr
constructors, except that there is one nested function call which isn't inlined (g
in the reduced example) and so its effect unknown to the compiler. – Ogpustd::wstring
is clearly a problem of the standard library implementation. – Triple