|
Boost : |
From: Alexander Nasonov (alnsn_at_[hidden])
Date: 2006-09-12 07:51:57
Robert Kawulak <kawulak <at> student.agh.edu.pl> writes:
> You're right that the checks are not needed everywhere, but think of
> places where a programmer *thought* they were not needed but in fact
> they were - this is not so uncommon bug, and I treat this class as a
> method to avoid such bugs.
Now think of a programmer who believes that they code is safe because
it throws on overflow but the code isn't safe because it contains subtle
bugs that appear only after the exception is thrown (e. g. broken
invariants).
What do you prefer to look for in a code, for missing checks or for
invariants?
> OTOH you seem to have a different goal - to
> provide checks only when a programmer needs them. Maybe the best
> solution, as Philippe Vaucher pointed out, is to have both interfaces
> - one explicit (free functions), and the second - implicit (a wrapper
> class, which would make use of the former).
I'm all for two libraries.
> > - Throwing an exception from a place where it's not expected
> > often breaks invariants (in C++, broken invariants are often
> > subtle and dangerous)
>
> Not less than UB, which would probably happen in most situations where
> the exception would be thrown. I think exception is way better than UB
... if not swallowed by try/catch and silently ignored.
> > popular classes in a hope that it would magically work when I
> > resolve hundreds of compiler erros
>
> Oh, I think you exaggerate a bit
No, I was in similar situations several times.
> I don't see why genericity would make security to be sacrified...
It's much harder to check generic code.
> What I was thinking of was making the functions statically polymorphic,
> and this would make them even more secure. This is because the user
> doesn't have to care for the operands' type (which means less errors
> when he makes a mistake as to what the type is). So, instead of
>
> int addsi(int lhs, int rhs);
> unsigned int addui(unsigned int lhs, unsigned int rhs);
>
> there could be
>
> signed int add( signed int, signed int);
> unsigned int add(unsigned int, unsigned int);
enum { e1 = 1U + UINT_MAX / 2U, /* not shown on purpose */ };
long i = add(e1, LONG_MAX / 2L);
Try to audit this "simple" code (hints: integral promotion,
usual arithmetic conversion, bit representation ).
> This way we have the same functionality the set of C-style functions
> have, plus:
> - there are no unintended implicit argument conversions when the user
> makes error and uses a wrong function for a wrong type,
> - if the type of the argument changes, there's no need to manually
> change all the calls (which would be another error-prone activity),
> - the functions can be used in generic code.
> Is there really a reason why this approach is less secure than yours?
See code snipset above.
-- Alexander Nasonov
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk