sys-apps/sed: add upstream fixes for some newline handling which causes segfaults

This commit is contained in:
Mike Frysinger
2017-01-18 03:43:12 -06:00
parent 5a52b646b4
commit 73c81e7072
4 changed files with 440 additions and 2 deletions

View File

@@ -0,0 +1,175 @@
fix from upstream gnulib (fudged to apply to sed-4.3)
From 823b5cb589366f7c8742503af980803afad0978f Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 8 Jan 2017 12:44:29 -0800
Subject: [PATCH] dfa: fix reallocation bug when matching newlines
Problem reported for sed by S. Gilles (Bug#25390).
* lib/dfa.c (realloc_trans_if_necessary): Move earlier.
(dfastate): Reallocate before moving any newline transition ...
(build_state): ... instead of reallocating here, where it is too late.
---
ChangeLog | 8 +++++
lib/dfa.c | 114 ++++++++++++++++++++++++++++++--------------------------------
2 files changed, 63 insertions(+), 59 deletions(-)
diff --git a/lib/dfa.c b/lib/dfa.c
index 8276db160a4b..141888a978fa 100644
--- a/lib/dfa.c
+++ b/lib/dfa.c
@@ -2574,6 +2574,40 @@ dfaanalyze (struct dfa *d, bool searchflag)
free (merged.elems);
}
+/* Make sure D's state arrays are large enough to hold NEW_STATE. */
+static void
+realloc_trans_if_necessary (struct dfa *d, state_num new_state)
+{
+ state_num oldalloc = d->tralloc;
+ if (oldalloc <= new_state)
+ {
+ state_num **realtrans = d->trans ? d->trans - 2 : NULL;
+ ptrdiff_t newalloc1 = realtrans ? d->tralloc + 2 : 0;
+ realtrans = xpalloc (realtrans, &newalloc1, new_state - oldalloc + 1,
+ -1, sizeof *realtrans);
+ realtrans[0] = realtrans[1] = NULL;
+ d->trans = realtrans + 2;
+ ptrdiff_t newalloc = d->tralloc = newalloc1 - 2;
+ d->fails = xnrealloc (d->fails, newalloc, sizeof *d->fails);
+ d->success = xnrealloc (d->success, newalloc, sizeof *d->success);
+ d->newlines = xnrealloc (d->newlines, newalloc, sizeof *d->newlines);
+ if (d->localeinfo.multibyte)
+ {
+ realtrans = d->mb_trans ? d->mb_trans - 2 : NULL;
+ realtrans = xnrealloc (realtrans, newalloc1, sizeof *realtrans);
+ if (oldalloc == 0)
+ realtrans[0] = realtrans[1] = NULL;
+ d->mb_trans = realtrans + 2;
+ }
+ for (; oldalloc < newalloc; oldalloc++)
+ {
+ d->trans[oldalloc] = NULL;
+ d->fails[oldalloc] = NULL;
+ if (d->localeinfo.multibyte)
+ d->mb_trans[oldalloc] = NULL;
+ }
+ }
+}
/* Return the transition out of state s of d for the input character uc,
updating the slots in trans accordingly.
@@ -2810,20 +2844,25 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
}
/* Set the transitions for each character in the label. */
+ state_num maxstate = -1;
for (i = 0; i < NOTCHAR; i++)
if (tstbit (i, label))
- switch (d->syntax.sbit[i])
- {
- case CTX_NEWLINE:
- trans[i] = state_newline;
- break;
- case CTX_LETTER:
- trans[i] = state_letter;
- break;
- default:
- trans[i] = state;
- break;
- }
+ {
+ switch (d->syntax.sbit[i])
+ {
+ case CTX_NEWLINE:
+ trans[i] = state_newline;
+ break;
+ case CTX_LETTER:
+ trans[i] = state_letter;
+ break;
+ default:
+ trans[i] = state;
+ break;
+ }
+ if (maxstate < trans[i])
+ maxstate = trans[i];
+ }
#ifdef DEBUG
fprintf (stderr, "trans table %td", s);
@@ -2840,6 +2879,9 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
free (follows.elems);
free (tmp.elems);
+ /* Reallocate now, to reallocate any newline transition properly. */
+ realloc_trans_if_necessary (d, maxstate);
+
/* Keep the newline transition in a special place so we can use it as
a sentinel. */
if (tstbit (d->syntax.eolbyte, label))
@@ -2851,42 +2893,6 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
return trans[uc];
}
-/* Make sure D's state arrays are large enough to hold NEW_STATE. */
-static void
-realloc_trans_if_necessary (struct dfa *d, state_num new_state)
-{
- state_num oldalloc = d->tralloc;
- if (oldalloc <= new_state)
- {
- state_num **realtrans = d->trans ? d->trans - 2 : NULL;
- ptrdiff_t newalloc, newalloc1;
- newalloc1 = realtrans ? d->tralloc + 2 : 0;
- realtrans = xpalloc (realtrans, &newalloc1, new_state - oldalloc + 1,
- -1, sizeof *realtrans);
- realtrans[0] = realtrans[1] = NULL;
- d->trans = realtrans + 2;
- d->tralloc = newalloc = newalloc1 - 2;
- d->fails = xnrealloc (d->fails, newalloc, sizeof *d->fails);
- d->success = xnrealloc (d->success, newalloc, sizeof *d->success);
- d->newlines = xnrealloc (d->newlines, newalloc, sizeof *d->newlines);
- if (d->localeinfo.multibyte)
- {
- realtrans = d->mb_trans ? d->mb_trans - 2 : NULL;
- realtrans = xnrealloc (realtrans, newalloc1, sizeof *realtrans);
- if (oldalloc == 0)
- realtrans[0] = realtrans[1] = NULL;
- d->mb_trans = realtrans + 2;
- }
- for (; oldalloc < newalloc; oldalloc++)
- {
- d->trans[oldalloc] = NULL;
- d->fails[oldalloc] = NULL;
- if (d->localeinfo.multibyte)
- d->mb_trans[oldalloc] = NULL;
- }
- }
-}
-
/* Calculate the transition table for a new state derived from state s
for a compiled dfa d after input character uc, and return the new
state number. */
@@ -2932,18 +2939,7 @@ build_state (state_num s, struct dfa *d, unsigned char uc)
if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_NONE, s, *d))
d->success[s] |= CTX_NONE;
- s = dfastate (s, d, uc, trans);
-
- /* Now go through the new transition table, and make sure that the trans
- and fail arrays are allocated large enough to hold a pointer for the
- largest state mentioned in the table. */
- state_num maxstate = -1;
- for (int i = 0; i < NOTCHAR; i++)
- if (maxstate < trans[i])
- maxstate = trans[i];
- realloc_trans_if_necessary (d, maxstate);
-
- return s;
+ return dfastate (s, d, uc, trans);
}
/* Multibyte character handling sub-routines for dfaexec. */
--
2.11.0

