source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: Escape quotes when expanding macro arguments.
Date: Sat, 21 Feb 2015 09:47:28 -0500 (EST)	[thread overview]
Message-ID: <1359415269619155702.enqueue@fantadrom.bsd.lv> (raw)

Log Message:
-----------
Escape quotes when expanding macro arguments.
This fixes a bug naddy@ found in plan9/rc(1).

Modified Files:
--------------
    mdocml:
        roff.c

Revision Data
-------------
Index: roff.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/roff.c,v
retrieving revision 1.262
retrieving revision 1.263
diff -Lroff.c -Lroff.c -u -p -r1.262 -r1.263
--- roff.c
+++ roff.c
@@ -2653,14 +2653,16 @@ roff_so(ROFF_ARGS)
 static enum rofferr
 roff_userdef(ROFF_ARGS)
 {
-	const char	 *arg[9];
+	const char	 *arg[9], *ap;
 	char		 *cp, *n1, *n2;
 	int		  i;
+	size_t		  asz, rsz;
 
 	/*
 	 * Collect pointers to macro argument strings
 	 * and NUL-terminate them.
 	 */
+
 	cp = buf->buf + pos;
 	for (i = 0; i < 9; i++)
 		arg[i] = *cp == '\0' ? "" :
@@ -2669,31 +2671,89 @@ roff_userdef(ROFF_ARGS)
 	/*
 	 * Expand macro arguments.
 	 */
-	buf->sz = 0;
-	n1 = cp = mandoc_strdup(r->current_string);
-	while ((cp = strstr(cp, "\\$")) != NULL) {
-		i = cp[2] - '1';
-		if (0 > i || 8 < i) {
-			/* Not an argument invocation. */
-			cp += 2;
+
+	buf->sz = strlen(r->current_string) + 1;
+	n1 = cp = mandoc_malloc(buf->sz);
+	memcpy(n1, r->current_string, buf->sz);
+	while (*cp != '\0') {
+
+		/* Scan ahead for the next argument invocation. */
+
+		if (*cp++ != '\\')
+			continue;
+		if (*cp++ != '$')
+			continue;
+		i = *cp - '1';
+		if (0 > i || 8 < i)
 			continue;
+		cp -= 2;
+
+		/*
+		 * Determine the size of the expanded argument,
+		 * taking escaping of quotes into account.
+		 */
+
+		asz = 0;
+		for (ap = arg[i]; *ap != '\0'; ap++) {
+			asz++;
+			if (*ap == '"')
+				asz += 3;
+		}
+		if (asz != 3) {
+
+			/*
+			 * Determine the size of the rest of the
+			 * unexpanded macro, including the NUL.
+			 */
+
+			rsz = buf->sz - (cp - n1) - 3;
+
+			/*
+			 * When shrinking, move before
+			 * releasing the storage.
+			 */
+
+			if (asz < 3)
+				memmove(cp + asz, cp + 3, rsz);
+
+			/*
+			 * Resize the storage for the macro
+			 * and readjust the parse pointer.
+			 */
+
+			buf->sz += asz - 3;
+			n2 = mandoc_realloc(n1, buf->sz);
+			cp = n2 + (cp - n1);
+			n1 = n2;
+
+			/*
+			 * When growing, make room
+			 * for the expanded argument.
+			 */
+
+			if (asz > 3)
+				memmove(cp + asz, cp + 3, rsz);
+		}
+
+		/* Copy the expanded argument, escaping quotes. */
+
+		n2 = cp;
+		for (ap = arg[i]; *ap != '\0'; ap++) {
+			if (*ap == '"') {
+				memcpy(n2, "\\(dq", 4);
+				n2 += 4;
+			} else
+				*n2++ = *ap;
 		}
-		*cp = '\0';
-		buf->sz = mandoc_asprintf(&n2, "%s%s%s",
-		    n1, arg[i], cp + 3) + 1;
-		cp = n2 + (cp - n1);
-		free(n1);
-		n1 = n2;
 	}
 
 	/*
 	 * Replace the macro invocation
 	 * by the expanded macro.
 	 */
+
 	free(buf->buf);
 	buf->buf = n1;
-	if (buf->sz == 0)
-		buf->sz = strlen(buf->buf) + 1;
 	*offs = 0;
 
 	return(buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ?
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

                 reply	other threads:[~2015-02-21 14:47 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=1359415269619155702.enqueue@fantadrom.bsd.lv \
    --to=schwarze@mdocml.bsd.lv \
    --cc=source@mdocml.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).