Boost logo

Boost Users :

Subject: Re: [Boost-users] Iostreams with two filters throws exception (Ken Appleby)
From: NuSkooler (nuskooler_at_[hidden])
Date: 2013-08-08 23:46:23


Below is a little app that illustrates the issue (Can also be found here:
http://pastebin.com/k8jRN64R) I've removed most error handling/etc. for
illustration purposes. The program expects a "input.txt" to be present in
the same directory it's run from.

Note again that this works *most* of the time, but depending on the input
file, will crash. Also I forgot to mention before that I'm using Clang on
OS X 8.4 and Boost v1.53.

Any help is greatly appreciated!

// Boost.Crypto
#include <boost/crypto/rc4_cipher.hpp>

// Boost
#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filtering_stream.hpp>

template <typename StreamCipherT>
class StreamCipherFilterBase
{
public:
typedef char char_type;

StreamCipherFilterBase(const std::string& key)
{
m_cipher.set_key(key.data(), static_cast<unsigned int>(key.length()));
}
protected:
    char m_buffer[1024 * 2]; // 2k internal buffer size
    StreamCipherT m_cipher;
};

template <typename StreamCipherT>
class StreamCipherEncryptFilter
: public StreamCipherFilterBase<StreamCipherT>
{
public:
typedef boost::iostreams::multichar_output_filter_tag category;

StreamCipherEncryptFilter(const std::string& key)
: StreamCipherFilterBase<StreamCipherT>(key)
{
}

template<typename Sink>
std::streamsize write(Sink& snk, const char* s, std::streamsize n)
{
std::streamsize written = 0;
std::streamsize remain = n;
std::streamsize eat;
while(remain) {
eat = remain < sizeof(StreamCipherFilterBase<StreamCipherT>::m_buffer) ?
                remain :
sizeof(StreamCipherFilterBase<StreamCipherT>::m_buffer);
StreamCipherFilterBase<StreamCipherT>::m_cipher.encrypt(
s,
StreamCipherFilterBase<StreamCipherT>::m_buffer,
eat);
written += boost::iostreams::write(snk,
StreamCipherFilterBase<StreamCipherT>::m_buffer, eat);
remain -= eat;
s += eat;
}
return written;
}
};

template <typename StreamCipherT>
class StreamCipherDecryptFilter
: public StreamCipherFilterBase<StreamCipherT>
{
public:
typedef boost::iostreams::multichar_input_filter_tag category;

StreamCipherDecryptFilter(const std::string& key)
: StreamCipherFilterBase<StreamCipherT>(key)
{
}

template<typename Source>
std::streamsize read(Source& src, char* s, std::streamsize n)
{
const std::streamsize read = boost::iostreams::read(src, s, n);
        if(EOF == read) {
            return EOF;
        }
StreamCipherFilterBase<StreamCipherT>::m_cipher.decrypt(s, s, read);
return read;
}
};

const std::string KEY = "Kitteh";
typedef boost::crypto::rc4_cipher CipherT;

void Encrypt(
const std::string& in, const std::string& out)
{
// error handling omitted
boost::filesystem::ifstream inf(in, std::ios_base::binary |
std::ios_base::in);
boost::filesystem::ofstream outf(out, std::ios_base::binary |
std::ios_base::out);

StreamCipherEncryptFilter<CipherT> outCipherFilter(KEY);
boost::iostreams::filtering_ostreambuf outs;
outs.push(boost::iostreams::zlib_compressor()); // compress
    outs.push(outCipherFilter); // then encrypt
outs.push(outf); // write to file

boost::iostreams::copy(inf, outs);
}

void Decrypt(
const std::string& in, const std::string& out)
{
// error handling omitted
boost::filesystem::ifstream inf(in, std::ios_base::binary |
std::ios_base::in);
boost::filesystem::ofstream outf(out, std::ios_base::binary |
std::ios_base::out);

StreamCipherDecryptFilter<CipherT> inCipherFilter(KEY);
boost::iostreams::filtering_istreambuf ins;
ins.push(boost::iostreams::zlib_decompressor());
ins.push(inCipherFilter);
ins.push(inf);

boost::iostreams::copy(ins, outf); // <-- exception thrown here with some
files
}

int main()
{
// compress+encrypt input.txt -> output.encrypt
Encrypt("input.txt", "output.encrypt");

// decrypt+decompress output.encrypt -> input.read.txt
Decrypt("output.encrypt", "input.read.txt");
}

------------------------------
>
> Message: 5
> Date: Thu, 08 Aug 2013 17:52:50 +0100
> From: Ken Appleby <ken.appleby_at_[hidden]>
> To: boost-users_at_[hidden]
> Subject: Re: [Boost-users] Iostreams with two filters throws exception
> Message-ID: <5203CCE2.4060200_at_[hidden]>
> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
>
>
> You are a lot more likely to get a response if you post a complete
> example. Just a single file with a main() would make it a lot easier to
> help you. You're not far from that with the code you posted.
>
>



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net