[prev in list] [next in list] [prev in thread] [next in thread] 

List:       helix-filesystem-cvs
Subject:    [Filesystem-cvs] http decoder.cpp, 1.5, 1.5.40.1 decoder.h, 1.2,
From:       tknox () helixcommunity ! org
Date:       2006-03-08 2:28:01
[Download RAW message or body]

Update of /cvsroot/filesystem/http
In directory cvs:/tmp/cvs-serv30656

Modified Files:
      Tag: SERVER_11_1
	decoder.cpp decoder.h httpfsys.cpp httpfsys.h 
Log Message:
Synopsis
========
Fixes PR 152802: Server spins at nearly 100% CPU for about a minute on retreival of \
attached UAP from gzip-encoding HTTP server

Branches: head, SERVER_11_1
Suggested Reviewer: ehyche, any


Description
===========

The http plugin can be used to fetch a UAP for displaying content.
If the UAP claims to be gzip encoded, but is not, in certain cases it
can cause the server to spin forever.

The decoder attempts to skip the gzip header, and if it doesn't get enough
bytes of data, rewrites the HXR_INCOMPLETE to an HXR_OK, and trusts that
future reads will supply the remaining data. Unfortunately, that won't
work when the remote site has sent all the data it intends to. The fix is
to note when the decoder rewrites the header, and in the client of the
decoder to check for the rewrite, as well as for having already read at
least as many bytes as the content length header specified. In that case,
the client rewrites the HXR_OK to an HXR_FAIL, and gives up.

Per comments from ehyche, rewrote methods in decoder.{h,cpp}.

Files Affected
==============

filesystem/http/decoder.h
filesystem/http/decoder.cpp
filesystem/http/httpfsys.h
filesystem/http/httpfsys.cpp


Testing Performed
=================
Tested using the repro steps given in the PR, and the server now does
the right thing and gives up.

Platforms Tested: linux-rhel4-i686
Build verified: linux-rhel4-i686, sunos-5.9-sparc-server, win32-i386-vc7


QA Hints
===============

Nothing special.


Additional Notes
================
* The http code should attempt to timeout the connection, which it didn't
do in my testing. A new PR may be needed to address that issue.
* The diffs are from HEAD. The main change is that HEAD uses HXBOOL instead
plain old BOOL. I will check in the appropriate versions of each.


Index: httpfsys.h
===================================================================
RCS file: /cvsroot/filesystem/http/httpfsys.h,v
retrieving revision 1.21.2.3.6.2
retrieving revision 1.21.2.3.6.3
diff -u -d -r1.21.2.3.6.2 -r1.21.2.3.6.3
--- httpfsys.h	27 Jan 2006 22:10:15 -0000	1.21.2.3.6.2
+++ httpfsys.h	8 Mar 2006 02:27:58 -0000	1.21.2.3.6.3
@@ -842,6 +842,7 @@
 
     BOOL                        m_bKnowContentSize;
     ULONG32                     m_nContentSize;
+    ULONG32                     m_nOriginalContentSize;
     BOOL                        m_bEncoded;
 
     BOOL                        m_bChunkedEncoding;

Index: decoder.cpp
===================================================================
RCS file: /cvsroot/filesystem/http/decoder.cpp,v
retrieving revision 1.5
retrieving revision 1.5.40.1
diff -u -d -r1.5 -r1.5.40.1
--- decoder.cpp	9 Jul 2004 18:40:30 -0000	1.5
+++ decoder.cpp	8 Mar 2006 02:27:58 -0000	1.5.40.1
@@ -87,6 +87,7 @@
     , m_pOutputBuf	(NULL)
     , m_bHeaderRemoved	(FALSE)
     , m_bStarted	(FALSE)
+    , m_bSeenIncomplete	(FALSE)
 {
     m_DStream.avail_in = 0;
     m_DStream.next_in = NULL;
@@ -130,6 +131,8 @@
     m_DStream.avail_out = 0;
     m_DStream.next_out = NULL;
 
+    SetSeenIncomplete (FALSE);
+
     int err = Z_OK;
     err = inflateInit2(&m_DStream, -MAX_WBITS);
     if (err != Z_OK) 
@@ -179,6 +182,7 @@
 	    // We failed simply because we don't yet have
 	    // enough data to begin decompression. We'll
 	    // just try again when the next chunk comes in.
+            SetSeenIncomplete(TRUE);
 	    hResult = HXR_OK;
 	}
     }
@@ -444,3 +448,15 @@
 
     return hResult;
 }
+
+BOOL
+CDecoder::SeenIncomplete() const
+{
+    return m_bSeenIncomplete;
+}
+
+void
+CDecoder::SetSeenIncomplete(BOOL bSeenIncomplete)
+{
+    m_bSeenIncomplete = bSeenIncomplete;
+}

