Modify

Ticket #5494 (closed Bugs: wontfix)

Opened 3 years ago

Last modified 3 years ago

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

Reported by: Rupert Kittinger-Sereinig <rks@…> Owned by: apolukhin
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

Attachments

Change History

comment:1 Changed 3 years ago by apolukhin

  • Owner changed from nasonov to apolukhin
  • Status changed from new to assigned

comment:2 Changed 3 years ago by apolukhin

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 Changed 3 years ago by Rupert Kittinger-Sereinig <rks@…>

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 Changed 3 years ago by apolukhin

  • Status changed from assigned to closed
  • Resolution set to wontfix
  • Milestone changed from To Be Determined to Boost 1.47.0
View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.