diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/asn1/ber_dec.cpp | 27 | ||||
-rw-r--r-- | src/tests/test_asn1.cpp | 67 |
2 files changed, 83 insertions, 11 deletions
diff --git a/src/lib/asn1/ber_dec.cpp b/src/lib/asn1/ber_dec.cpp index 7b2147600..bf728a8e8 100644 --- a/src/lib/asn1/ber_dec.cpp +++ b/src/lib/asn1/ber_dec.cpp @@ -218,20 +218,25 @@ BER_Object BER_Decoder::get_next_object() return next; } - decode_tag(m_source, next.type_tag, next.class_tag); - if(next.type_tag == NO_OBJECT) - return next; + for(;;) + { + decode_tag(m_source, next.type_tag, next.class_tag); + if(next.type_tag == NO_OBJECT) + return next; - const size_t length = decode_length(m_source); - if(!m_source->check_available(length)) - throw BER_Decoding_Error("Value truncated"); + const size_t length = decode_length(m_source); + if(!m_source->check_available(length)) + throw BER_Decoding_Error("Value truncated"); - next.value.resize(length); - if(m_source->read(next.value.data(), length) != length) - throw BER_Decoding_Error("Value truncated"); + next.value.resize(length); + if(m_source->read(next.value.data(), length) != length) + throw BER_Decoding_Error("Value truncated"); - if(next.type_tag == EOC && next.class_tag == UNIVERSAL) - return get_next_object(); + if(next.type_tag == EOC && next.class_tag == UNIVERSAL) + continue; + else + break; + } return next; } diff --git a/src/tests/test_asn1.cpp b/src/tests/test_asn1.cpp new file mode 100644 index 000000000..3427d391d --- /dev/null +++ b/src/tests/test_asn1.cpp @@ -0,0 +1,67 @@ +/* +* (C) 2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "tests.h" + +#if defined(BOTAN_HAS_ASN1) + #include <botan/der_enc.h> + #include <botan/ber_dec.h> +#endif + +namespace Botan_Tests { + +#if defined(BOTAN_HAS_ASN1) + +namespace { + +Test::Result test_ber_stack_recursion() + { + Test::Result result("BER stack recursion"); + + // OSS-Fuzz #813 GitHub #989 + + try + { + const std::vector<uint8_t> in(10000000, 0); + Botan::DataSource_Memory input(in.data(), in.size()); + Botan::BER_Decoder dec(input); + + while(dec.more_items()) + { + Botan::BER_Object obj; + dec.get_next(obj); + } + } + catch(Botan::Decoding_Error&) + { + } + + result.test_success("No crash"); + + return result; + } + +} + +class ASN1_Tests : public Test + { + public: + std::vector<Test::Result> run() override + { + std::vector<Test::Result> results; + + results.push_back(test_ber_stack_recursion()); + + return results; + } + }; + +BOTAN_REGISTER_TEST("asn1", ASN1_Tests); + +#endif + +} + |