]> git.ipfire.org Git - location/libloc.git/commitdiff
stringpool: Avoid memory leak if mmap() fails
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 11 Jul 2021 12:27:43 +0000 (12:27 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 11 Jul 2021 12:27:43 +0000 (12:27 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/stringpool.c

index 7f641f8a57b625b1fc5c78fae663a550c7c797d0..49606de2609f68eeaaf19c8902f3e6374fcfb53c 100644 (file)
@@ -105,6 +105,30 @@ static off_t loc_stringpool_append(struct loc_stringpool* pool, const char* stri
        return offset;
 }
 
+static void loc_stringpool_free(struct loc_stringpool* pool) {
+       DEBUG(pool->ctx, "Releasing string pool %p\n", pool);
+       int r;
+
+       switch (pool->mode) {
+               case STRINGPOOL_DEFAULT:
+                       if (pool->data)
+                               free(pool->data);
+                       break;
+
+               case STRINGPOOL_MMAP:
+                       if (pool->data) {
+                               r = munmap(pool->data, pool->length);
+                               if (r)
+                                       ERROR(pool->ctx, "Could not unmap data at %p: %s\n",
+                                               pool->data, strerror(errno));
+                       }
+                       break;
+       }
+
+       loc_unref(pool->ctx);
+       free(pool);
+}
+
 LOC_EXPORT int loc_stringpool_new(struct loc_ctx* ctx, struct loc_stringpool** pool) {
        struct loc_stringpool* p = calloc(1, sizeof(*p));
        if (!p)
@@ -135,29 +159,33 @@ static int loc_stringpool_mmap(struct loc_stringpool* pool, FILE* f, size_t leng
        pool->length = length;
 
        if (pool->data == MAP_FAILED)
-               return -errno;
+               return 1;
 
        return 0;
 }
 
 LOC_EXPORT int loc_stringpool_open(struct loc_ctx* ctx, struct loc_stringpool** pool,
                FILE* f, size_t length, off_t offset) {
-       int r = loc_stringpool_new(ctx, pool);
+       struct loc_stringpool* p = NULL;
+
+       // Allocate a new stringpool
+       int r = loc_stringpool_new(ctx, &p);
        if (r)
                return r;
 
-       struct loc_stringpool* p = *pool;
-
        // Change mode to mmap
        p->mode = STRINGPOOL_MMAP;
 
        // Map data into memory
        if (length > 0) {
                r = loc_stringpool_mmap(p, f, length, offset);
-               if (r)
+               if (r) {
+                       loc_stringpool_free(p);
                        return r;
+               }
        }
 
+       *pool = p;
        return 0;
 }
 
@@ -167,30 +195,6 @@ LOC_EXPORT struct loc_stringpool* loc_stringpool_ref(struct loc_stringpool* pool
        return pool;
 }
 
-static void loc_stringpool_free(struct loc_stringpool* pool) {
-       DEBUG(pool->ctx, "Releasing string pool %p\n", pool);
-       int r;
-
-       switch (pool->mode) {
-               case STRINGPOOL_DEFAULT:
-                       if (pool->data)
-                               free(pool->data);
-                       break;
-
-               case STRINGPOOL_MMAP:
-                       if (pool->data) {
-                               r = munmap(pool->data, pool->length);
-                               if (r)
-                                       ERROR(pool->ctx, "Could not unmap data at %p: %s\n",
-                                               pool->data, strerror(errno));
-                       }
-                       break;
-       }
-
-       loc_unref(pool->ctx);
-       free(pool);
-}
-
 LOC_EXPORT struct loc_stringpool* loc_stringpool_unref(struct loc_stringpool* pool) {
        if (--pool->refcount > 0)
                return NULL;