df3f53
From 780f79420073e0c09cd41afea28ac217a6d4ef29 Mon Sep 17 00:00:00 2001
df3f53
From: Karel Zak <kzak@redhat.com>
df3f53
Date: Fri, 26 Jun 2020 12:59:32 +0200
df3f53
Subject: [PATCH 49/55] libmount: (parser) fix memory leak on error before
df3f53
 end-of-file
df3f53
df3f53
Let's simplify the loop where we add FS to the table. The optimization
df3f53
for recoverable errors is a fragile overkill. The new code always
df3f53
allocates and unrefs FS for each loop.
df3f53
df3f53
Addresses: https://github.com/karelzak/util-linux/pull/1068
df3f53
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1900498
df3f53
Upstream: http://github.com/karelzak/util-linux/commit/fe0d12d4f82269096f8d0cffc51ca9590814c284
df3f53
Signed-off-by: Karel Zak <kzak@redhat.com>
df3f53
---
df3f53
 libmount/src/fs.c        |  2 +-
df3f53
 libmount/src/tab_parse.c | 49 ++++++++++++++++++++++------------------
df3f53
 2 files changed, 28 insertions(+), 23 deletions(-)
df3f53
df3f53
diff --git a/libmount/src/fs.c b/libmount/src/fs.c
df3f53
index def32253c..aae4961c3 100644
df3f53
--- a/libmount/src/fs.c
df3f53
+++ b/libmount/src/fs.c
df3f53
@@ -34,7 +34,7 @@ struct libmnt_fs *mnt_new_fs(void)
df3f53
 
df3f53
 	fs->refcount = 1;
df3f53
 	INIT_LIST_HEAD(&fs->ents);
df3f53
-	/*DBG(FS, ul_debugobj(fs, "alloc"));*/
df3f53
+	DBG(FS, ul_debugobj(fs, "alloc"));
df3f53
 	return fs;
df3f53
 }
df3f53
 
df3f53
diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c
df3f53
index 10fc68279..719c1abca 100644
df3f53
--- a/libmount/src/tab_parse.c
df3f53
+++ b/libmount/src/tab_parse.c
df3f53
@@ -608,7 +608,6 @@ static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *fi
df3f53
 	int rc = -1;
df3f53
 	int flags = 0;
df3f53
 	pid_t tid = -1;
df3f53
-	struct libmnt_fs *fs = NULL;
df3f53
 	struct libmnt_parser pa = { .line = 0 };
df3f53
 
df3f53
 	assert(tb);
df3f53
@@ -628,19 +627,25 @@ static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *fi
df3f53
 	if (filename && strcmp(filename, _PATH_PROC_MOUNTS) == 0)
df3f53
 		flags = MNT_FS_KERNEL;
df3f53
 
df3f53
-	while (!feof(f)) {
df3f53
-		if (!fs) {
df3f53
-			fs = mnt_new_fs();
df3f53
-			if (!fs)
df3f53
-				goto err;
df3f53
+	do {
df3f53
+		struct libmnt_fs *fs;
df3f53
+
df3f53
+		if (feof(f)) {
df3f53
+			DBG(TAB, ul_debugobj(tb, "end-of-file"));
df3f53
+			break;
df3f53
 		}
df3f53
+		fs = mnt_new_fs();
df3f53
+		if (!fs)
df3f53
+			goto err;
df3f53
 
df3f53
+		/* parse */
df3f53
 		rc = mnt_table_parse_next(&pa, tb, fs);
df3f53
 
df3f53
-		if (!rc && tb->fltrcb && tb->fltrcb(fs, tb->fltrcb_data))
df3f53
-			rc = 1;	/* filtered out by callback... */
df3f53
+		if (rc != 0 && tb->fltrcb && tb->fltrcb(fs, tb->fltrcb_data))
df3f53
+			rc = 1;	/* error filtered out by callback... */
df3f53
 
df3f53
-		if (!rc) {
df3f53
+		/* add to the table */
df3f53
+		if (rc == 0) {
df3f53
 			rc = mnt_table_add_fs(tb, fs);
df3f53
 			fs->flags |= flags;
df3f53
 
df3f53
@@ -651,21 +656,21 @@ static int __table_parse_stream(struct libmnt_table *tb, FILE *f, const char *fi
df3f53
 			}
df3f53
 		}
df3f53
 
df3f53
-		if (rc) {
df3f53
-			if (rc > 0) {
df3f53
-				mnt_reset_fs(fs);
df3f53
-				assert(fs->refcount == 1);
df3f53
-				continue;	/* recoverable error, reuse fs*/
df3f53
-			}
df3f53
+		/* remove refernece (or deallocate on error) */
df3f53
+		mnt_unref_fs(fs);
df3f53
 
df3f53
-			mnt_unref_fs(fs);
df3f53
-			if (feof(f))
df3f53
-				break;
df3f53
-			goto err;		/* fatal error */
df3f53
+		/* recoverable error */
df3f53
+		if (rc > 0) {
df3f53
+			DBG(TAB, ul_debugobj(tb, "recoverable error (continue)"));
df3f53
+			continue;
df3f53
 		}
df3f53
-		mnt_unref_fs(fs);
df3f53
-		fs = NULL;
df3f53
-	}
df3f53
+
df3f53
+		/* fatal errors */
df3f53
+		if (rc < 0 && !feof(f)) {
df3f53
+			DBG(TAB, ul_debugobj(tb, "fatal error"));
df3f53
+			goto err;
df3f53
+		}
df3f53
+	} while (1);
df3f53
 
df3f53
 	DBG(TAB, ul_debugobj(tb, "%s: stop parsing (%d entries)",
df3f53
 				filename, mnt_table_get_nents(tb)));
df3f53
-- 
df3f53
2.29.2
df3f53