
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@btopenworld.com> To: boost-users@lists.boost.org Subject: Re: [Boost-users] Iostreams with two filters throws exception Message-ID: <5203CCE2.4060200@btopenworld.com> 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.