File CVE-2015-5726+CVE-2015-5727.patch of Package Botan.4627
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