Opened 12 years ago

Closed 11 years ago

#5494 closed Bugs (wontfix)

lexical_cast<unsigned int>("-1") fails to throw

Reported by: Rupert Kittinger-Sereinig <rks@…> Owned by: Antony Polukhin
Milestone: Boost 1.47.0 Component: lexical_cast
Version: Boost 1.45.0 Severity: Problem
Keywords: lexical_cast Cc:

Description

The following fails to throw: std::cout << boost::lexical_cast<unsigned int>(std::string("-1"))

<< std::endl;

output: 4294967295

which looks a lot like static_cast<unsigned int>(-1)

boost version: 1.45 compiler: g++ (Debian 4.4.5-8) 4.4.5

For my project, this is a serious problem since lexical_cast is used for input validation

Change History (4)

comment:1 by Antony Polukhin, 11 years ago

Owner: changed from nasonov to Antony Polukhin
Status: newassigned

comment:2 by Antony Polukhin, 11 years ago

boost::lexical_cast has the behavior of stringstream, which uses num_get functions of std::locale to convert numbers. If we look at the [22.2.2.1.2] of Programming languages — C++ ( or at [22.2.2.1.2] Working Draft, Standard for Programming Language C++) we`ll see, that num_get uses the rules of scanf for conversions. And in the C99 standard for %u the input value minus sign is optional, so if a negative number is read, no errors will arise and the result will be the two's complement.
I recommend you to use some wrappers, around lexical_cast, like:

#include <boost/lexical_cast.hpp>
#include <boost/type_traits/is_unsigned.hpp>

template <bool is_unsigned>
struct unsigned_checker
{
    template<typename String_type>
    static inline void do_check(const String_type & str) { }
};

template <>
struct unsigned_checker<true>
{
    template<typename String_type>
    static inline void do_check(const String_type & str)
    {
        if( str[0] == '-' ) boost::throw_exception( boost::bad_lexical_cast() );
    }
};

template<typename Target, typename Source>
inline Target forced_lexical_cast(const Source &arg)
{
    unsigned_checker< boost::is_unsigned<Target>::value >::do_check(arg);
    return boost::lexical_cast<Target>( arg );
}


Thank you for that bug report! I`ll add your question to the FAQ section of lexical_cast documentation.

comment:3 by Rupert Kittinger-Sereinig <rks@…>, 11 years ago

thanks for the explanation, I already implemented a similar workaround.

You might als add to the FAQ that this may not be very portable.

e.g. with g++-4.3.2, the behaviour was different.

comment:4 by Antony Polukhin, 11 years ago

Milestone: To Be DeterminedBoost 1.47.0
Resolution: wontfix
Status: assignedclosed
Note: See TracTickets for help on using tickets.