From: JINMEI Tatuya Date: Wed, 6 Mar 2013 07:28:15 +0000 (-0800) Subject: [2764] unified exception messages for the two incomplete-input cases. X-Git-Tag: bind10-1.1.0beta1-release~65^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dd41cb13ce276c055af55e486404773dfbf31154;p=thirdparty%2Fkea.git [2764] unified exception messages for the two incomplete-input cases. adjusted one unit test case based on the message change. --- diff --git a/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py b/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py index 808f28a174..8c1639cc02 100644 --- a/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py +++ b/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py @@ -86,7 +86,7 @@ class TSigKeysTest(unittest.TestCase): self.assertEqual("TSIG: Invalid TSIG key string: invalid.key", tsig_keys.check({'keys': ['invalid.key']})) self.assertEqual( - "TSIG: Unexpected end of input in BASE decoder", + "TSIG: Incomplete input for base64: 123", tsig_keys.check({'keys': ['invalid.key:123']})) def test_bad_format(self): diff --git a/src/lib/util/encode/base_n.cc b/src/lib/util/encode/base_n.cc index acf3d3e4a5..f37ebfc3e6 100644 --- a/src/lib/util/encode/base_n.cc +++ b/src/lib/util/encode/base_n.cc @@ -12,17 +12,6 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. -#include -#include -#include -#include -#include - -#include -#include -#include -#include - #include #include #include @@ -32,6 +21,18 @@ #include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + using namespace std; using namespace boost::archive::iterators; @@ -143,6 +144,11 @@ private: bool in_pad_; }; +// An internally caught exception to unify a few possible cases of the same +// error. +class IncompleteBaseInput : public std::exception { +}; + // DecodeNormalizer is an input iterator intended to be used as a filter // between the encoded baseX stream and binary_from_baseXX. // A DecodeNormalizer object is configured with three string iterators @@ -164,16 +170,20 @@ public: DecodeNormalizer(const char base_zero_code, const string::const_iterator& base, const string::const_iterator& base_beginpad, - const string::const_iterator& base_end) : + const string::const_iterator& base_end, + size_t* char_count) : base_zero_code_(base_zero_code), base_(base), base_beginpad_(base_beginpad), base_end_(base_end), - in_pad_(false) + in_pad_(false), char_count_(char_count) { // Skip beginning spaces, if any. We need do it here because // otherwise the first call to operator*() would be confused. skipSpaces(); } DecodeNormalizer& operator++() { + if (base_ < base_end_) { + ++*char_count_; + } ++base_; skipSpaces(); if (base_ == base_beginpad_) { @@ -196,12 +206,18 @@ public: } const char& operator*() const { if (base_ == base_end_) { - // binary_from_baseX calls this operator when it needs more bits + // binary_from_baseX can call this operator when it needs more bits // even if the internal iterator (base_) has reached its end // (if that happens it means the input is an incomplete baseX // string and should be rejected). So this is the only point // we can catch and reject this type of invalid input. - isc_throw(BadValue, "Unexpected end of input in BASE decoder"); + // + // More recent versions of Boost fixed the behavior and the + // out-of-range call to this operator doesn't happen. It's good, + // but in that case we need to catch incomplete baseX input in + // a different way. It's done via char_count_ and after the + // completion of decoding. + throw IncompleteBaseInput(); // throw this now and convert it } if (*base_ == BASE_PADDING_CHAR) { // Padding can only happen at the end of the input string. We can @@ -220,12 +236,16 @@ public: bool operator==(const DecodeNormalizer& other) const { return (base_ == other.base_); } + bool allDecoded() const { return (base_ == base_end_); } private: const char base_zero_code_; string::const_iterator base_; const string::const_iterator base_beginpad_; const string::const_iterator base_end_; bool in_pad_; + // Store number of non-space decoded characters (incl. pad) here. Define + // it as a pointer so we can carry it over to any copied objects. + size_t* char_count_; }; // BitsPerChunk: number of bits to be converted using the baseN mapping table. @@ -347,10 +367,24 @@ BaseNTransformer::decode( const size_t padbytes = padbits / 8; try { + size_t char_count = 0; result.assign(Decoder(DecodeNormalizer(BaseZeroCode, input.begin(), - srit.base(), input.end())), + srit.base(), input.end(), + &char_count)), Decoder(DecodeNormalizer(BaseZeroCode, input.end(), - input.end(), input.end()))); + input.end(), input.end(), + NULL))); + + // Number of bits of the conversion result including padding must be + // a multiple of 8; otherwise the decoder reaches the end of input + // with some incomplete bits of data, which is invalid. + if (((char_count * BitsPerChunk) & 7) != 0) { + throw IncompleteBaseInput(); // catch this immediately below + } + } catch (const IncompleteBaseInput&) { + // we unify error handling for incomplete input here. + isc_throw(BadValue, "Incomplete input for " << algorithm + << ": " << input); } catch (const dataflow_exception& ex) { // convert any boost exceptions into our local one. isc_throw(BadValue, ex.what());