From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from localhost (fantadrom.bsd.lv [local]); by fantadrom.bsd.lv (OpenSMTPD) with ESMTPA id 6d636aaa; for ; Fri, 27 Feb 2015 19:03:23 -0500 (EST) Date: Fri, 27 Feb 2015 19:03:23 -0500 (EST) Message-Id: <14378159329918326414.enqueue@fantadrom.bsd.lv> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: kristaps@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: texi2mdoc: Prevent infinite macro expansion by incrementing a "depth" of X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 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, ¯o); 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, ¯o); 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, ¯o); 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, ¯o); 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, ¯o); 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