|
Boost : |
From: Reece Dunn (msclrhd_at_[hidden])
Date: 2004-05-06 07:41:10
John Nagle wrote:
>Reece Dunn wrote:
>>There is currently a static-sized array in the Boost library that allows
>>you to operate on arrays of fixed size. I was wondering if something
>>similar exists for strings, in particular, providing buffer-overflow safe
>>string operations.
>>
>>I have an nstring< std::size_t n > string class that provides size-safe
>>copying and comparison, allowing for you to do things like:
>
> That's an excellent direction in which to be moving.
>
> How far can we go in replacing unsafe C strings? With
>the endless reports of buffer overflow exploits, anything
>that can be done in that direction would help.
This was the motivation for designing the class: to allow safe string
operations with a clean, easy-to-use interface. I have attached the source
below. Note that this is still a work-in-progress and as such is not yet
complete.
> I'd suggest a class with the following properties:
>
> Fixed-allocated strings, with length information.
> No calls to "new".
Typical usage would be something like:
boost::char_string< 15 > str;
str.copy( "Hello World!" );
NOTE: there is not yet an operator=.
The formatterex class is to support sprintf-like operations and can be used
like this:
error_message( boost::formatterex< 1024 >( "[%s]: %s", severity, msg ));
> Supports most of the operations allowed for STL strings.
Good idea - this will help shifting between both classes.
> Also supports the "classic" C string operations, like
> "sprintf", "strlen", etc., using the classic C syntax for them.
Also a good idea. But where should these reside? In the global namespace,
std namespace or boost namespace?
> Implicit conversion to "const char*", but not "char *", for
> compatibility with existing library calls.
Done.
> Fully protected against overflow.
I hope that this is the case, although if any bugs are spotted, I'd
appreciate feedback so I can fix them. Note that the const char ( & )[ m ]
versions are to support string literals.
> It might also be worthwhile to provide "sprintf", "strlen", etc.
>for STL strings.
This is where things get tricky. Where do we place these overloads? Like
with the others (char_string) there is the question of how to be compatible
with the existing std+global namespace versions. Note that this is
complicated by the fact that the functions exist in the global namespace and
are using-imported into the std namespace in (all?) existing
implementations.
I would suggest having something like a boost::string namespace, where these
overloads (plus wchar_t overloads) of strlen, etc are placed. It may be that
the implementations need to be placed directly in the global namespace, but
I don't know what impact that would have.
> The basic idea is that this should be retrofittable to old code
>without major efforts. Ideally, you go through the code with
>a program, replacing "char foo[nnn]" with "char_array<nnn> foo",
>and "char *" with "char_array&", and it mostly works. Everything
>that doesn't work gets a compile-time error. You fix all the compile
>time errors, and your program is overflow-proof, at least in
>this area.
On my to-do list for this class is to add wchar_t support and support for a
traits class (char_traits?) as well as completing the implementation. Let me
know what you thing.
Regards,
Reece
=====
// (C) Copyright 2003-2004: Reece H. Dunn
#ifndef BOOST_CHAR_STRING_HPP
#define BOOST_CHAR_STRING_HPP
# include <cstring>
namespace boost
{
template< std::size_t n >
class char_string
{
private:
char str[ n ];
public: // access
inline operator const char *() const
{
return( str );
}
public:
inline const char * c_str() const
{
return( str );
}
inline std::size_t size() const
{
return( n );
}
public: // copy
inline void copy( const char * s,
std::size_t l )
{
::strncpy( str, s, ( l > n ) ? n : l );
}
inline void copy( const char * s )
{
copy( s, ::strlen( s ));
}
inline void copy( const char_string< n
> & s )
{
::strncpy( str, s, n );
}
template< std::size_t m >
inline void copy( const char( & s )[ m
] )
{
copy( s, m );
}
public: // comparison
inline int comp( const char * s,
std::size_t l ) const
{
return( ::strncmp( str, s, ( l > n ) ? n : l ));
}
inline int comp( const char * s )
const
{
return( comp( s, ::strlen( s )));
}
inline int comp( const char_string< n
> & s ) const
{
return( ::strncmp( str, s, n ));
}
template< std::size_t m >
inline int comp( const char( & s )[ m
] ) const
{
return( comp( s, m ));
}
public:
inline char_string()
{
str[ 0 ] = '\0';
}
};
template< std::size_t n >
bool operator==( const char_string< n > & a, const char_string< n > &
b )
{
return( a.comp( b ) == 0 );
}
template< std::size_t n, std::size_t m >
bool operator==( const char_string< n > & a, const char( & b )[ m ] )
{
return( a.comp( b ) == 0 );
}
template< std::size_t n, std::size_t m >
bool operator==( const char( & b )[ m ], const char_string< n > & a )
{
return( a.comp( b ) == 0 );
}
// formatter -- sprintf-like operations
template< std::size_t n >
class formatterex: public char_string< n >
{
public:
inline const char * operator()( const char * fs ... ) throw()
{
va_list args;
va_start( args, fs );
_vsnprintf( *this, n, fs, args );
va_end( args );
return( *this );
}
public:
inline formatterex( const char * fs ... ) throw()
{
va_list args;
va_start( args, fs );
_vsnprintf( *this, n, fs, args );
va_end( args );
}
inline formatterex() throw()
{
}
};
typedef formatterex< 512 >
formatter;
}
#endif
_________________________________________________________________
Express yourself with cool emoticons - download MSN Messenger today!
http://www.msn.co.uk/messenger
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk