On 11/28/05, Mick Hollins <mick@hollins.id.au> 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