]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Reorganize initialization and buffer allocation for gzopen/gzread/gzwrite
authorHans Kristian Rosbach <hk-git@circlestorm.org>
Fri, 4 Jul 2025 15:53:09 +0000 (17:53 +0200)
committerHans Kristian Rosbach <hk-git@circlestorm.org>
Fri, 4 Jul 2025 19:49:42 +0000 (21:49 +0200)
gzguts.h
gzlib.c
gzread.c.in
gzwrite.c
zutil.c
zutil.h

index 14f2391152a44899ce2848189bc9e9d8e32cfafd..1f9adbfcf226121edd3123c0180e5aaf5d28f840 100644 (file)
--- a/gzguts.h
+++ b/gzguts.h
@@ -135,6 +135,10 @@ typedef gz_state *gz_statep;
 
 /* shared functions */
 void Z_INTERNAL gz_error(gz_state *, int, const char *);
+int  Z_INTERNAL gz_buffer_alloc(gz_state *state);
+void Z_INTERNAL gz_buffer_free(gz_state *state);
+void Z_INTERNAL gz_state_free(gz_state *state);
+
 #ifdef ZLIB_COMPAT
 unsigned Z_INTERNAL gz_intmax(void);
 #endif
diff --git a/gzlib.c b/gzlib.c
index b8a506b6a51f31c058dbb4d4e84cb6a5383c11a3..56815c20c14c1970cca168e12aa2b141f1723e30 100644 (file)
--- a/gzlib.c
+++ b/gzlib.c
 #endif
 
 /* Local functions */
+static gzFile gz_state_init();
 static void gz_reset(gz_state *);
 static gzFile gz_open(const void *, int, const char *);
 
