mateidavid/zstr

Invalid string resizing length bug

lightvector opened this issue · 3 comments

#else
// GNU-specific strerror_r()
auto p = strerror_r(errno, &buff[0], buff.size());
std::string tmp(p, std::strlen(p));
std::swap(buff, tmp);
#endif
buff.resize(buff.find('\0'));
return buff;

In the GNU-specific strerror_r() case, line 42 here is buggy. Because the string has been swapped with "tmp", it will not contain a null character, and then it will attempt to invalidly resize to be of size std::string::npos, which is of course undesirable. (It will of course still be null terminated, but std::string::find will not find a null character within the body of the string, which is the problem).

std::string buff(80, '\0');

Also, for what it's worth, 80 byte buffer here might be a bit on the small side, and may cause unnecessary truncation of errors on some OSes in some locales, at least this is my reading of searching online such as https://stackoverflow.com/questions/423248/what-size-should-i-allow-for-strerror-r#comment5466341_423301

Going to 256 or 512 might be preferable - it doesn't seem like there should be a need to be so extremely stingy with memory on modern systems.

(edit: fixed some wording, added some clarifications)

Interesting. How about instead of

buff.resize(buff.find('\0')); 
return buff; 

one uses

return std::string( buff.c_str() );

This makes another copy, but given that this is just called in an error case, the overhead is probably bearable.

In my pull request, I have done the following:

    if(buff.find('\0') != std::string::npos)
    {
        buff.resize(buff.find('\0'));
    }

This fork applied a bigger buffer of 256 as @lightvector had suggested:
JGI-Bioinformatics@3344f87