Index: decoder.h
===================================================================
RCS file: /cvsroot/filesystem/http/decoder.h,v
retrieving revision 1.2
retrieving revision 1.2.36.1
diff -u -d -r1.2 -r1.2.36.1
--- decoder.h	9 Jul 2004 18:40:30 -0000	1.2
+++ decoder.h	8 Mar 2006 02:27:58 -0000	1.2.36.1
@@ -76,6 +76,7 @@
 				 const char* pBuf, 
 				 UINT32 ulCount);
     UINT32	GetContentRead	();
+    BOOL        SeenIncomplete  () const;
 
 private:
     CChunkyRes*	    m_pOutputSink;
@@ -88,6 +89,9 @@
     BOOL	    m_bHeaderRemoved;
     BOOL	    m_bStarted;
     z_stream	    m_DStream;		// Decompression Stream
+    BOOL	    m_bSeenIncomplete;  // Have we seen an incomplete header?
+
+    void        SetSeenIncomplete (BOOL bSeenIncomplete);
 
     // Helper methods
     HX_RESULT	Reset		();

Index: httpfsys.cpp
===================================================================
RCS file: /cvsroot/filesystem/http/httpfsys.cpp,v
retrieving revision 1.61.2.5.6.4
retrieving revision 1.61.2.5.6.5
diff -u -d -r1.61.2.5.6.4 -r1.61.2.5.6.5
--- httpfsys.cpp	27 Jan 2006 22:10:15 -0000	1.61.2.5.6.4
+++ httpfsys.cpp	8 Mar 2006 02:27:58 -0000	1.61.2.5.6.5
@@ -968,6 +968,7 @@
 
     , m_bKnowContentSize(FALSE)
     , m_nContentSize(0)
+    , m_nOriginalContentSize(0)
     , m_bEncoded(FALSE)
 
     , m_bChunkedEncoding(FALSE)
@@ -4994,7 +4995,7 @@
         UINT32 ulValue = 0;
         if (pMessage->getHeaderValue("content-length", ulValue))
         {
-            m_nContentSize = ulValue;
+            m_nOriginalContentSize = m_nContentSize = ulValue;
 
             // xxxbobclark the problem is that m_nContentSize is really
             // the content size of this particular GET. And if we're getting
@@ -5019,7 +5020,7 @@
                 if (numFields == 2)
                 {
                     CHXString theDenominator = theContentRange.NthField('/', 2);
-                    m_nContentSize = strtol((const char*)theDenominator, 0, 10);
+                    m_nOriginalContentSize = m_nContentSize = strtol((const \
char*)theDenominator, 0, 10);  }
             }
         }
@@ -5031,7 +5032,7 @@
                 m_ulPrgDnTotalFileSize != HX_PROGDOWNLD_UNKNOWN_FILE_SIZE)
         {
             m_bKnowContentSize = TRUE;
-            m_nContentSize = m_ulPrgDnTotalFileSize;
+            m_nOriginalContentSize = m_nContentSize = m_ulPrgDnTotalFileSize;
         }
         else if (m_bKnowContentSize)
         {
@@ -5142,6 +5143,15 @@
                     nContentLen);
                 m_nContentRead = m_pDecoder->GetContentRead();
 
+                if (m_pDecoder->SeenIncomplete()
+                    && m_nOriginalContentSize
+                    && nContentLen >= m_nOriginalContentSize)
+                {
+                    // If we read all the data the header told us was coming,
+                    // we're not incomplete, we failed.
+                    theErr = HXR_FAIL;
+                }
+
                 if (FAILED(theErr))
                 {
                     // A failure occurred while trying to decode
@@ -5165,7 +5175,7 @@
                 m_pChunkedEncoding->state = CE_HEADER_PENDING;
                 m_pChunkedEncoding->buf = new char[MAX_CHUNK_SIZE];
 
-                DecodeChunkedEncoding(m_pChunkedEncoding,
+                theErr = DecodeChunkedEncoding(m_pChunkedEncoding,
                       (const char*)pBuffer->GetBuffer() + ulHeaderLength,
                                       nContentLen);
             }
@@ -7532,6 +7542,16 @@
                                                  (char*) pBuffer->GetBuffer(),
                                                  ulSize);
                     m_nContentRead = m_pDecoder->GetContentRead();
+
+                    if (m_pDecoder->SeenIncomplete()
+                        && m_nOriginalContentSize
+                        && ulSize >= m_nOriginalContentSize)
+                    {
+                        // If we read all the data the header told us was coming,
+                        // we're not incomplete, we failed.
+                        retVal = HXR_FAIL;
+                    }
+
                     if (FAILED(retVal))
                     {
                         // A failure occurred while trying to decode
@@ -7559,7 +7579,7 @@
                         m_pChunkedEncoding->buf = new char[MAX_CHUNK_SIZE];
                     }
 
-                    DecodeChunkedEncoding(m_pChunkedEncoding,
+                    retVal = DecodeChunkedEncoding(m_pChunkedEncoding,
                                           (const char*)pBuffer->GetBuffer(),
                                           ulSize);
                 }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic