commit 7c907db91bfc048b498c23baa2ec83d329947581
Author: Jack Lloyd <lloyd@randombit.net>
Date:   Mon Aug 3 00:28:56 2015 -0400

    Fix two crashes in BER decoding found with afl

diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp
index c38b93dc3..478ebae86 100644
--- a/src/asn1/ber_dec.cpp
+++ b/src/asn1/ber_dec.cpp
@@ -205,7 +205,10 @@ BER_Object BER_Decoder::get_next_object()
    if(next.type_tag == NO_OBJECT)
       return next;
 
-   size_t length = decode_length(source);
+   const size_t length = decode_length(source);
+   if(!source->check_available(length))
+      throw BER_Decoding_Error("Value truncated");
+
    next.value.resize(length);
    if(source->read(&next.value[0], length) != length)
       throw BER_Decoding_Error("Value truncated");
@@ -457,6 +460,8 @@ BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer,
       buffer = obj.value;
    else
       {
+      if(obj.value.empty())
+         throw BER_Decoding_Error("Invalid BIT STRING");
       if(obj.value[0] >= 8)
          throw BER_Decoding_Error("Bad number of unused bits in BIT STRING");
 
diff --git a/src/entropy/unix_procs/unix_cmd.cpp b/src/entropy/unix_procs/unix_cmd.cpp
index 930444075..c72f9c00e 100644
--- a/src/entropy/unix_procs/unix_cmd.cpp
+++ b/src/entropy/unix_procs/unix_cmd.cpp
@@ -99,6 +99,11 @@ size_t DataSource_Command::peek(byte[], size_t, size_t) const
    throw Stream_IO_Error("Cannot peek/seek on a command pipe");
    }
 
+bool DataSource_Command::check_available(size_t)
+   {
+   throw Stream_IO_Error("Cannot check available bytes on a pipe");
+   }
+
 /**
 * Check if we reached EOF
 */
diff --git a/src/entropy/unix_procs/unix_cmd.h b/src/entropy/unix_procs/unix_cmd.h
index 5185c1c8f..bdbcec3cc 100644
--- a/src/entropy/unix_procs/unix_cmd.h
+++ b/src/entropy/unix_procs/unix_cmd.h
@@ -51,6 +51,7 @@ class DataSource_Command : public DataSource
    public:
       size_t read(byte[], size_t);
       size_t peek(byte[], size_t, size_t) const;
+      bool check_available(size_t n);
       bool end_of_data() const;
       std::string id() const;
 
diff --git a/src/filters/codec_filt/b64_filt.cpp b/src/filters/codec_filt/b64_filt.cpp
index 9341571d4..34d00fdf5 100644
--- a/src/filters/codec_filt/b64_filt.cpp
+++ b/src/filters/codec_filt/b64_filt.cpp
@@ -126,6 +126,11 @@ void Base64_Decoder::write(const byte input[], size_t length)
    while(length)
       {
       size_t to_copy = std::min<size_t>(length, in.size() - position);
+      if(to_copy == 0)
+         {
+         in.resize(in.size()*2);
+         out.resize(out.size()*2);
+         }
       copy_mem(&in[position], input, to_copy);
       position += to_copy;
 
diff --git a/src/filters/data_src.cpp b/src/filters/data_src.cpp
index da67baa98..b69601336 100644
--- a/src/filters/data_src.cpp
+++ b/src/filters/data_src.cpp
@@ -101,6 +101,11 @@ DataSource_Memory::DataSource_Memory(const std::string& in) :
    offset = 0;
    }
 
+bool DataSource_Memory::check_available(size_t n)
+   {
+   return (n <= (source.size() - offset));
+   }
+
 /*
 * Read from a stream
 */
@@ -115,6 +120,15 @@ size_t DataSource_Stream::read(byte out[], size_t length)
    return got;
    }
 
+bool DataSource_Stream::check_available(size_t n)
+   {
+   const std::streampos orig_pos = source.tellg();
+   source.seekg(0, std::ios::end);
+   const size_t avail = source.tellg() - orig_pos;
+   source.seekg(orig_pos);
+   return (avail >= n);
+   }
+
 /*
 * Peek into a stream
 */
diff --git a/src/filters/data_src.h b/src/filters/data_src.h
index a274de8e2..36d705760 100644
--- a/src/filters/data_src.h
+++ b/src/filters/data_src.h
@@ -56,6 +56,8 @@ class BOTAN_DLL DataSource
       */
       virtual std::string id() const { return ""; }
 
+      virtual bool check_available(size_t n) = 0;
+
       /**
       * Read one byte.
       * @param out the byte to read to
@@ -94,6 +96,7 @@ class BOTAN_DLL DataSource_Memory : public DataSource
    public:
       size_t read(byte[], size_t);
       size_t peek(byte[], size_t, size_t) const;
+      bool check_available(size_t n);
       bool end_of_data() const;
 
       /**
@@ -127,6 +130,7 @@ class BOTAN_DLL DataSource_Stream : public DataSource
    public:
       size_t read(byte[], size_t);
       size_t peek(byte[], size_t, size_t) const;
+      bool check_available(size_t n);
       bool end_of_data() const;
       std::string id() const;
 
diff --git a/src/filters/pipe.h b/src/filters/pipe.h
index e5cb5f445..3d9ffab9c 100644
--- a/src/filters/pipe.h
+++ b/src/filters/pipe.h
@@ -200,6 +200,9 @@ class BOTAN_DLL Pipe : public DataSource
       size_t peek(byte& output, size_t offset,
                   message_id msg = DEFAULT_MESSAGE) const;
 
+      bool check_available(size_t n);
+      bool check_available_msg(size_t n, message_id msg);
+
       /**
       * @return currently set default message
       */
diff --git a/src/filters/pipe_rw.cpp b/src/filters/pipe_rw.cpp
index 90af9ed34..145a7e32a 100644
--- a/src/filters/pipe_rw.cpp
+++ b/src/filters/pipe_rw.cpp
@@ -140,6 +140,16 @@ size_t Pipe::remaining(message_id msg) const
    return outputs->remaining(get_message_no("remaining", msg));
    }
 
+bool Pipe::check_available(size_t n)
+   {
+   return (n <= remaining(DEFAULT_MESSAGE));
+   }
+
+bool Pipe::check_available_msg(size_t n, message_id msg)
+   {
+   return (n <= remaining(msg));
+   }
+
 /*
 * Peek at some data in the pipe
 */
diff --git a/src/filters/secqueue.h b/src/filters/secqueue.h
index 632ae857d..15f336e6f 100644
--- a/src/filters/secqueue.h
+++ b/src/filters/secqueue.h
@@ -35,6 +35,8 @@ class BOTAN_DLL SecureQueue : public Fanout_Filter, public DataSource
 
       bool attachable() { return false; }
 
+      bool check_available(size_t n) { return n <= size(); }
+
       /**
       * SecureQueue assignment
       * @param other the queue to copy