View File

@@ -0,0 +1,112 @@
fix from upstream gnulib (fudged to apply to sed-4.3)
From aff55692da81f702ccbc461ad4f896b23c398638 Mon Sep 17 00:00:00 2001
From: Norihiro Tanaka <noritnk@kcn.ne.jp>
Date: Mon, 9 Jan 2017 07:46:13 +0900
Subject: [PATCH] dfa: simplify transition table allocation
* src/dfa.c (realloc_trans_if_necessary): Remove second argument.
Its value is derived from other variable. Update callers.
(dfastate): Remove calculation of max number of state.
---
lib/dfa.c | 44 ++++++++++++++++++++------------------------
1 file changed, 20 insertions(+), 24 deletions(-)
diff --git a/lib/dfa.c b/lib/dfa.c
index 141888a978fa..bda4602b1094 100644
--- a/lib/dfa.c
+++ b/lib/dfa.c
@@ -2576,14 +2576,14 @@ dfaanalyze (struct dfa *d, bool searchflag)
/* Make sure D's state arrays are large enough to hold NEW_STATE. */
static void
-realloc_trans_if_necessary (struct dfa *d, state_num new_state)
+realloc_trans_if_necessary (struct dfa *d)
{
state_num oldalloc = d->tralloc;
- if (oldalloc <= new_state)
+ if (oldalloc < d->sindex)
{
state_num **realtrans = d->trans ? d->trans - 2 : NULL;
ptrdiff_t newalloc1 = realtrans ? d->tralloc + 2 : 0;
- realtrans = xpalloc (realtrans, &newalloc1, new_state - oldalloc + 1,
+ realtrans = xpalloc (realtrans, &newalloc1, d->sindex - oldalloc,
-1, sizeof *realtrans);
realtrans[0] = realtrans[1] = NULL;
d->trans = realtrans + 2;
@@ -2825,6 +2825,9 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
state_letter = state_index (d, &follows, CTX_LETTER);
else
state_letter = state;
+
+ /* Reallocate now, to reallocate any newline transition properly. */
+ realloc_trans_if_necessary (d);
}
/* If we are a searching matcher, the default transition is to a state
@@ -2847,22 +2850,18 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
state_num maxstate = -1;
for (i = 0; i < NOTCHAR; i++)
if (tstbit (i, label))
- {
- switch (d->syntax.sbit[i])
- {
- case CTX_NEWLINE:
- trans[i] = state_newline;
- break;
- case CTX_LETTER:
- trans[i] = state_letter;
- break;
- default:
- trans[i] = state;
- break;
- }
- if (maxstate < trans[i])
- maxstate = trans[i];
- }
+ switch (d->syntax.sbit[i])
+ {
+ case CTX_NEWLINE:
+ trans[i] = state_newline;
+ break;
+ case CTX_LETTER:
+ trans[i] = state_letter;
+ break;
+ default:
+ trans[i] = state;
+ break;
+ }
#ifdef DEBUG
fprintf (stderr, "trans table %td", s);
@@ -2879,9 +2878,6 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
free (follows.elems);
free (tmp.elems);
- /* Reallocate now, to reallocate any newline transition properly. */
- realloc_trans_if_necessary (d, maxstate);
-
/* Keep the newline transition in a special place so we can use it as
a sentinel. */
if (tstbit (d->syntax.eolbyte, label))
@@ -3042,7 +3038,7 @@ transit_state (struct dfa *d, state_num s, unsigned char const **pp,
separate_contexts = state_separate_contexts (&d->mb_follows);
s2 = state_index (d, &d->mb_follows, separate_contexts ^ CTX_ANY);
- realloc_trans_if_necessary (d, s2);
+ realloc_trans_if_necessary (d);
d->mb_trans[s][d->states[s1].mb_trindex] = s2;
@@ -3137,7 +3133,7 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
}
if (!d->tralloc)
- realloc_trans_if_necessary (d, 0);
+ realloc_trans_if_necessary (d);
s = s1 = 0;
p = mbp = (unsigned char const *) begin;
--
2.11.0

View File

@@ -0,0 +1,146 @@
fix from upstream gnulib (fudged to apply to sed-4.3)
From 7c345c68cdf62737ccc4a9d0ba2cd921fae850fa Mon Sep 17 00:00:00 2001
From: Norihiro Tanaka <noritnk@kcn.ne.jp>
Date: Mon, 9 Jan 2017 08:21:21 +0900
Subject: [PATCH] dfa: melt down dfastate into build_state
* src/dfa.c (dfastate): Remove it.
(build_state): Insert content of dfastate() to bottom.
---
lib/dfa.c | 97 +++++++++++++++++++++++++++++----------------------------------
1 file changed, 45 insertions(+), 52 deletions(-)
diff --git a/lib/dfa.c b/lib/dfa.c
index bda4602b1094..6896ed320a7b 100644
--- a/lib/dfa.c
+++ b/lib/dfa.c
@@ -2609,8 +2609,10 @@ realloc_trans_if_necessary (struct dfa *d)
}
}
-/* Return the transition out of state s of d for the input character uc,
- updating the slots in trans accordingly.
+/*
+ Calculate the transition table for a new state derived from state s
+ for a compiled dfa d after input character uc, and return the new
+ state number.
Do not worry about all possible input characters; calculate just the group
of positions that match uc. Label it with the set of characters that
@@ -2639,8 +2641,9 @@ realloc_trans_if_necessary (struct dfa *d)
If after comparing with every group there are characters remaining in C,
create a new group labeled with the characters of C and insert this
position in that group. */
+
static state_num
-dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
+build_state (state_num s, struct dfa *d, unsigned char uc)
{
leaf_set group; /* Positions that match the input char. */
charclass label; /* The group's label. */
@@ -2652,6 +2655,45 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
fprintf (stderr, "build state %td\n", s);
#endif
+ /* A pointer to the new transition table, and the table itself. */
+ state_num **ptrans = (ACCEPTING (s, *d) ? d->fails : d->trans) + s;
+ state_num *trans = *ptrans;
+
+ if (!trans)
+ {
+ /* MAX_TRCOUNT is an arbitrary upper limit on the number of
+ transition tables that can exist at once, other than for
+ initial states. Often-used transition tables are quickly
+ rebuilt, whereas rarely-used ones are cleared away. */
+ if (MAX_TRCOUNT <= d->trcount)
+ {
+ for (state_num i = d->min_trcount; i < d->tralloc; i++)
+ {
+ free (d->trans[i]);
+ free (d->fails[i]);
+ d->trans[i] = d->fails[i] = NULL;
+ }
+ d->trcount = 0;
+ }
+
+ d->trcount++;
+ *ptrans = trans = xmalloc (NOTCHAR * sizeof *trans);
+
+ /* Fill transition table with a default value which means that the
+ transited state has not been calculated yet. */
+ for (int i = 0; i < NOTCHAR; i++)
+ trans[i] = -2;
+ }
+
+ /* Set up the success bits for this state. */
+ d->success[s] = 0;
+ if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_NEWLINE, s, *d))
+ d->success[s] |= CTX_NEWLINE;
+ if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_LETTER, s, *d))
+ d->success[s] |= CTX_LETTER;
+ if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_NONE, s, *d))
+ d->success[s] |= CTX_NONE;
+
group.elems = xnmalloc (d->nleaves, sizeof *group.elems);
group.nelem = 0;
@@ -2889,55 +2931,6 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[])
return trans[uc];
}
-/* Calculate the transition table for a new state derived from state s
- for a compiled dfa d after input character uc, and return the new
- state number. */
-
-static state_num
-build_state (state_num s, struct dfa *d, unsigned char uc)
-{
- /* A pointer to the new transition table, and the table itself. */
- state_num **ptrans = (ACCEPTING (s, *d) ? d->fails : d->trans) + s;
- state_num *trans = *ptrans;
-
- if (!trans)
- {
- /* MAX_TRCOUNT is an arbitrary upper limit on the number of
- transition tables that can exist at once, other than for
- initial states. Often-used transition tables are quickly
- rebuilt, whereas rarely-used ones are cleared away. */
- if (MAX_TRCOUNT <= d->trcount)
- {
- for (state_num i = d->min_trcount; i < d->tralloc; i++)
- {
- free (d->trans[i]);
- free (d->fails[i]);
- d->trans[i] = d->fails[i] = NULL;
- }
- d->trcount = 0;
- }
-
- d->trcount++;
- *ptrans = trans = xmalloc (NOTCHAR * sizeof *trans);
-
- /* Fill transition table with a default value which means that the
- transited state has not been calculated yet. */
- for (int i = 0; i < NOTCHAR; i++)
- trans[i] = -2;
- }
-
- /* Set up the success bits for this state. */
- d->success[s] = 0;
- if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_NEWLINE, s, *d))
- d->success[s] |= CTX_NEWLINE;
- if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_LETTER, s, *d))
- d->success[s] |= CTX_LETTER;
- if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_NONE, s, *d))
- d->success[s] |= CTX_NONE;
-
- return dfastate (s, d, uc, trans);
-}
-
/* Multibyte character handling sub-routines for dfaexec. */
/* Consume a single byte and transit state from 's' to '*next_state'.
--
2.11.0

View File

@@ -1,8 +1,7 @@
# Copyright 1999-2017 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
EAPI=5
EAPI="5"
inherit eutils flag-o-matic toolchain-funcs
@@ -21,6 +20,10 @@ RDEPEND="acl? ( virtual/acl )
DEPEND="${RDEPEND}
nls? ( sys-devel/gettext )"
PATCHES=(
"${FILESDIR}"/${P}-dfa-segv-{1,2,3}.patch
)
src_bootstrap_sed() {
# make sure system-sed works #40786
export NO_SYS_SED=""
@@ -34,6 +37,8 @@ src_bootstrap_sed() {
}
src_prepare() {
epatch "${PATCHES[@]}"
# don't use sed before bootstrap if we have to recover a broken host sed
src_bootstrap_sed
}