1

I've been using the following code successfully on Linux but it crashes at the boost::iostreams::copy() on Windows. What could be the cause?

#include <sstream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/zlib.hpp>

// https://stackoverflow.com/a/17176881/3764804
bool is_compressed(const std::string &data) {
    return data.at(0) == 0x78 && (unsigned char) data.at(1) == 0xDA;
}

std::string compress(const std::string &plain_text) {
    boost::iostreams::filtering_streambuf<boost::iostreams::output> output_stream;
    const auto compression_level = boost::iostreams::zlib::best_compression;
    output_stream.push(boost::iostreams::zlib_compressor(compression_level));
    std::stringstream string_stream;
    output_stream.push(string_stream);
    boost::iostreams::copy(boost::iostreams::basic_array_source<char>(plain_text.c_str(),
                                                                      plain_text.size()), output_stream);
    return string_stream.str();
}

std::string decompress(const std::string &cipher_text) {
    std::stringstream string_stream;
    string_stream << cipher_text;
    boost::iostreams::filtering_streambuf<boost::iostreams::input> input_stream;
    input_stream.push(boost::iostreams::zlib_decompressor());

    input_stream.push(string_stream);
    std::stringstream unpacked_text;
    boost::iostreams::copy(input_stream, unpacked_text); // <-- Crashes here on Windows
    return unpacked_text.str();
}

Exception:

Exception thrown at 0x00007FFF08A8A859 in my_project.exe: Microsoft C++ exception: boost::wrapexcept<boost::iostreams::zlib_error> at memory location 0x00000015E14FD440.
Exception thrown at 0x00007FFF08A8A859 in my_project.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.

My Boost is version 1.72.0.

I tried calling a simple compress/decompress example at the top of my main function and it worked. However, when using a bigger compressed buffer it still crashes the same way.

This answer does not apply to me since I'm writing to a std::stringstream and not an output file.

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • Not that your problem is related to an `std::fstream` that you didn't open with `std::ios::binary`. That wouldn't be a problem on Linux but it would probably be a problem on Windows. I strongly assume that zip compression/uncompression is allergic to `0xd` bytes which are removed (or inserted) here and there. (Just a stupid thought.) ;-) (I mean what if the `cipher_text` has been already corrupted before and doesn't form anymore a valid zip archive?) – Scheff's Cat Mar 29 '20 at 15:34
  • @Scheff: I updated my question. Also I don't see a `std::fstream` in my code, what are you referring to with the `std::ios::binary` mode? – BullyWiiPlaza Apr 01 '20 at 19:40
  • Just a shot into the blue.(See my last sentence/question of the above comment.) – Scheff's Cat Apr 01 '20 at 20:26
  • @Scheff: That's not the case since it decompresses the same file/buffer with the same code when running under `Linux` but not when running under `Windows`. – BullyWiiPlaza Apr 02 '20 at 07:32

1 Answers1

0

A few days later, I found that the Windows line separators 0D 0A are written into the zlib compressed file instead of just 0A on Linux. This surprisingly causes the decompression to crash. A simple fix was to replace all 0D 0A sequences with just 0A. See this question. Still, I don't know why this "hack" is necessary. Maybe there is still a more elegant way? Or maybe my solution isn't even fool proof. Feel free to post another answer.

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185