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