source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mandoc.bsd.lv
To: source@mandoc.bsd.lv
Subject: mandoc: After opening a file with gzdopen(3), we have to call gzclose(3)
Date: Fri, 23 Feb 2018 16:35:49 -0500 (EST)	[thread overview]
Message-ID: <84f4c559624fd54b@fantadrom.bsd.lv> (raw)

Log Message:
-----------
After opening a file with gzdopen(3), we have to call gzclose(3) or 
we leak memory internally used by zlib to keep compression state.
Bug reported by Wolfgang Mueller <vehk at vehk dot de> who also
provided an incomplete patch, part of which i'm using in this commit.

Modified Files:
--------------
    mandoc:
        read.c

Revision Data
-------------
Index: read.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/read.c,v
retrieving revision 1.193
retrieving revision 1.194
diff -Lread.c -Lread.c -u -p -r1.193 -r1.194
--- read.c
+++ read.c
@@ -556,6 +556,7 @@ read_whole_file(struct mparse *curp, con
 	gzFile		 gz;
 	size_t		 off;
 	ssize_t		 ssz;
+	int		 gzerrnum, retval;
 
 	if (fstat(fd, &st) == -1) {
 		mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
@@ -583,9 +584,22 @@ read_whole_file(struct mparse *curp, con
 	}
 
 	if (curp->gzip) {
+		/*
+		 * Duplicating the file descriptor is required
+		 * because we will have to call gzclose(3)
+		 * to free memory used internally by zlib,
+		 * but that will also close the file descriptor,
+		 * which this function must not do.
+		 */
+		if ((fd = dup(fd)) == -1) {
+			mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
+			    "dup: %s", strerror(errno));
+			return 0;
+		}
 		if ((gz = gzdopen(fd, "rb")) == NULL) {
 			mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
 			    "gzdopen: %s", strerror(errno));
+			close(fd);
 			return 0;
 		}
 	} else
@@ -598,6 +612,7 @@ read_whole_file(struct mparse *curp, con
 
 	*with_mmap = 0;
 	off = 0;
+	retval = 0;
 	fb->sz = 0;
 	fb->buf = NULL;
 	for (;;) {
@@ -614,19 +629,29 @@ read_whole_file(struct mparse *curp, con
 		    read(fd, fb->buf + (int)off, fb->sz - off);
 		if (ssz == 0) {
 			fb->sz = off;
-			return 1;
+			retval = 1;
+			break;
 		}
 		if (ssz == -1) {
-			mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
-			    "read: %s", strerror(errno));
+			if (curp->gzip)
+				(void)gzerror(gz, &gzerrnum);
+			mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, "read: %s",
+			    curp->gzip && gzerrnum != Z_ERRNO ?
+			    zError(gzerrnum) : strerror(errno));
 			break;
 		}
 		off += (size_t)ssz;
 	}
 
-	free(fb->buf);
-	fb->buf = NULL;
-	return 0;
+	if (curp->gzip && (gzerrnum = gzclose(gz)) != Z_OK)
+		mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, "gzclose: %s",
+		    gzerrnum == Z_ERRNO ? strerror(errno) :
+		    zError(gzerrnum));
+	if (retval == 0) {
+		free(fb->buf);
+		fb->buf = NULL;
+	}
+	return retval;
 }
 
 static void
--
 To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv

                 reply	other threads:[~2018-02-23 21:35 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=84f4c559624fd54b@fantadrom.bsd.lv \
    --to=schwarze@mandoc.bsd.lv \
    --cc=source@mandoc.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).