]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: (parser) fix memory leak on error before end-of-file
authorKarel Zak <kzak@redhat.com>
Fri, 26 Jun 2020 10:59:32 +0000 (12:59 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 26 Jun 2020 10:59:32 +0000 (12:59 +0200)
Let's simplify the loop where we add FS to the table. The optimization
for recoverable errors is a fragile overkill. The new code always
allocates and unrefs FS for each loop.

Addresses: https://github.com/karelzak/util-linux/pull/1068
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/fs.c
libmount/src/tab_parse.c

index bcc8273488c19afdeb7464b49035e41a19555fef..52f937acc3454a754a1425acf038d0789cd07184 100644 (file)
@@ -39,7 +39,7 @@ struct libmnt_fs *mnt_new_fs(void)
 
        fs->refcount = 1;
        INIT_LIST_HEAD(&fs->ents);
-       /*DBG(FS, ul_debugobj(fs, "alloc"));*/
+       DBG(FS, ul_debugobj(fs, "alloc"));
        return fs;
 }
 
index 3b52f6b287ff967b126b85e0838b797fb27c5b23..e3f30c291fc6bf24f0b3f5796c65f8dda0f73e93 100644 (file)
@@ -703,7 +703,6 @@ static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *fi
        int rc = -1;
        int flags = 0;
        pid_t tid = -1;
-       struct libmnt_fs *fs = NULL;
        struct libmnt_parser pa = { .line = 0 };
 
        assert(tb);
@@ -723,19 +722,25 @@ static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *fi
        if (filename && strcmp(filename, _PATH_PROC_MOUNTS) == 0)
                flags = MNT_FS_KERNEL;
 
-       while (!feof(f)) {
-               if (!fs) {
-                       fs = mnt_new_fs();
-                       if (!fs)
-                               goto err;
+       do {
+               struct libmnt_fs *fs;
+
+               if (feof(f)) {
+                       DBG(TAB, ul_debugobj(tb, "end-of-file"));
+                       break;
                }
+               fs = mnt_new_fs();
+               if (!fs)
+                       goto err;
 
+               /* parse */
                rc = mnt_table_parse_next(&pa, tb, fs);
 
-               if (!rc && tb->fltrcb && tb->fltrcb(fs, tb->fltrcb_data))
-                       rc = 1; /* filtered out by callback... */
+               if (rc != 0 && tb->fltrcb && tb->fltrcb(fs, tb->fltrcb_data))
+                       rc = 1; /* error filtered out by callback... */
 
-               if (!rc) {
+               /* add to the table */
+               if (rc == 0) {
                        rc = mnt_table_add_fs(tb, fs);
                        fs->flags |= flags;
 
@@ -746,21 +751,21 @@ static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *fi
                        }
                }
 
-               if (rc) {
-                       if (rc > 0) {
-                               mnt_reset_fs(fs);
-                               assert(fs->refcount == 1);
-                               continue;       /* recoverable error, reuse fs*/
-                       }
+               /* remove refernece (or deallocate on error) */
+               mnt_unref_fs(fs);
 
-                       mnt_unref_fs(fs);
-                       if (feof(f))
-                               break;
-                       goto err;               /* fatal error */
+               /* recoverable error */
+               if (rc > 0) {
+                       DBG(TAB, ul_debugobj(tb, "recoverable error (continue)"));
+                       continue;
                }
-               mnt_unref_fs(fs);
-               fs = NULL;
-       }
+
+               /* fatal errors */
+               if (rc < 0 && !feof(f)) {
+                       DBG(TAB, ul_debugobj(tb, "fatal error"));
+                       goto err;
+               }
+       } while (1);
 
        DBG(TAB, ul_debugobj(tb, "%s: stop parsing (%d entries)",
                                filename, mnt_table_get_nents(tb)));