]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Use a single malloc call for both in and out buffers in gzopen/gzread/gzwrite.
authorHans Kristian Rosbach <hk-git@circlestorm.org>
Fri, 4 Jul 2025 18:58:28 +0000 (20:58 +0200)
committerHans Kristian Rosbach <hk-git@circlestorm.org>
Fri, 4 Jul 2025 19:59:18 +0000 (21:59 +0200)
Also start aligning the allocation to 64 bytes (on a cacheline border).

gzguts.h
gzlib.c

index 1f9adbfcf226121edd3123c0180e5aaf5d28f840..a5a0b40b1cb2bfa786452647098b0e0c27e348d3 100644 (file)
--- a/gzguts.h
+++ b/gzguts.h
@@ -112,6 +112,7 @@ typedef struct {
     unsigned want;          /* requested buffer size, default is GZBUFSIZE */
     unsigned char *in;      /* input buffer (double-sized when writing) */
     unsigned char *out;     /* output buffer (double-sized when reading) */
+    unsigned char *buffers; /* Pointer to the real input/output buffer allocation */
     int direct;             /* 0 if processing gzip, 1 if transparent */
         /* just for reading */
     int how;                /* 0: get header, 1: copy, 2: decompress */
diff --git a/gzlib.c b/gzlib.c
index 56815c20c14c1970cca168e12aa2b141f1723e30..5fd6ca40dd76f2a6a95ac6a813fb0d89dfb5c250 100644 (file)
--- a/gzlib.c
+++ b/gzlib.c
@@ -4,6 +4,7 @@
  */
 
 #include "zbuild.h"
+#include "zutil.h"
 #include "zutil_p.h"
 #include "gzguts.h"
 
@@ -70,21 +71,23 @@ static void gz_reset(gz_state *state) {
 /* Allocate in/out buffers for gzFile */
 int Z_INTERNAL gz_buffer_alloc(gz_state *state) {
     int in_mult = 1, out_mult = 1;
-    int skip_outbuff = (state->mode == GZ_WRITE && state->direct);
 
-    if (state->mode == GZ_WRITE)
-        in_mult = 2; // double imput buffer for compression (ref: gzprintf)
-    else if (state->mode == GZ_READ)
+    if (state->mode == GZ_WRITE) {
+        in_mult = 2; // double input buffer for compression (ref: gzprintf)
+        if (state->direct)
+            out_mult = 0; // output buffer not needed in write + direct mode
+    } else if (state->mode == GZ_READ) {
         out_mult = 2;  // double output buffer for decompression
+    }
 
-    state->in = (unsigned char *)zng_alloc(state->want * in_mult);
-    /* Don't need output buffer if compressing with state->direct set */
-    if ( !skip_outbuff ) {
-        state->out = (unsigned char *)zng_alloc(state->want * out_mult);
+    state->buffers = (unsigned char *)zng_alloc_aligned(state->want * (in_mult + out_mult), 64);
+    state->in = state->buffers;
+    if (out_mult >= 1) {
+        state->out = state->buffers + (state->want * in_mult); // Outbuffer goes after inbuffer
     }
 
     /* Return error if memory allocation failed */
-    if (state->in == NULL || (!skip_outbuff && state->out == NULL) ) {
+    if (state->in == NULL || (out_mult >= 1 && state->out == NULL) ) {
         gz_buffer_free(state);
         gz_error(state, Z_MEM_ERROR, "out of memory");
         return -1;
@@ -96,8 +99,10 @@ int Z_INTERNAL gz_buffer_alloc(gz_state *state) {
 }
 
 void Z_INTERNAL gz_buffer_free(gz_state *state) {
-    zng_free(state->out);
-    zng_free(state->in);
+    zng_free_aligned(state->buffers);
+    state->buffers = NULL;
+    state->out = NULL;
+    state->in = NULL;
     state->size = 0;
 }