From 780f79420073e0c09cd41afea28ac217a6d4ef29 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 26 Jun 2020 12:59:32 +0200 Subject: [PATCH 49/55] libmount: (parser) fix memory leak on error before end-of-file 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 Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1900498 Upstream: http://github.com/karelzak/util-linux/commit/fe0d12d4f82269096f8d0cffc51ca9590814c284 Signed-off-by: Karel Zak --- libmount/src/fs.c | 2 +- libmount/src/tab_parse.c | 49 ++++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/libmount/src/fs.c b/libmount/src/fs.c index def32253c..aae4961c3 100644 --- a/libmount/src/fs.c +++ b/libmount/src/fs.c @@ -34,7 +34,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; } diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c index 10fc68279..719c1abca 100644 --- a/libmount/src/tab_parse.c +++ b/libmount/src/tab_parse.c @@ -608,7 +608,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); @@ -628,19 +627,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; @@ -651,21 +656,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))); -- 2.29.2