+/* Initialize struct for gzFile state */
+static gzFile gz_state_init() {
+    /* allocate gzFile structure to return */
+    gz_state *state = (gz_state *)zng_alloc(sizeof(gz_state));
+    if (state == NULL)
+        return NULL;
+
+    state->strm.zalloc = NULL;
+    state->strm.zfree = NULL;
+    state->strm.opaque = NULL;
+    state->strm.next_in = NULL;
+
+    state->size = 0;
+    state->want = GZBUFSIZE;
+    state->in = NULL;
+    state->out = NULL;
+    state->direct = 0;
+    state->mode = GZ_NONE;
+    state->level = Z_DEFAULT_COMPRESSION;
+    state->strategy = Z_DEFAULT_STRATEGY;
+    state->msg = NULL;
+
+    return (gzFile)state;
+}
+
+void Z_INTERNAL gz_state_free(gz_state *state) {
+    zng_free(state);
+}
+
 /* Reset gzip file state */
 static void gz_reset(gz_state *state) {
     state->x.have = 0;              /* no output data available */
@@ -37,6 +67,40 @@ static void gz_reset(gz_state *state) {
     state->strm.avail_in = 0;       /* no input data yet */
 }
 
+/* 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)
+        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);
+    }
+
+    /* Return error if memory allocation failed */
+    if (state->in == NULL || (!skip_outbuff && state->out == NULL) ) {
+        gz_buffer_free(state);
+        gz_error(state, Z_MEM_ERROR, "out of memory");
+        return -1;
+    }
+
+    state->size = state->want; // mark state as initialized
+
+    return 0;
+}
+
+void Z_INTERNAL gz_buffer_free(gz_state *state) {
+    zng_free(state->out);
+    zng_free(state->in);
+    state->size = 0;
+}
+
 /* Open a gzip file either by name or file descriptor. */
 static gzFile gz_open(const void *path, int fd, const char *mode) {
     gz_state *state;
@@ -53,19 +117,12 @@ static gzFile gz_open(const void *path, int fd, const char *mode) {
     if (path == NULL)
         return NULL;
 
-    /* allocate gzFile structure to return */
-    state = (gz_state *)zng_alloc(sizeof(gz_state));
+    /* Initialize gzFile state */
+    state = (gz_state *)gz_state_init();
     if (state == NULL)
         return NULL;
-    state->size = 0;            /* no buffers allocated yet */
-    state->want = GZBUFSIZE;    /* requested buffer size */
-    state->msg = NULL;          /* no error message yet */
 
     /* interpret mode */
-    state->mode = GZ_NONE;
-    state->level = Z_DEFAULT_COMPRESSION;
-    state->strategy = Z_DEFAULT_STRATEGY;
-    state->direct = 0;
     while (*mode) {
         if (*mode >= '0' && *mode <= '9') {
             state->level = *mode - '0';
@@ -83,7 +140,7 @@ static gzFile gz_open(const void *path, int fd, const char *mode) {
                 break;
 #endif
             case '+':       /* can't read and write at the same time */
-                zng_free(state);
+                gz_state_free(state);
                 return NULL;
             case 'b':       /* ignore -- will request binary anyway */
                 break;
@@ -121,14 +178,14 @@ static gzFile gz_open(const void *path, int fd, const char *mode) {
 
     /* must provide an "r", "w", or "a" */
     if (state->mode == GZ_NONE) {
-        zng_free(state);
+        gz_state_free(state);
         return NULL;
     }
 
     /* can't force transparent read */
     if (state->mode == GZ_READ) {
         if (state->direct) {
-            zng_free(state);
+            gz_state_free(state);
             return NULL;
         }
         state->direct = 1;      /* for empty file */
@@ -145,7 +202,7 @@ static gzFile gz_open(const void *path, int fd, const char *mode) {
         len = strlen((const char *)path);
     state->path = (char *)malloc(len + 1);
     if (state->path == NULL) {
-        zng_free(state);
+        gz_state_free(state);
         return NULL;
     }
 #ifdef WIDECHAR
@@ -190,7 +247,7 @@ static gzFile gz_open(const void *path, int fd, const char *mode) {
         open((const char *)path, oflag, 0666));
     if (state->fd == -1) {
         free(state->path);
-        zng_free(state);
+        gz_state_free(state);
         return NULL;
     }
     if (state->mode == GZ_APPEND) {
@@ -224,14 +281,13 @@ gzFile Z_EXPORT PREFIX4(gzopen)(const char *path, const char *mode) {
 
 /* -- see zlib.h -- */
 gzFile Z_EXPORT PREFIX(gzdopen)(int fd, const char *mode) {
-    char *path;         /* identifier for error messages */
     gzFile gz;
+    char path[32];         /* identifier for error messages */
 
-    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
+    if (fd == -1)
         return NULL;
-    (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
+    (void)snprintf(path, 32, "<fd:%d>", fd); /* for debugging */
     gz = gz_open(path, fd, mode);
-    free(path);
     return gz;
 }
 
index 1fc7b370fde38d246c0c99ff9d802bd069502cb3..e725d54a2c4cd352ad1345845184211a6c7c5c03 100644 (file)
@@ -81,29 +81,15 @@ static int gz_avail(gz_state *state) {
 static int gz_look(gz_state *state) {
     PREFIX3(stream) *strm = &(state->strm);
 
-    /* allocate read buffers and inflate memory */
     if (state->size == 0) {
-        /* allocate buffers */
-        state->in = (unsigned char *)zng_alloc(state->want);
-        state->out = (unsigned char *)zng_alloc(state->want << 1);
-        if (state->in == NULL || state->out == NULL) {
-            zng_free(state->out);
-            zng_free(state->in);
-            gz_error(state, Z_MEM_ERROR, "out of memory");
+        /* Allocate gz buffers */
+        if (gz_buffer_alloc(state) != 0) {
             return -1;
         }
-        state->size = state->want;
-
-        /* allocate inflate memory */
-        state->strm.zalloc = NULL;
-        state->strm.zfree = NULL;
-        state->strm.opaque = NULL;
-        state->strm.avail_in = 0;
-        state->strm.next_in = NULL;
+
+        /* Initialize inflate state */
         if (PREFIX(inflateInit2)(&(state->strm), MAX_WBITS + 16) != Z_OK) {    /* gunzip */
-            zng_free(state->out);
-            zng_free(state->in);
-            state->size = 0;
+            gz_buffer_free(state);
             gz_error(state, Z_MEM_ERROR, "out of memory");
             return -1;
         }
@@ -594,8 +580,7 @@ int Z_EXPORT PREFIX(gzclose_r)(gzFile file) {
     /* free memory and close file */
     if (state->size) {
         PREFIX(inflateEnd)(&(state->strm));
-        zng_free(state->out);
-        zng_free(state->in);
+        gz_buffer_free(state);
     }
     err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
     gz_error(state, Z_OK, NULL);
index 08e0ce9aab2a401073f851d265d39c9755fda6c7..7bac0f77563714eb398c3b02ac93a42656200668 100644 (file)
--- a/gzwrite.c
+++ b/gzwrite.c
@@ -21,43 +21,22 @@ static int gz_init(gz_state *state) {
     int ret;
     PREFIX3(stream) *strm = &(state->strm);
 
-    /* allocate input buffer (double size for gzprintf) */
-    state->in = (unsigned char *)zng_alloc(state->want << 1);
-    if (state->in == NULL) {
-        gz_error(state, Z_MEM_ERROR, "out of memory");
+    /* Allocate gz buffers */
+    if (gz_buffer_alloc(state) != 0)
         return -1;
-    }
-    memset(state->in, 0, state->want << 1);
 
-    /* only need output buffer and deflate state if compressing */
+    /* only need deflate state if compressing */
     if (!state->direct) {
-        /* allocate output buffer */
-        state->out = (unsigned char *)zng_alloc(state->want);
-        if (state->out == NULL) {
-            zng_free(state->in);
-            gz_error(state, Z_MEM_ERROR, "out of memory");
-            return -1;
-        }
-
         /* allocate deflate memory, set up for gzip compression */
-        strm->zalloc = NULL;
-        strm->zfree = NULL;
-        strm->opaque = NULL;
         ret = PREFIX(deflateInit2)(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
         if (ret != Z_OK) {
-            zng_free(state->out);
-            zng_free(state->in);
+            gz_buffer_free(state);
             gz_error(state, Z_MEM_ERROR, "out of memory");
             return -1;
         }
         strm->next_in = NULL;
-    }
 
-    /* mark state as initialized */
-    state->size = state->want;
-
-    /* initialize write buffer if compressing */
-    if (!state->direct) {
+        /* initialize write buffer */
         strm->avail_out = state->size;
         strm->next_out = state->out;
         state->x.next = strm->next_out;
@@ -513,14 +492,13 @@ int Z_EXPORT PREFIX(gzclose_w)(gzFile file) {
     if (state->size) {
         if (!state->direct) {
             (void)PREFIX(deflateEnd)(&(state->strm));
-            zng_free(state->out);
         }
-        zng_free(state->in);
+        gz_buffer_free(state);
     }
     gz_error(state, Z_OK, NULL);
     free(state->path);
     if (close(state->fd) == -1)
         ret = Z_ERRNO;
-    zng_free(state);
+    gz_state_free(state);
     return ret;
 }
diff --git a/zutil.c b/zutil.c
index 99818c3a7b9e04614a65b14bc9edab8aed9b9010..886e0ce5557bca68d4a63060ea1b880b39342889 100644 (file)
--- a/zutil.c
+++ b/zutil.c
@@ -109,3 +109,41 @@ void Z_INTERNAL PREFIX(zcfree)(void *opaque, void *ptr) {
     Z_UNUSED(opaque);
     zng_free(ptr);
 }
+
+/* Provide aligned allocations, only used by gz* code */
+void Z_INTERNAL *zng_alloc_aligned(unsigned size, unsigned align) {
+    uintptr_t return_ptr, original_ptr;
+    uint32_t alloc_size, align_diff;
+    void *ptr;
+
+    /* Allocate enough memory for proper alignment and to store the original memory pointer */
+    alloc_size = sizeof(void *) + size + align;
+    ptr = zng_alloc(alloc_size);
+    if (!ptr)
+        return NULL;
+
+    /* Calculate return pointer address with space enough to store original pointer */
+    align_diff = align - ((uintptr_t)ptr % align);
+    return_ptr = (uintptr_t)ptr + align_diff;
+    if (align_diff < sizeof(void *))
+        return_ptr += align;
+
+    /* Store the original pointer for free() */
+    original_ptr = return_ptr - sizeof(void *);
+    memcpy((void *)original_ptr, &ptr, sizeof(void *));
+
+    /* Return properly aligned pointer in allocation */
+    return (void *)return_ptr;
+}
+
+void Z_INTERNAL zng_free_aligned(void *ptr) {
+    if (!ptr)
+        return;
+
+    /* Calculate offset to original memory allocation pointer */
+    void *original_ptr = (void *)((uintptr_t)ptr - sizeof(void *));
+    void *free_ptr = *(void **)original_ptr;
+
+    /* Free original memory allocation */
+    zng_free(free_ptr);
+}
diff --git a/zutil.h b/zutil.h
index a6284502d047e8af74a5d0159da9825b80625208..9017c687f1c4c7d4a1bf8025a748a5466375111e 100644 (file)
--- a/zutil.h
+++ b/zutil.h
@@ -133,6 +133,8 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */
 
 void Z_INTERNAL *PREFIX(zcalloc)(void *opaque, unsigned items, unsigned size);
 void Z_INTERNAL  PREFIX(zcfree)(void *opaque, void *ptr);
+void Z_INTERNAL *zng_alloc_aligned(unsigned size, unsigned align);
+void Z_INTERNAL zng_free_aligned(void *ptr);
 
 typedef void *zng_calloc_func(void *opaque, unsigned items, unsigned size);
 typedef void  zng_cfree_func(void *opaque, void *ptr);