Re: std::cout breaks after nullptr

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





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









[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux