9front - general discussion about 9front
 help / color / mirror / Atom feed
From: boehm.igor@gmail.com
To: 9front@9front.org
Cc: boehm.igor@gmail.com
Subject: [9front] cmd/acme: fix resource leak in ecmd.c (patch)
Date: Tue, 02 Feb 2021 00:09:39 +0100	[thread overview]
Message-ID: <863CA88C234EA794D5D1804F1D51D318@gmail.com> (raw)

There is a resource leak in acme functions:
• /sys/src/cmd/acme/ecmd.c:/^B_cmd
• /sys/src/cmd/acme/ecmd.c:/^D_cmd

I will describe the case for function B_cmd, the issue is the same for
D_cmd.

In short, there can be a case where the heap allocated storage
returned by the /sys/src/cmd/acme/ecmd.c:/^filelist(...) function is
not freed. You can use the following as a starting point:

• /sys/src/cmd/acme/ecmd.c:192

int
B_cmd(Text *t, Cmd *cp)
{
	Rune *list, *r, *s;
	int nr;

	list = filelist(t, cp->text->r, cp->text->n);
	^^^^^^^^^^^^^^^
	if(list == nil)
		editerror(Enoname);
	r = list;
	...
	...
	}
	clearcollection();
	^^^^^^^^^^^^^^^^^
	return TRUE;
}

Notice the two lines that are highlighted, namely the call to
filelist(...) and clearcollection(...).

Now if we look at the impl of filelist(...) we have:

/* string is known to be NUL-terminated */
Rune*
filelist(Text *t, Rune *r, int nr)
{
	if(nr == 0)
		return nil;
	r = skipbl(r, nr, &nr);
	if(r[0] != '<')
		return runestrdup(r);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
WHEN WE TAKE THE ABOVE PATH WE LEAK
WHAT runestrdup(r) RETURNS
	/* use < command to collect text */
	clearcollection();
	runpipe(t, '<', r+1, nr-1, Collecting);
	return collection;
^^^^^^^^^^^^^^^^^^^^^^
TAKING THIS PATH IS FINE AS clearcollection(...)
WILL FREE ANY HEAP ALLOCATED MEMORY
}

So for the case where we *do not* return the 'collection' pointer we
leak memory that is allocated by 'runestrdup(...)'.

There are probably more elegant solutions for this.  The below simply
checks if the pointer returned by filelist(...) is not equal to
'collection'.  That is used as a sentinel to detect the case where
runestrdup(...) has been called.  That is the case where the memory
returned by filelist(...) is *not* freed by clearcollection(...) and
requires an extra free.

Somehow the explanation is much more complicated than I initially
intended.  Hope you can still follow the reasoning and I haven't
screwed up somewhere.

Here is the patch:

diff -r 0b8c8ef6a3d4 sys/src/cmd/acme/ecmd.c
--- a/sys/src/cmd/acme/ecmd.c	Tue Jan 19 15:18:57 2021 -0800
+++ b/sys/src/cmd/acme/ecmd.c	Mon Feb 01 22:24:56 2021 +0100
@@ -204,6 +204,8 @@
 		if(nr > 0)
 			r = skipbl(s+1, nr-1, &nr);
 	}
+	if(list != collection)
+		free(list);
 	clearcollection();
 	return TRUE;
 }
@@ -278,6 +280,8 @@
 		if(nr > 0)
 			r = skipbl(s+1, nr-1, &nr);
 	}while(nr > 0);
+	if(list != collection)
+		free(list);
 	clearcollection();
 	free(dir.r);
 	return TRUE;


             reply	other threads:[~2021-02-02  3:47 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-01 23:09 boehm.igor [this message]
2021-02-02  1:16 ` Noam Preil
2021-02-02  1:36   ` Noam Preil
2021-02-02  1:40   ` Noam Preil
2021-02-05  7:55 ` [9front] " boehm.igor

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=863CA88C234EA794D5D1804F1D51D318@gmail.com \
    --to=boehm.igor@gmail.com \
    --cc=9front@9front.org \
    /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).