From 62d2d15b57af5150965913c4fd98edd0c2d97dfe Mon Sep 17 00:00:00 2001
From: KOLANICH <kolan_n@mail.ru>
Date: Thu, 23 Jul 2020 16:37:06 +0300
Subject: [PATCH] Fixed some memory leaks and UB

---
 lib/dpkg/tarfn.c        | 5 +++++
 lib/dpkg/trigdeferred.c | 3 +++
 lib/dpkg/varbuf.c       | 8 +++++---
 src/main.c              | 4 +++-
 src/unpack.c            | 8 ++++++--
 5 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/lib/dpkg/tarfn.c b/lib/dpkg/tarfn.c
index a0821f217..c759918e8 100644
--- a/lib/dpkg/tarfn.c
+++ b/lib/dpkg/tarfn.c
@@ -458,10 +458,13 @@ tar_extractor(struct tar_archive *tar)
 	h.linkname = NULL;
 	h.stat.uname = NULL;
 	h.stat.gname = NULL;
+	tar->err.str = NULL;
 
 	while ((status = tar->ops->read(tar, buffer, TARBLKSZ)) == TARBLKSZ) {
 		int name_len;
 
+		if(tar->err.str != NULL)
+			free(tar->err.str);
 		if (tar_header_decode((struct tar_header *)buffer, &h, &tar->err) < 0) {
 			if (h.name[0] == '\0') {
 				/* End Of Tape. */
@@ -485,6 +488,8 @@ tar_extractor(struct tar_archive *tar)
 		}
 
 		if (h.name[0] == '\0') {
+			if(tar->err.str != NULL)
+				free(tar->err.str);
 			status = dpkg_put_error(&tar->err,
 			                        _("invalid tar header with empty name field"));
 			errno = 0;
diff --git a/lib/dpkg/trigdeferred.c b/lib/dpkg/trigdeferred.c
index b9b028f73..71d050318 100644
--- a/lib/dpkg/trigdeferred.c
+++ b/lib/dpkg/trigdeferred.c
@@ -85,6 +85,7 @@ trigdef_update_start(enum trigdef_update_flags uf)
 					ohshite(_("unable to open/create "
 					          "triggers lock file '%.250s'"),
 					        fn.buf);
+				free(triggersdir);
 				return TDUS_ERROR_NO_DIR;
 			}
 		}
@@ -121,6 +122,7 @@ trigdef_update_start(enum trigdef_update_flags uf)
 		if (stab.st_size == 0 && !(uf & TDUF_WRITE_IF_EMPTY)) {
 			if (uf & TDUF_WRITE)
 				pop_cleanup(ehflag_normaltidy);
+			free(triggersdir);
 			return TDUS_ERROR_EMPTY_DEFERRED;
 		}
 	}
@@ -136,6 +138,7 @@ trigdef_update_start(enum trigdef_update_flags uf)
 
 		setcloexec(fileno(trig_new_deferred), newfn.buf);
 	}
+	free(triggersdir);
 
 	if (!old_deferred)
 		return TDUS_NO_DEFERRED;
diff --git a/lib/dpkg/varbuf.c b/lib/dpkg/varbuf.c
index ee757bcc7..cce61f612 100644
--- a/lib/dpkg/varbuf.c
+++ b/lib/dpkg/varbuf.c
@@ -95,9 +95,11 @@ varbuf_vprintf(struct varbuf *v, const char *fmt, va_list args)
 void
 varbuf_add_buf(struct varbuf *v, const void *s, size_t size)
 {
-  varbuf_grow(v, size);
-  memcpy(v->buf + v->used, s, size);
-  v->used += size;
+  if(size){
+    varbuf_grow(v, size);
+    memcpy(v->buf + v->used, s, size);
+    v->used += size;
+  }
 }
 
 void
diff --git a/src/main.c b/src/main.c
index 3482ed1e2..5d3eaf0ea 100644
--- a/src/main.c
+++ b/src/main.c
@@ -781,8 +781,10 @@ int main(int argc, const char *const *argv) {
     ohshite(_("unable to setenv for subprocesses"));
   if (setenv("DPKG_ROOT", instdir, 1) < 0)
     ohshite(_("unable to setenv for subprocesses"));
-  if (setenv("DPKG_FORCE", get_force_string(), 1) < 0)
+  char *force_string = get_force_string();
+  if (setenv("DPKG_FORCE", force_string, 1) < 0)
     ohshite(_("unable to setenv for subprocesses"));
+  free(force_string);
 
   if (!f_triggers)
     f_triggers = (cipaction->arg_int == act_triggers && *argv) ? -1 : 1;
diff --git a/src/unpack.c b/src/unpack.c
index 4a143666e..e73fa3e2e 100644
--- a/src/unpack.c
+++ b/src/unpack.c
@@ -1114,7 +1114,7 @@ void process_archive(const char *filename) {
     deb_verify(filename);
 
   /* Get the control information directory. */
-  cidir = get_control_dir(cidir);
+  cidir = get_control_dir(cidir);  // todo: Memory leak!!! cannot free because it is used after exitting this func.
   cidirrest = cidir + strlen(cidir);
   push_cleanup(cu_cidir, ~0, 2, (void *)cidir, (void *)cidirrest);
 
@@ -1443,9 +1443,13 @@ void process_archive(const char *filename) {
   tar.ops = &tf;
 
   rc = tar_extractor(&tar);
-  if (rc)
+  if (rc){
     dpkg_error_print(&tar.err,
                      _("corrupted filesystem tarfile in package archive"));
+  }
+  if(tar.err.str) // todo: during normal operation no error strings should be set!
+    free(tar.err.str);
+
   if (fd_skip(p1[0], -1, &err) < 0)
     ohshit(_("cannot zap possible trailing zeros from dpkg-deb: %s"), err.str);
   close(p1[0]);
