Page 1 of 1

GZIP decompression always ends up with Exception

Posted: Sat Sep 17, 2011 8:49 am
by soMan
Hi all! I need to decompress gzip traffic from the internet link, but always get an exception (SIGSEGV error).

Code

Code: Select all

wxString SomeFunc()
{
	wxHTTP *con = new wxHTTP();
	con->SetHeader("User-Agent", "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.9.168 Version/11.51");
	con->SetHeader("Host", "some url");
	con->SetHeader("Accept", "text/html");
	con->SetHeader("Accept-Language", "ru-RU,ru;q=0.9,en;q=0.8");
	con->SetHeader("Accept-Encoding", "gzip, deflate");
    con->SetHeader("Connection", "Keep-Alive");
	wxZlibInputStream inStream(con->GetInputStream("/"), wxZLIB_GZIP);
	wxTextInputStream txtStream(inStream);
	wxString resp = txtStream.ReadWord();
	
	wxDELETE(con);
	return resp;
}
After I get a response, exception's appearing at OnSysRead method as you can see in screenshot below:
Image
OnSysRead function:

Code: Select all

size_t wxZlibInputStream::OnSysRead(void *buffer, size_t size)
{
  wxASSERT_MSG(m_inflate && m_z_buffer, wxT("Inflate stream not open"));

  if (!m_inflate || !m_z_buffer)
    m_lasterror = wxSTREAM_READ_ERROR;
  if (!IsOk() || !size)
    return 0;

  int err = Z_OK;
  m_inflate->next_out = (unsigned char *)buffer;
  m_inflate->avail_out = size;

  while (err == Z_OK && m_inflate->avail_out > 0) {
    if (m_inflate->avail_in == 0 && m_parent_i_stream->IsOk()) {
      m_parent_i_stream->Read(m_z_buffer, m_z_size);
      m_inflate->next_in = m_z_buffer;
      m_inflate->avail_in = m_parent_i_stream->LastRead();
    }
    err = inflate(m_inflate, Z_SYNC_FLUSH);
  }

  switch (err) {
    case Z_OK:
        break;

    case Z_STREAM_END:
      if (m_inflate->avail_out) {
        // Unread any data taken from past the end of the deflate stream, so that
        // any additional data can be read from the underlying stream (the crc
        // in a gzip for example)
        if (m_inflate->avail_in) {
          m_parent_i_stream->Reset();
          m_parent_i_stream->Ungetch(m_inflate->next_in, m_inflate->avail_in);
          m_inflate->avail_in = 0;
        }
        m_lasterror = wxSTREAM_EOF;
      }
      break;

    case Z_BUF_ERROR:
      // Indicates that zlib was expecting more data, but the parent stream
      // has none. Other than Eof the error will have been already reported
      // by the parent strean,
      m_lasterror = wxSTREAM_READ_ERROR;
      if (m_parent_i_stream->Eof())
      {
          wxLogError(_("Can't read inflate stream: unexpected EOF in underlying stream."));
      }
      break;

    default:
      wxString msg(m_inflate->msg, *wxConvCurrent);
      if (!msg)
        msg = wxString::Format(_("zlib error %d"), err);
      wxLogError(_("Can't read from inflate stream: %s"), msg.c_str());
      m_lasterror = wxSTREAM_READ_ERROR;
  }

  size -= m_inflate->avail_out;
  m_pos += size;
  return size;
}
wxWidgets ver 2.9.2
Unicode Support yes
OS Windows 7 Pro SP1 32 bit
IDE CodeLite 3.0.0.5041
_UNICODE Preprocessor symbol specified

Re: GZIP decompression always ends up with Exception

Posted: Sat Sep 17, 2011 10:44 am
by doublemax
At which line exactly does it crash?
Which pointer is wrong at that location?
Did you check that con->GetInputStream() actually returns a valid stream?

Re: GZIP decompression always ends up with Exception

Posted: Sat Sep 17, 2011 11:32 am
by soMan
con->GetInputStream returns a valid stream. I found it out from the sniffer. About line can say that if I'm putting the breakpoint at the first line of func

Code: Select all

wxHTTP *con = new wxHTTP();
debugger adds an extra breakpoint with "exception throw" description which signals about app crash. You can see it on a screenshot below: Image.
Also I can add that this wxHTTP-using function is in seperate dll project. So this function I'm testing on a console application which uses this dll.

Code: Select all

#include "App.h"

bool DllClass::OnInit()
{
	Client client;
	wxPuts(client.SomeFunc());
	return true;
}
Variable states at the specified "exception throw" added breakpoint: Image

Re: GZIP decompression always ends up with Exception

Posted: Sat Sep 17, 2011 4:40 pm
by doublemax
The actual wxHTTP::Connect() call is missing.

Code: Select all

[...]
con->SetHeader("Connection", "Keep-Alive");

con->Connect("www.some.host", 80);

// ATT: pass inputstream as reference, so it doesn't get destroyed
// while the following inputstreams (zlib, text) are still in scope
wxZlibInputStream inStream(*con->GetInputStream("/"), wxZLIB_GZIP);
wxTextInputStream txtStream(inStream);
[...]