[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] trunk r113804: * decompress.c: Fix bugs with large buffers
From: |
Paul Eggert |
Subject: |
[Emacs-diffs] trunk r113804: * decompress.c: Fix bugs with large buffers and weird inputs. |
Date: |
Sun, 11 Aug 2013 23:09:34 +0000 |
User-agent: |
Bazaar (2.6b2) |
------------------------------------------------------------
revno: 113804
revision-id: address@hidden
parent: address@hidden
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Sun 2013-08-11 16:09:26 -0700
message:
* decompress.c: Fix bugs with large buffers and weird inputs.
Tune a bit. Reindent as per usual Emacs style.
(BUFFER_SIZE): Remove.
(Fdecompress_gzipped_region): Do not mishandle input buffers with
more than UINT_MAX bytes. Decompress into the gap instead of into
an auto buffer, as this should avoid copying. Return nil if
'inflate' returns Z_NEED_DICT, as we have no dictionary. Do not
set immediate_quit; we shouldn't trust zlib code that much.
modified:
src/ChangeLog changelog-20091113204419-o5vbwnq5f7feedwu-1438
src/decompress.c decompress.c-20130811194033-wfhl0tqmmc36jfmu-1
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog 2013-08-11 20:51:47 +0000
+++ b/src/ChangeLog 2013-08-11 23:09:26 +0000
@@ -1,3 +1,14 @@
+2013-08-11 Paul Eggert <address@hidden>
+
+ * decompress.c: Fix bugs with large buffers and weird inputs.
+ Tune a bit. Reindent as per usual Emacs style.
+ (BUFFER_SIZE): Remove.
+ (Fdecompress_gzipped_region): Do not mishandle input buffers with
+ more than UINT_MAX bytes. Decompress into the gap instead of into
+ an auto buffer, as this should avoid copying. Return nil if
+ 'inflate' returns Z_NEED_DICT, as we have no dictionary. Do not
+ set immediate_quit; we shouldn't trust zlib code that much.
+
2013-08-11 Lars Magne Ingebrigtsen <address@hidden>
* decompress.c (Fdecompress_gzipped_region): Respect all zlib
=== modified file 'src/decompress.c'
--- a/src/decompress.c 2013-08-11 20:51:47 +0000
+++ b/src/decompress.c 2013-08-11 23:09:26 +0000
@@ -27,48 +27,48 @@
#include "buffer.h"
-#define BUFFER_SIZE 16384
-
-struct decompress_unwind_data {
+struct decompress_unwind_data
+{
ptrdiff_t old_point, start;
z_stream *stream;
};
static void
-unwind_decompress (void *ddata) {
+unwind_decompress (void *ddata)
+{
struct decompress_unwind_data *data = ddata;
inflateEnd (data->stream);
- /* Delete any uncompressed data already inserted and restore
- point. */
- if (data->start) {
- del_range (data->start, PT);
- SET_PT (data->old_point);
- }
+
+ /* Delete any uncompressed data already inserted and restore point. */
+ if (data->start)
+ {
+ del_range (data->start, PT);
+ SET_PT (data->old_point);
+ }
}
DEFUN ("decompress-gzipped-region", Fdecompress_gzipped_region,
Sdecompress_gzipped_region,
2, 2, 0,
doc: /* Decompress a gzip-compressed region.
-The text in the region will be replaced by the decompressed data.
-On failure, nil is returned and the data is left in place.
-This function can only be called in unibyte buffers.*/)
+Replace the text in the region by the decompressed data.
+On failure, return nil and leave the data in place.
+This function can be called only in unibyte buffers. */)
(Lisp_Object start, Lisp_Object end)
{
- ptrdiff_t istart, iend, point = PT;
+ ptrdiff_t istart, iend, pos_byte;
z_stream stream;
- int decompressed;
- char out[16384];
+ int inflate_status;
struct decompress_unwind_data unwind_data;
ptrdiff_t count = SPECPDL_INDEX ();
validate_region (&start, &end);
if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
- error ("This function can only be called in unibyte buffers");
+ error ("This function can be called only in unibyte buffers");
/* This is a unibyte buffer, so character positions and bytes are
- the same. */
+ the same. */
istart = XINT (start);
iend = XINT (end);
move_gap_both (iend, iend);
@@ -79,49 +79,55 @@
stream.avail_in = 0;
stream.next_in = Z_NULL;
- /* This magic number apparently means "this is gzip". */
+ /* This magic number apparently means "this is gzip". */
if (inflateInit2 (&stream, 16 + MAX_WBITS) != Z_OK)
return Qnil;
- /* We're inserting the decompressed data at the end of the
- compressed data. */
- SET_PT (iend);
-
- stream.avail_in = iend - istart;
- stream.next_in = (char *) BYTE_POS_ADDR (istart);
-
unwind_data.start = iend;
unwind_data.stream = &stream;
- unwind_data.old_point = point;
+ unwind_data.old_point = PT;
+
record_unwind_protect_ptr (unwind_decompress, &unwind_data);
- immediate_quit = 1;
-
- /* Run inflate() on input until the output buffer isn't full. */
- do {
- int result;
- stream.avail_out = BUFFER_SIZE;
- stream.next_out = out;
- result = inflate (&stream, Z_NO_FLUSH);
- if (result < 0) {
- unbind_to (count, Qnil);
- return Qnil;
+ /* Insert the decompressed data at the end of the compressed data. */
+ SET_PT (iend);
+
+ pos_byte = istart;
+
+ /* Keep calling 'inflate' until it reports an error or end-of-input. */
+ do
+ {
+ /* Maximum number of bytes that one 'inflate' call should read and write.
+ zlib requires that these values not exceed UINT_MAX.
+ Do not make avail_out too large, as that might unduly delay C-g. */
+ ptrdiff_t avail_in = min (iend - pos_byte, UINT_MAX);
+ ptrdiff_t avail_out = min (1 << 14, UINT_MAX);
+
+ ptrdiff_t decompressed;
+
+ if (GAP_SIZE < avail_out)
+ make_gap (avail_out - GAP_SIZE);
+ stream.next_in = BYTE_POS_ADDR (pos_byte);
+ stream.avail_in = avail_in;
+ stream.next_out = GPT_ADDR;
+ stream.avail_out = avail_out;
+ inflate_status = inflate (&stream, Z_NO_FLUSH);
+ pos_byte += avail_in - stream.avail_in;
+ decompressed = avail_out - stream.avail_out;
+ insert_from_gap (decompressed, decompressed, 0);
+ QUIT;
}
-
- decompressed = BUFFER_SIZE - stream.avail_out;
- insert_1_both (out, decompressed, decompressed, 0, 0, 0);
- QUIT;
- } while (stream.avail_out == 0);
-
- immediate_quit = 0;
+ while (inflate_status == Z_OK);
+
+ if (inflate_status != Z_STREAM_END)
+ return unbind_to (count, Qnil);
unwind_data.start = 0;
- unbind_to (count, Qnil);
- /* Delete the compressed data. */
+ /* Delete the compressed data. */
del_range (istart, iend);
- return Qt;
+ return unbind_to (count, Qt);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] trunk r113804: * decompress.c: Fix bugs with large buffers and weird inputs.,
Paul Eggert <=
- Prev by Date:
[Emacs-diffs] trunk r113803: Add --with-zlib to 'configure'.
- Next by Date:
[Emacs-diffs] trunk r113805: Add build, install, uninstall rules for all dvi, html, pdf, ps manuals
- Previous by thread:
[Emacs-diffs] trunk r113803: Add --with-zlib to 'configure'.
- Next by thread:
[Emacs-diffs] trunk r113805: Add build, install, uninstall rules for all dvi, html, pdf, ps manuals
- Index(es):