source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* texi2mdoc: Prevent infinite macro expansion by incrementing a "depth" of
@ 2015-02-28  0:03 kristaps
  0 siblings, 0 replies; only message in thread
From: kristaps @ 2015-02-28  0:03 UTC (permalink / raw)
  To: source

Log Message:
-----------
Prevent infinite macro expansion by incrementing a "depth" of recursive
expansion IFF we're currently in a macro expansion already, where the start
of the macro expansion begins at the macro name and NOT after the name has
been parsed.

Modified Files:
--------------
    texi2mdoc:
        extern.h
        main.c
        util.c
    texi2mdoc/afl:
        mkdict.sh

Revision Data
-------------
Index: util.c
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/util.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -Lutil.c -Lutil.c -u -p -r1.16 -r1.17
--- util.c
+++ util.c
@@ -330,8 +330,11 @@ advance(struct texi *p, size_t *pos)
 			f->col = 0;
 		} else
 			f->col++;
-	} else
+	} else {
 		--f->insplice;
+		if (0 == f->insplice)
+			f->depth = 0;
+	}
 
 	(*pos)++;
 }
@@ -439,7 +442,7 @@ advanceto(struct texi *p, size_t *pos, s
 }
 
 static void
-texiexecmacro(struct texi *p, struct teximacro *m, size_t *pos)
+texiexecmacro(struct texi *p, struct teximacro *m, size_t sv, size_t *pos)
 {
 	size_t		  valsz, realsz, aasz, asz, 
 			   ssz, i, j, k, start, end;
@@ -447,17 +450,31 @@ texiexecmacro(struct texi *p, struct tex
 	char		**args;
 	const char	 *cp;
 
+	/* Disregard empty macros. */
+	if (0 == (valsz = realsz = strlen(m->value)))
+		return;
+
+	/*
+	 * This is important: it protect us from macros that invoke more
+	 * macros, possibly going on infinitely.
+	 * We use "sv" instead of the current position because we might
+	 * be invoked at the end of the macro (i.e., insplice == 0).
+	 * The "sv" value was initialised at the start of the macro.
+	 */
+	if (sv > 0)
+		if (++p->files[p->filepos].depth > 64)
+			texierr(p, "maximium recursive depth");
+
 	args = argparse(p, pos, &asz, m->argsz);
 	if (asz != m->argsz)
 		texiwarn(p, "invalid macro argument length");
 	aasz = asz < m->argsz ? asz : m->argsz;
 
 	if (0 == aasz) {
-		texisplice(p, m->value, strlen(m->value), pos);
+		texisplice(p, m->value, valsz, pos);
 		return;
 	}
 
-	valsz = realsz = strlen(m->value);
 	val = strdup(m->value);
 
 	for (i = j = 0; i < realsz; i++) {
@@ -653,7 +670,7 @@ texicmd(struct texi *p, size_t pos, size
 int
 parsearg(struct texi *p, size_t *pos, size_t num)
 {
-	size_t		  end;
+	size_t		  end, sv;
 	enum texicmd	  cmd;
 	struct teximacro *macro;
 
@@ -684,10 +701,11 @@ parsearg(struct texi *p, size_t *pos, si
 			continue;
 		}
 
+		sv = p->files[p->filepos - 1].insplice;
 		cmd = texicmd(p, *pos, &end, &macro);
 		advanceto(p, pos, end);
 		if (NULL != macro)
-			texiexecmacro(p, macro, pos);
+			texiexecmacro(p, macro, sv, pos);
 		if (TEXICMD__MAX == cmd) 
 			continue;
 		if (NULL != texitoks[cmd].fp)
@@ -703,7 +721,7 @@ parsearg(struct texi *p, size_t *pos, si
 void
 parsebracket(struct texi *p, size_t *pos)
 {
-	size_t		  end;
+	size_t		  end, sv;
 	enum texicmd	  cmd;
 	struct teximacro *macro;
 
@@ -731,10 +749,11 @@ parsebracket(struct texi *p, size_t *pos
 			continue;
 		}
 
+		sv = p->files[p->filepos - 1].insplice;
 		cmd = texicmd(p, *pos, &end, &macro);
 		advanceto(p, pos, end);
 		if (NULL != macro)
-			texiexecmacro(p, macro, pos);
+			texiexecmacro(p, macro, sv, pos);
 		if (TEXICMD__MAX == cmd) 
 			continue;
 		if (NULL != texitoks[cmd].fp)
@@ -750,7 +769,7 @@ parsebracket(struct texi *p, size_t *pos
 void
 parseeoln(struct texi *p, size_t *pos)
 {
-	size_t		  end;
+	size_t		  end, sv;
 	enum texicmd	  cmd;
 	struct teximacro *macro;
 
@@ -779,10 +798,11 @@ parseeoln(struct texi *p, size_t *pos)
 			continue;
 		}
 
+		sv = p->files[p->filepos - 1].insplice;
 		cmd = texicmd(p, *pos, &end, &macro);
 		advanceto(p, pos, end);
 		if (NULL != macro)
-			texiexecmacro(p, macro, pos);
+			texiexecmacro(p, macro, sv, pos);
 		if (TEXICMD__MAX == cmd) 
 			continue;
 		if (NULL != texitoks[cmd].fp)
@@ -800,7 +820,7 @@ parseeoln(struct texi *p, size_t *pos)
 static void
 parsesingle(struct texi *p, size_t *pos)
 {
-	size_t		  end;
+	size_t		  end, sv;
 	enum texicmd	  cmd;
 	struct teximacro *macro;
 
@@ -825,10 +845,11 @@ parsesingle(struct texi *p, size_t *pos)
 		return;
 	}
 
+	sv = p->files[p->filepos - 1].insplice;
 	cmd = texicmd(p, *pos, &end, &macro);
 	advanceto(p, pos, end);
 	if (NULL != macro)
-		texiexecmacro(p, macro, pos);
+		texiexecmacro(p, macro, sv, pos);
 	if (TEXICMD__MAX == cmd) 
 		return;
 	if (NULL != texitoks[cmd].fp)
@@ -905,7 +926,7 @@ texisplice(struct texi *p, const char *b
 void
 parseto(struct texi *p, size_t *pos, const char *endtoken)
 {
-	size_t		  end;
+	size_t		  end, sv;
 	enum texicmd	  cmd;
 	size_t		  endtoksz;
 	struct teximacro *macro;
@@ -932,6 +953,7 @@ parseto(struct texi *p, size_t *pos, con
 			continue;
 		}
 
+		sv = p->files[p->filepos - 1].insplice;
 		cmd = texicmd(p, *pos, &end, &macro);
 		advanceto(p, pos, end);
 		if (TEXICMD_END == cmd) {
@@ -952,7 +974,7 @@ parseto(struct texi *p, size_t *pos, con
 			continue;
 		} 
 		if (NULL != macro)
-			texiexecmacro(p, macro, pos);
+			texiexecmacro(p, macro, sv, pos);
 		if (TEXICMD__MAX == cmd) 
 			continue;
 		if (NULL != texitoks[cmd].fp) 
@@ -1209,6 +1231,9 @@ argparse(struct texi *p, size_t *pos, si
 	args = NULL;
 	*argsz = 0;
 
+	if (*pos == BUFSZ(p))
+		return(args);
+
 	if ('{' != BUF(p)[*pos] && hint) {
 		/*
 		 * Special case: if we encounter an unbracketed argument
@@ -1234,6 +1259,8 @@ argparse(struct texi *p, size_t *pos, si
 		return(args);
 	} else if ('{' != BUF(p)[*pos])
 		return(args);
+
+	assert('{' == BUF(p)[*pos]);
 
 	/* Parse til the closing '}', putting into the array. */
 	advance(p, pos);
Index: main.c
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/main.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -Lmain.c -Lmain.c -u -p -r1.51 -r1.52
--- main.c
+++ main.c
@@ -614,8 +614,8 @@ doignblock(struct texi *p, enum texicmd 
 	 * Thus, we keep track of scopes for matching "end" blocks.
 	 */
 	while (stack > 0 && *pos < BUFSZ(p)) {
-		if (stack > 10)
-			abort();
+		if (stack > 64)
+			texierr(p, "run-away nested stack?");
 		endt = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, end, esz);
 		startt = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, start, ssz);
 		if (NULL == endt) {
Index: extern.h
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/extern.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -Lextern.h -Lextern.h -u -p -r1.17 -r1.18
--- extern.h
+++ extern.h
@@ -317,6 +317,7 @@ struct	texifile {
 	size_t		 mapsz; /* size of map */
 	size_t		 mapmaxsz; /* full size of map */
 	size_t		 insplice; /* how many bytes left in splice */
+	size_t		 depth; /* pasted macro recursive depth */
 };
 
 struct	texi;
@@ -426,8 +427,7 @@ void	parseto(struct texi *, size_t *, co
 void	texiabort(struct texi *, const char *)
 		__attribute__((noreturn));
 enum texicmd
-	texicmd(struct texi *, size_t, 
-		size_t *, struct teximacro **);
+	texicmd(struct texi *, size_t, size_t *, struct teximacro **);
 void	texierr(struct texi *, const char *, ...)
 		__attribute__((format(printf, 2, 3)))
 		__attribute__((noreturn));
Index: mkdict.sh
===================================================================
RCS file: /home/cvs/mdocml/texi2mdoc/afl/mkdict.sh,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lafl/mkdict.sh -Lafl/mkdict.sh -u -p -r1.2 -r1.3
--- afl/mkdict.sh
+++ afl/mkdict.sh
@@ -1,6 +1,7 @@
 #! /bin/sh
 
-rm -f dict/*
+rm -rf dict
+mkdir dict
 
 sed -n '/TEXICMD__BEGIN/,/TEXICMD__END/p' ../main.c | \
 	tail -n +2 | \
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-02-28  0:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-28  0:03 texi2mdoc: Prevent infinite macro expansion by incrementing a "depth" of kristaps

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).