Boost logo

Boost :

From: Caleb Epstein (caleb.epstein_at_[hidden])
Date: 2005-11-30 12:45:34


On 11/28/05, Mick Hollins <mick_at_[hidden]> wrote:
>
> The following code causes a runtime assertion in VC 8.0:
>
> std::string l_param;
> std::string l_str = (boost::format("here is an empty string: %1%") %
> l_param).str();
>
> It passes an empty string argument to boost::format.
> The assert is inside the implementation of basic_string::append()
> and boils down to the fact that the implementation of boost::format ends
> up calling
> basic_string::append(const char *, size_type) with a null pointer, which
> causes
> basic_string::append to assert.

This assertion seems to only happen with /MDd (e.g. debug runtime), but I'd
say it qualifies as a bug in Boost.Format.

Here's the stack trace:

     msvcp80d.dll!std::_Debug_message(const wchar_t * message=0x105157a0,
const wchar_t * file=0x10514a0c, unsigned int line=2023) Line 23 C++
     msvcp80d.dll!std::_Debug_pointer<char>(const char * _First=0x00000000,
const wchar_t * _File=0x10514a0c, unsigned int _Line=2023) Line 1334 + 0x12
bytes C++
     msvcp80d.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char>
>::_Inside(const char * _Ptr=0x00000000) Line 2023 + 0x13 bytes C++
     msvcp80d.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char>
>::append(const char * _Ptr=0x00000000, unsigned int _Count=0) Line 942 +
0xc bytes C++
> format.exe!boost::io::detail::mk_str<char,std::char_traits<char>,std::allocator<char>
>(std::basic_string<char,std::char_traits<char>,std::allocator<char> > &
res="", const char * beg=0x00000000, unsigned int size=0, int w=0, const
char fill_char=' ', int f=513, const char prefix_space=0, bool
center=false) Line 50 C++
     format.exe!boost::io::detail::put<char,std::char_traits<char>,std::allocator<char>,std::basic_string<char,std::char_traits<char>,std::allocator<char>
> const &>(const
std::basic_string<char,std::char_traits<char>,std::allocator<char> > & x="",
const
boost::io::detail::format_item<char,std::char_traits<char>,std::allocator<char>
> & specs={...},
std::basic_string<char,std::char_traits<char>,std::allocator<char> > &
res="",
boost::io::basic_altstringbuf<char,std::char_traits<char>,std::allocator<char>
> & buf={...}, std::locale * loc_p=0x00000000) Line 161 + 0x3b bytes C++
     format.exe!boost::io::detail::distribute<char,std::char_traits<char>,std::allocator<char>,std::basic_string<char,std::char_traits<char>,std::allocator<char>
> const
&>(boost::basic_format<char,std::char_traits<char>,std::allocator<char> > &
self={...}, const
std::basic_string<char,std::char_traits<char>,std::allocator<char> > &
x="") Line 242 + 0x3f bytes C++
     format.exe!boost::io::detail::feed<char,std::char_traits<char>,std::allocator<char>,std::basic_string<char,std::char_traits<char>,std::allocator<char>
> const
&>(boost::basic_format<char,std::char_traits<char>,std::allocator<char> > &
self={...}, const
std::basic_string<char,std::char_traits<char>,std::allocator<char> > &
x="") Line 251 + 0xd bytes C++
     format.exe!boost::basic_format<char,std::char_traits<char>,std::allocator<char>
>::operator%<std::basic_string<char,std::char_traits<char>,std::allocator<char>
> >(const std::basic_string<char,std::char_traits<char>,std::allocator<char>
> & x="") Line 64 + 0xd bytes C++
     format.exe!main() Line 13 + 0x35 bytes C++
     format.exe!__tmainCRTStartup() Line 586 + 0x19 bytes C
     format.exe!mainCRTStartup() Line 403 C
     KERNEL32.DLL!ProcessIdToSessionId() + 0x17d bytes
     [Frames below may be incorrect and/or missing, no symbols loaded for
KERNEL32.DLL]

And here's the offending code from boost::io::detail::mk_str
(feed_args.hpp):

        typedef typename std::basic_string<Ch,Tr,Alloc>::size_type
size_type;
        res.resize(0);
        if(w<=0 || static_cast<size_type>(w) <=size) {
            // no need to pad.
            res.reserve(size + !!prefix_space);
            if(prefix_space)
              res.append(1, prefix_space);
=> res.append(beg, size);
        }

I think the simple and obvious fix is to just check for size != 0 before
calling res.append, but I'm not familiar with this code.

--
Caleb Epstein
caleb dot epstein at gmail dot com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk