On 24/03/2019 13:53, Xi Ruoyao wrote:
On 2019-03-24 12:45 +0000, Jonny Grant wrote:
Hello!
Is this an issue? G++ doesn't identify problem in this test case doesn't
when compiling or running.
"hello" is not displayed, std::cout never works again after nullptr.
// g++-8 -Wall -Wextra -Wconversion-null -Wno-nonnull-compare
-Wzero-as-null-pointer-constant
-fsanitize=null,returns-nonnull-attribute,signed-integer-
overflow,leak,undefined,address
-o cout cout.cpp
#include <iostream>
int main()
{
const char * p = nullptr;
std::cout << p;
std::cout << "hello";
}
The standard *Requires* p is not a null pointer here (N4618 27.7.3.2.4 p3). So
if p is a null pointer, the implementation (GCC and libstdc++) can do anything.
Libstdc++ is friendly. It does not abort, raise exception, or run
/usr/game/starwar, it just sets ios::badbit to cout (ostream:559) so actually
you can detect this issue by checking the state of cout. But do NOT rely on
this behavior. This is really undefined.
Because libstdc++ is so friendly, the sanitizer don't even know this is an
undefined behavior. And, it can not sanitize undefined behaviors in
libstdc++.so because it was built w/o -fsanitize= option.
Well, if you want this to be detected at compile time, maybe you can convince
Jonathan to add an __attribute__((nonnull(2))) to operator<<(basic_ostream&,
const char *). Then this case can be detected with "-O -Wnonnull".
Hello Xi
Sounds reasonable to add the nonnull attribute. But I'm not an expert,
so let's wait for Jonathan's reply!
Can I ask, for this nonnull attribute, would it also detect for
std::cin, std::err, std::clog as well as std::cout ? Worth adding for
std::wcin, std::wcout, std::cerr, std::wclog too.
Are there other places where nullptr would not be valid? There are lots
of classes, eg <streambuf>
BTW, this other test case below using std::cin does cause SEGV. What is
better, SEGV or ignore the nullptr and set ios::badbit too?
Santizer does seem to find this one in libstdc++
I didn't even need to add -g for syms!
// g++-8 -O -Wnonnull -Wall -Wextra -Wconversion-null
-Wno-nonnull-compare -Wzero-as-null-pointer-constant
-fsanitize=null,returns-nonnull-attribute,signed-integer-overflow,leak,undefined,address
-o cout cout.cpp
#include <iostream>
int main()
{
char * p = nullptr;
std::cout << "press a key, and then press return\n";
std::cin >> p;
}
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2534==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000
(pc 0x7fa4504d40a0 bp 0x000000000000 sp 0x7ffe0c21fd30 T0)
==2534==The signal is caused by a WRITE memory access.
==2534==Hint: address points to the zero page.
#0 0x7fa4504d409f in std::basic_istream<char,
std::char_traits<char> >& std::operator>><char, std::char_traits<char>
>(std::basic_istream<char, std::char_traits<char> >&, char*)
(/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xab09f)
#1 0x55a36acccba9 in main (/home/jonny/code/cout+0xba9)
#2 0x7fa44f339b96 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#3 0x55a36acccad9 in _start (/home/jonny/code/cout+0xad9)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
(/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xab09f) in
std::basic_istream<char, std::char_traits<char> >& std::operator>><char,
std::char_traits<char> >(std::basic_istream<char, std::char_traits<char>
>&, char*)
==2534==ABORTING