<div dir="ltr"><div>Below is a little app that illustrates the issue (Can also be found here: <a href="http://pastebin.com/k8jRN64R">http://pastebin.com/k8jRN64R</a>) 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. </div> <div><div><br></div><div>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.</div><div><br></div> <div>Any help is greatly appreciated!</div><div><br></div><div><div>//<span class="" style="white-space:pre"> </span>Boost.Crypto</div><div>#include <boost/crypto/rc4_cipher.hpp></div><div><br></div><div>//<span class="" style="white-space:pre"> </span>Boost</div> <div>#include <boost/filesystem/fstream.hpp></div><div>#include <boost/iostreams/filter/zlib.hpp></div><div>#include <boost/iostreams/copy.hpp></div><div>#include <boost/iostreams/filtering_stream.hpp></div> <div><br></div><div><br></div><div>template <typename StreamCipherT></div><div>class StreamCipherFilterBase</div><div>{</div><div>public:</div><div><span class="" style="white-space:pre"> </span>typedef char<span class="" style="white-space:pre"> </span>char_type;</div> <div><br></div><div><span class="" style="white-space:pre"> </span>StreamCipherFilterBase(const std::string& key)</div><div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>m_cipher.set_key(key.data(), static_cast<unsigned int>(key.length()));</div> <div><span class="" style="white-space:pre"> </span>}</div><div>protected:</div><div> char m_buffer[1024 * 2]; // 2k internal buffer size</div><div> StreamCipherT<span class="" style="white-space:pre"> </span>m_cipher;</div> <div>};</div><div><br></div><div>template <typename StreamCipherT></div><div>class StreamCipherEncryptFilter</div><div><span class="" style="white-space:pre"> </span>: public StreamCipherFilterBase<StreamCipherT></div> <div>{</div><div>public:</div><div><span class="" style="white-space:pre"> </span>typedef boost::iostreams::multichar_output_filter_tag<span class="" style="white-space:pre"> </span>category;</div><div><br></div><div><span class="" style="white-space:pre"> </span>StreamCipherEncryptFilter(const std::string& key)</div> <div><span class="" style="white-space:pre"> </span>: StreamCipherFilterBase<StreamCipherT>(key)</div><div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>}</div> <div><br></div><div><span class="" style="white-space:pre"> </span>template<typename Sink></div><div><span class="" style="white-space:pre"> </span>std::streamsize write(Sink& snk, const char* s, std::streamsize n)</div> <div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>std::streamsize written<span class="" style="white-space:pre"> </span>= 0;</div><div><span class="" style="white-space:pre"> </span>std::streamsize remain<span class="" style="white-space:pre"> </span>= n;</div> <div><span class="" style="white-space:pre"> </span>std::streamsize eat;</div><div><span class="" style="white-space:pre"> </span>while(remain) {</div><div><span class="" style="white-space:pre"> </span>eat = remain < sizeof(StreamCipherFilterBase<StreamCipherT>::m_buffer) ?</div> <div> remain : sizeof(StreamCipherFilterBase<StreamCipherT>::m_buffer);</div><div><span class="" style="white-space:pre"> </span>StreamCipherFilterBase<StreamCipherT>::m_cipher.encrypt(</div><div> <span class="" style="white-space:pre"> </span>s,</div><div><span class="" style="white-space:pre"> </span>StreamCipherFilterBase<StreamCipherT>::m_buffer,</div><div><span class="" style="white-space:pre"> </span>eat);</div> <div><span class="" style="white-space:pre"> </span>written += boost::iostreams::write(snk, StreamCipherFilterBase<StreamCipherT>::m_buffer, eat);</div><div><span class="" style="white-space:pre"> </span>remain -= eat;</div> <div><span class="" style="white-space:pre"> </span>s += eat;</div><div><span class="" style="white-space:pre"> </span>}</div><div><span class="" style="white-space:pre"> </span>return written;</div><div><span class="" style="white-space:pre"> </span>}</div> <div>};</div><div><br></div><div>template <typename StreamCipherT></div><div>class StreamCipherDecryptFilter</div><div><span class="" style="white-space:pre"> </span>: public StreamCipherFilterBase<StreamCipherT></div> <div>{</div><div>public:</div><div><span class="" style="white-space:pre"> </span>typedef boost::iostreams::multichar_input_filter_tag<span class="" style="white-space:pre"> </span>category;</div><div><br></div><div><span class="" style="white-space:pre"> </span>StreamCipherDecryptFilter(const std::string& key)</div> <div><span class="" style="white-space:pre"> </span>: StreamCipherFilterBase<StreamCipherT>(key)</div><div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>}</div> <div><br></div><div><span class="" style="white-space:pre"> </span>template<typename Source></div><div><span class="" style="white-space:pre"> </span>std::streamsize read(Source& src, char* s, std::streamsize n)</div> <div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>const std::streamsize read = boost::iostreams::read(src, s, n);</div><div> if(EOF == read) {</div><div> return EOF;</div><div> }</div><div><span class="" style="white-space:pre"> </span>StreamCipherFilterBase<StreamCipherT>::m_cipher.decrypt(s, s, read);</div><div><span class="" style="white-space:pre"> </span>return read;</div> <div><span class="" style="white-space:pre"> </span>}</div><div>};</div><div><br></div><div>const std::string KEY = "Kitteh";</div><div>typedef boost::crypto::rc4_cipher<span class="" style="white-space:pre"> </span>CipherT;</div> <div><br></div><div>void Encrypt(</div><div><span class="" style="white-space:pre"> </span>const std::string& in, const std::string& out)</div><div>{</div><div><span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span>error handling omitted</div> <div><span class="" style="white-space:pre"> </span>boost::filesystem::ifstream inf(in, std::ios_base::binary | std::ios_base::in);</div><div><span class="" style="white-space:pre"> </span>boost::filesystem::ofstream outf(out, std::ios_base::binary | std::ios_base::out);</div> <div><br></div><div><span class="" style="white-space:pre"> </span>StreamCipherEncryptFilter<CipherT> outCipherFilter(KEY);</div><div><span class="" style="white-space:pre"> </span>boost::iostreams::filtering_ostreambuf outs;</div> <div><span class="" style="white-space:pre"> </span>outs.push(boost::iostreams::zlib_compressor());<span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span>compress</div><div> outs.push(outCipherFilter);<span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span>then encrypt</div> <div><span class="" style="white-space:pre"> </span>outs.push(outf);<span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span>write to file</div><div><br></div><div><span class="" style="white-space:pre"> </span>boost::iostreams::copy(inf, outs);</div> <div>}</div><div><br></div><div>void Decrypt(</div><div><span class="" style="white-space:pre"> </span>const std::string& in, const std::string& out)</div><div>{</div><div><span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span>error handling omitted</div> <div><span class="" style="white-space:pre"> </span>boost::filesystem::ifstream inf(in, std::ios_base::binary | std::ios_base::in);</div><div><span class="" style="white-space:pre"> </span>boost::filesystem::ofstream outf(out, std::ios_base::binary | std::ios_base::out);</div> <div><br></div><div><span class="" style="white-space:pre"> </span>StreamCipherDecryptFilter<CipherT> inCipherFilter(KEY);</div><div><span class="" style="white-space:pre"> </span>boost::iostreams::filtering_istreambuf ins;</div> <div><span class="" style="white-space:pre"> </span>ins.push(boost::iostreams::zlib_decompressor());</div><div><span class="" style="white-space:pre"> </span>ins.push(inCipherFilter);</div><div><span class="" style="white-space:pre"> </span>ins.push(inf);</div> <div><br></div><div><span class="" style="white-space:pre"> </span>boost::iostreams::copy(ins, outf);<span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span><-- exception thrown here with some files</div> <div>}</div><div><br></div><div>int main()</div><div>{</div><div><span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span>compress+encrypt input.txt -> output.encrypt</div><div><span class="" style="white-space:pre"> </span>Encrypt("input.txt", "output.encrypt");</div> <div><br></div><div><span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span>decrypt+decompress output.encrypt -> input.read.txt</div><div><span class="" style="white-space:pre"> </span>Decrypt("output.encrypt", "input.read.txt");</div> <div>}</div></div><div><div class="gmail_extra"><br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> ------------------------------<br> <br> Message: 5<br> Date: Thu, 08 Aug 2013 17:52:50 +0100<br> From: Ken Appleby <<a href="mailto:ken.appleby@btopenworld.com">ken.appleby@btopenworld.com</a>><br> To: <a href="mailto:boost-users@lists.boost.org">boost-users@lists.boost.org</a><br> Subject: Re: [Boost-users] Iostreams with two filters throws exception<br> Message-ID: <<a href="mailto:5203CCE2.4060200@btopenworld.com">5203CCE2.4060200@btopenworld.com</a>><br> Content-Type: text/plain; charset=ISO-8859-1; format=flowed<br> <br><br> You are a lot more likely to get a response if you post a complete<br> example. Just a single file with a main() would make it a lot easier to<br> help you. You're not far from that with the code you posted.<br> <br></blockquote></div></div></div></div></div>