[pypy-svn] r46868 - in pypy/dist/pypy/rlib: . test

arigo at codespeak.net arigo at codespeak.net
Tue Sep 25 19:42:39 CEST 2007


Author: arigo
Date: Tue Sep 25 19:42:39 2007
New Revision: 46868

Modified:
   pypy/dist/pypy/rlib/rzlib.py
   pypy/dist/pypy/rlib/test/test_rzlib.py
Log:
Fix the decompression flushing, now that I understood the purpose
of the flush() method of decompression objects: it's there only
to complain if the input stream was truncated at some point.


Modified: pypy/dist/pypy/rlib/rzlib.py
==============================================================================
--- pypy/dist/pypy/rlib/rzlib.py	(original)
+++ pypy/dist/pypy/rlib/rzlib.py	Tue Sep 25 19:42:39 2007
@@ -189,6 +189,8 @@
         return RZlibError(msg)
     fromstream = staticmethod(fromstream)
 
+null_stream = lltype.nullptr(z_stream)
+
 
 def deflateInit(level=Z_DEFAULT_COMPRESSION, method=Z_DEFLATED,
                 wbits=MAX_WBITS, memLevel=DEF_MEM_LEVEL,
@@ -215,15 +217,9 @@
 def deflateEnd(stream):
     """
     Free the resources associated with the deflate stream.
-    Note that this may raise RZlibError.
     """
-    try:
-        err = _deflateEnd(stream)
-        if err != Z_OK:
-            raise RZlibError.fromstream(stream, err,
-                "while finishing compression")
-    finally:
-        lltype.free(stream, flavor='raw')
+    _deflateEnd(stream)
+    lltype.free(stream, flavor='raw')
 
 
 def inflateInit(wbits=MAX_WBITS):
@@ -251,13 +247,8 @@
     Free the resources associated with the inflate stream.
     Note that this may raise RZlibError.
     """
-    try:
-        err = _inflateEnd(stream)
-        if err != Z_OK:
-            raise RZlibError.fromstream(stream, err,
-                "while finishing decompression")
-    finally:
-        lltype.free(stream, flavor='raw')
+    _inflateEnd(stream)
+    lltype.free(stream, flavor='raw')
 
 
 def compress(stream, data, flush=Z_NO_FLUSH):
@@ -269,10 +260,10 @@
     """
     # Warning, reentrant calls to the zlib with a given stream can cause it
     # to crash.  The caller of pypy.rlib.rzlib should use locks if needed.
-    return _operate(stream, data, flush, _deflate, "while compressing")
+    return _operate(stream, data, flush, False, _deflate, "while compressing")
 
 
-def decompress(stream, data, flush=Z_NO_FLUSH):
+def decompress(stream, data, flush=Z_SYNC_FLUSH):
     """
     Feed more data into an inflate stream.  Returns a string containing
     (a part of) the decompressed data.  If flush != Z_NO_FLUSH, this also
@@ -282,15 +273,19 @@
     # Warning, reentrant calls to the zlib with a given stream can cause it
     # to crash.  The caller of pypy.rlib.rzlib should use locks if needed.
 
-    # _operate() does not support the Z_FINISH method of decompressing,
-    # which is for one-shot decompression where a single output buffer is
-    # large enough.  We can just map Z_FINISH to Z_SYNC_FLUSH.
+    # _operate() does not support the Z_FINISH method of decompressing.
+    # We can use Z_SYNC_FLUSH instead and manually check that we got to
+    # the end of the data.
     if flush == Z_FINISH:
         flush = Z_SYNC_FLUSH
-    return _operate(stream, data, flush, _inflate, "while decompressing")
+        should_finish = True
+    else:
+        should_finish = False
+    return _operate(stream, data, flush, should_finish, _inflate,
+                    "while decompressing")
 
 
-def _operate(stream, data, flush, cfunc, while_doing):
+def _operate(stream, data, flush, should_finish, cfunc, while_doing):
     """Common code for compress() and decompress().
     """
     # Prepare the input buffer for the stream
@@ -348,5 +343,11 @@
     finally:
         lltype.free(inbuf, flavor='raw')
 
+    # When decompressing, if the compressed stream of data was truncated,
+    # then the zlib simply returns Z_OK and waits for more.  Let's detect
+    # this situation and complain.
+    if should_finish and err != Z_STREAM_END:
+        raise RZlibError("the input compressed stream of data is not complete")
+
     assert not stream.c_avail_in, "not all input consumed by deflate/inflate"
     return ''.join(result)

Modified: pypy/dist/pypy/rlib/test/test_rzlib.py
==============================================================================
--- pypy/dist/pypy/rlib/test/test_rzlib.py	(original)
+++ pypy/dist/pypy/rlib/test/test_rzlib.py	Tue Sep 25 19:42:39 2007
@@ -3,6 +3,7 @@
 Tests for the rzlib module.
 """
 
+import py
 from pypy.rlib import rzlib
 from pypy.rlib.rarithmetic import r_uint
 import zlib
@@ -137,3 +138,22 @@
     bytes = rzlib.decompress(stream, compressed, rzlib.Z_FINISH)
     rzlib.inflateEnd(stream)
     assert bytes == expanded
+
+
+def test_decompression_truncated_input():
+    """
+    Test that we can accept incomplete input when inflating, but also
+    detect this situation when using Z_FINISH.
+    """
+    expanded = repr(range(20000))
+    compressed = zlib.compress(expanded)
+    print len(compressed), '=>', len(expanded)
+    stream = rzlib.inflateInit()
+    data = rzlib.decompress(stream, compressed[:1000])
+    assert expanded.startswith(data)
+    data += rzlib.decompress(stream, compressed[1000:2000])
+    assert expanded.startswith(data)
+    py.test.raises(rzlib.RZlibError,
+                   rzlib.decompress, stream, compressed[2000:-500],
+                   rzlib.Z_FINISH)
+    rzlib.inflateEnd(stream)



More information about the Pypy-commit mailing list