[tex-live] pdftex segfault with \pdflastmatch
Karl Berry
karl at freefriends.org
Sun Jun 12 20:19:59 CEST 2016
dc> This plain tex document demonstrates \pdflastmatch failing if
dc> used after a \pdfmatch that returned no matches.
Thanks for the report, of course, though it's sad.
ak> The crash disappears if I apply an attached utils.c.diff.
ak> But I don't know that the patch is right or not.
I was still seeing garbage for the position reported by \pdflastmatch
unless I added an explicit check (and variable) for whether the
preceding match succeeded. (Because otherwise the various arrays are
accessed without necessarily being set.)
Patch (minus the documentation, etc.) below; I installed it in pdftex
and TL. Akira (or anyone), let me know you see problems with it.
Thanks,
Karl
My test file (with the example from the pdftex manual):
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file public domain. Bug report of \pdflastmatch crash:
% http://tug.org/pipermail/tex-live/2016-June/038664.html
%
\catcode`\{=1 \catcode`\}=2 \catcode`^=7 \newlinechar=`^^J
%
\message{^^Jpdflastmatch0 before any match: \pdflastmatch0}
\message{^^J}%
%
\message{^^Jmatch a to b: \pdfmatch{a}{b}}
\message{^^J}%
\message{pdflastmatch0: \pdflastmatch0}
\message{^^J}%
%
\message{^^Jmatch example: \pdfmatch subcount 3 {ab(cd)*ef(gh)(ij)}{abefghij}}
\message{^^J}%
\message{pdflastmatch0 (0->abefghij): \pdflastmatch0 ^^J}
\message{pdflastmatch1 (-1->): \pdflastmatch1 ^^J}
\message{pdflastmatch2 (4->gh): \pdflastmatch2 ^^J}
\message{pdflastmatch3 (-1->): \pdflastmatch3}
\message{^^J}%
\end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
And the patch:
--- pdftexdir/utils.c (revision 757)
+++ pdftexdir/utils.c (working copy)
@@ -817,12 +817,16 @@
pdf_printf("/ModDate (%s)\n", start_time_str);
}
+
#define DEFAULT_SUB_MATCH_COUNT 10
static int sub_match_count = DEFAULT_SUB_MATCH_COUNT;
static regmatch_t *pmatch = NULL;
static char *match_string = NULL;
+static int last_match_succeeded = 0;
-void matchstrings(strnumber s, strnumber t, int subcount, boolean icase)
+/* Implements \pdfmatch */
+void
+matchstrings(strnumber s, strnumber t, int subcount, boolean icase)
{
regex_t preg;
int cflags = REG_EXTENDED;
@@ -857,20 +861,31 @@
pmatch = xtalloc(sub_match_count, regmatch_t);
}
ret = regexec(&preg, str, sub_match_count, pmatch, eflags);
+
xfree(match_string);
- match_string = xstrdup(str);
- strpool[poolptr++] = ((ret == 0) ? '1' : '0');
+ match_string = xstrdup(str); /* save searched-in string, used below */
+ last_match_succeeded = ret == 0; /* save whether match succeeded */
+ strpool[poolptr++] = ((ret == 0) ? '1' : '0'); /* in string pool too */
}
regfree(&preg);
}
-void getmatch(int i)
+/* Implements \pdflastmatch */
+
+void
+getmatch(int i)
{
- int size, len = 0; /* to avoid warning about uninitialized use of len */
+ int size;
+ int len = 0; /* avoid spurious uninitialized warning */
- boolean found = i < sub_match_count
- && match_string != NULL && pmatch[i].rm_so >= 0 && i >= 0;
+ boolean found
+ = i >= 0 /* should always be so due to pdftex.web */
+ && i < sub_match_count /* if >subcount, not found by definition */
+ && match_string != NULL /* first call, and just in case */
+ && last_match_succeeded /* if no match, not found */
+ && pmatch[i].rm_so >= 0 /* if no starting position, not found */
+ && pmatch[i].rm_eo >= pmatch[i].rm_so; /* just in case */
if (found) {
len = pmatch[i].rm_eo - pmatch[i].rm_so;
More information about the tex-live
mailing list