[serialization] Treatment of corrupt archives - assert vs. exception throw
Hi folks,
I'm dealing with binary archives which may have been corrupted enroute to
my code. My naive expectation was that the serialization library should
throw an exception when it encounters something in the input stream it
doesn't understand (in which case my code can react gracefully). But, I've
found that:
1. There exist cases where serialization will just assert and bring down
the process
2. The documentation suggests that an exception should be thrown, but I
didn't find any strong statement of this, so I am not sure whether it is a
contract of the library.
My first and most pressing question is: is it a guarantee of the library
that invalid input should result in an exception and not an assert? If
this is not so, I think it should be documented much more clearly.
If it is so, then this message is a bug report. There's an assert in
archive/basic_binary_iprimitive.hpp:98 that can be triggered if the bytes
in the archive which represent a bool actually contain a value other than 0
or 1. One can trigger this in a test case like so (on x86_64 Linux, at
least):
==========
#include
Speaking from memory, I often use BOTH assert and exception. Sometimes something looks like a program error which should never happen so I use an assert. But should this occur during release mode, it should throw an exception. So what happens when you build in release mode? Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/serialization-Treatment-of-corrupt-archiv... Sent from the Boost - Users mailing list archive at Nabble.com.
Hi Robert, Thanks for your reply!
Speaking from memory, I often use BOTH assert and exception. Sometimes something looks like a program error which should never happen so I use an assert. But should this occur during release mode, it should throw an exception.
In this case, the code looks like: // trap usage of invalid uninitialized boolean void load(bool & t){ load_binary(& t, sizeof(t)); int i = t; BOOST_ASSERT(0 == i || 1 == i); (void)i; // warning suppression for release builds. } (see: serialization/archive/basic_binary_iprimitive.hpp) so if I strip out asserts, nothing happens, and the process just blunders on without reporting any problems. As far as I can see, this assert is not checking for a program error - it's looking to catch an invalid value in the input stream. I'd also argue that adding a 'throw' after the 'assert' is not the right approach to take. For instance, I may want to test that my code will correctly reject invalid inputs. If the assert is present in debug but not release modes, the behavior will be different in the two cases. And if the assert is in code not my own, I have no reason to expect such a change. IMO asserts should be reserved for situations which can occur only in cases of programmer error, and should in theory not be triggerable by any external input. So as I see it, this assert should simply be replaced by a throw. Do you agree? -Gabe
On Wed, Nov 12, 2014 at 2:09 PM, Robert Ramey
Speaking from memory, I often use BOTH assert and exception. Sometimes something looks like a program error which should never happen so I use an assert. But should this occur during release mode, it should throw an exception.
Asserts should be used to report logic errors. In this case the error is triggered by incorrect format of the data file -- which is not a logic error, so the correct behavior is to throw and to not assert. -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
participants (3)
-
Emil Dotchevski
-
Gabriel Redner
-
Robert Ramey