summaryrefslogtreecommitdiffstats
path: root/patches/glibc-2.18/0006-Fall-back-to-non-cached-sequence-traversal-and-compa.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/glibc-2.18/0006-Fall-back-to-non-cached-sequence-traversal-and-compa.patch')
-rw-r--r--patches/glibc-2.18/0006-Fall-back-to-non-cached-sequence-traversal-and-compa.patch384
1 files changed, 0 insertions, 384 deletions
diff --git a/patches/glibc-2.18/0006-Fall-back-to-non-cached-sequence-traversal-and-compa.patch b/patches/glibc-2.18/0006-Fall-back-to-non-cached-sequence-traversal-and-compa.patch
deleted file mode 100644
index b7f1c22..0000000
--- a/patches/glibc-2.18/0006-Fall-back-to-non-cached-sequence-traversal-and-compa.patch
+++ /dev/null
@@ -1,384 +0,0 @@
-From: Siddhesh Poyarekar <siddhesh@redhat.com>
-Date: Mon, 23 Sep 2013 11:20:02 +0530
-Subject: [PATCH] Fall back to non-cached sequence traversal and comparison on
- malloc fail
-
-strcoll currently falls back to alloca if malloc fails, resulting in a
-possible stack overflow. This patch implements sequence traversal and
-comparison without caching indices and rules.
-
-Fixes CVE-2012-4424.
----
- string/strcoll_l.c | 265 ++++++++++++++++++++++++++++++++++++++++++++++-------
- 1 file changed, 234 insertions(+), 31 deletions(-)
-
-diff --git a/string/strcoll_l.c b/string/strcoll_l.c
-index 50ed84d..eb042ff 100644
---- a/string/strcoll_l.c
-+++ b/string/strcoll_l.c
-@@ -45,7 +45,7 @@
- typedef struct
- {
- int len; /* Length of the current sequence. */
-- int val; /* Position of the sequence relative to the
-+ size_t val; /* Position of the sequence relative to the
- previous non-ignored sequence. */
- size_t idxnow; /* Current index in sequences. */
- size_t idxmax; /* Maximum index in sequences. */
-@@ -55,6 +55,12 @@ typedef struct
- const USTRING_TYPE *us; /* The string. */
- int32_t *idxarr; /* Array to cache weight indices. */
- unsigned char *rulearr; /* Array to cache rules. */
-+ unsigned char rule; /* Saved rule for the first sequence. */
-+ int32_t idx; /* Index to weight of the current sequence. */
-+ int32_t save_idx; /* Save looked up index of a forward
-+ sequence after the last backward
-+ sequence. */
-+ const USTRING_TYPE *back_us; /* Beginning of the backward sequence. */
- } coll_seq;
-
- /* Get next sequence. The weight indices are cached, so we don't need to
-@@ -64,7 +70,7 @@ get_next_seq_cached (coll_seq *seq, int nrules, int pass,
- const unsigned char *rulesets,
- const USTRING_TYPE *weights)
- {
-- int val = seq->val = 0;
-+ size_t val = seq->val = 0;
- int len = seq->len;
- size_t backw_stop = seq->backw_stop;
- size_t backw = seq->backw;
-@@ -146,7 +152,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
- const USTRING_TYPE *extra, const int32_t *indirect)
- {
- #include WEIGHT_H
-- int val = seq->val = 0;
-+ size_t val = seq->val = 0;
- int len = seq->len;
- size_t backw_stop = seq->backw_stop;
- size_t backw = seq->backw;
-@@ -162,7 +168,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
- ++val;
- if (backw_stop != ~0ul)
- {
-- /* The is something pushed. */
-+ /* There is something pushed. */
- if (backw == backw_stop)
- {
- /* The last pushed character was handled. Continue
-@@ -227,15 +233,199 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
- seq->us = us;
- }
-
--/* Compare two sequences. */
-+/* Get next sequence. Traverse the string as required. This function does not
-+ set or use any index or rule cache. */
-+static void
-+get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets,
-+ const USTRING_TYPE *weights, const int32_t *table,
-+ const USTRING_TYPE *extra, const int32_t *indirect,
-+ int pass)
-+{
-+#include WEIGHT_H
-+ size_t val = seq->val = 0;
-+ int len = seq->len;
-+ size_t backw_stop = seq->backw_stop;
-+ size_t backw = seq->backw;
-+ size_t idxcnt = seq->idxcnt;
-+ size_t idxmax = seq->idxmax;
-+ int32_t idx = seq->idx;
-+ const USTRING_TYPE *us = seq->us;
-+
-+ while (len == 0)
-+ {
-+ ++val;
-+ if (backw_stop != ~0ul)
-+ {
-+ /* There is something pushed. */
-+ if (backw == backw_stop)
-+ {
-+ /* The last pushed character was handled. Continue
-+ with forward characters. */
-+ if (idxcnt < idxmax)
-+ {
-+ idx = seq->save_idx;
-+ backw_stop = ~0ul;
-+ }
-+ else
-+ {
-+ /* Nothing anymore. The backward sequence ended with
-+ the last sequence in the string. Note that len is
-+ still zero. */
-+ idx = 0;
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ /* XXX Traverse BACKW sequences from the beginning of
-+ BACKW_STOP to get the next sequence. Is ther a quicker way
-+ to do this? */
-+ size_t i = backw_stop;
-+ us = seq->back_us;
-+ while (i < backw)
-+ {
-+ int32_t tmp = findidx (&us, -1);
-+ idx = tmp & 0xffffff;
-+ i++;
-+ }
-+ --backw;
-+ us = seq->us;
-+ }
-+ }
-+ else
-+ {
-+ backw_stop = idxmax;
-+ int32_t prev_idx = idx;
-+
-+ while (*us != L('\0'))
-+ {
-+ int32_t tmp = findidx (&us, -1);
-+ unsigned char rule = tmp >> 24;
-+ prev_idx = idx;
-+ idx = tmp & 0xffffff;
-+ idxcnt = idxmax++;
-+
-+ /* Save the rule for the first sequence. */
-+ if (__glibc_unlikely (idxcnt == 0))
-+ seq->rule = rule;
-+
-+ if ((rulesets[rule * nrules + pass]
-+ & sort_backward) == 0)
-+ /* No more backward characters to push. */
-+ break;
-+ ++idxcnt;
-+ }
-+
-+ if (backw_stop >= idxcnt)
-+ {
-+ /* No sequence at all or just one. */
-+ if (idxcnt == idxmax || backw_stop > idxcnt)
-+ /* Note that len is still zero. */
-+ break;
-+
-+ backw_stop = ~0ul;
-+ }
-+ else
-+ {
-+ /* We pushed backward sequences. If the stream ended with the
-+ backward sequence, then we process the last sequence we
-+ found. Otherwise we process the sequence before the last
-+ one since the last one was a forward sequence. */
-+ seq->back_us = seq->us;
-+ seq->us = us;
-+ backw = idxcnt;
-+ if (idxmax > idxcnt)
-+ {
-+ backw--;
-+ seq->save_idx = idx;
-+ idx = prev_idx;
-+ }
-+ if (backw > backw_stop)
-+ backw--;
-+ }
-+ }
-+
-+ len = weights[idx++];
-+ /* Skip over indices of previous levels. */
-+ for (int i = 0; i < pass; i++)
-+ {
-+ idx += len;
-+ len = weights[idx];
-+ idx++;
-+ }
-+ }
-+
-+ /* Update the structure. */
-+ seq->val = val;
-+ seq->len = len;
-+ seq->backw_stop = backw_stop;
-+ seq->backw = backw;
-+ seq->idxcnt = idxcnt;
-+ seq->idxmax = idxmax;
-+ seq->us = us;
-+ seq->idx = idx;
-+}
-+
-+/* Compare two sequences. This version does not use the index and rules
-+ cache. */
-+static int
-+do_compare_nocache (coll_seq *seq1, coll_seq *seq2, int position,
-+ const USTRING_TYPE *weights)
-+{
-+ int seq1len = seq1->len;
-+ int seq2len = seq2->len;
-+ size_t val1 = seq1->val;
-+ size_t val2 = seq2->val;
-+ int idx1 = seq1->idx;
-+ int idx2 = seq2->idx;
-+ int result = 0;
-+
-+ /* Test for position if necessary. */
-+ if (position && val1 != val2)
-+ {
-+ result = val1 > val2 ? 1 : -1;
-+ goto out;
-+ }
-+
-+ /* Compare the two sequences. */
-+ do
-+ {
-+ if (weights[idx1] != weights[idx2])
-+ {
-+ /* The sequences differ. */
-+ result = weights[idx1] - weights[idx2];
-+ goto out;
-+ }
-+
-+ /* Increment the offsets. */
-+ ++idx1;
-+ ++idx2;
-+
-+ --seq1len;
-+ --seq2len;
-+ }
-+ while (seq1len > 0 && seq2len > 0);
-+
-+ if (position && seq1len != seq2len)
-+ result = seq1len - seq2len;
-+
-+out:
-+ seq1->len = seq1len;
-+ seq2->len = seq2len;
-+ seq1->idx = idx1;
-+ seq2->idx = idx2;
-+ return result;
-+}
-+
-+/* Compare two sequences using the index cache. */
- static int
- do_compare (coll_seq *seq1, coll_seq *seq2, int position,
- const USTRING_TYPE *weights)
- {
- int seq1len = seq1->len;
- int seq2len = seq2->len;
-- int val1 = seq1->val;
-- int val2 = seq2->val;
-+ size_t val1 = seq1->val;
-+ size_t val2 = seq2->val;
- int32_t *idx1arr = seq1->idxarr;
- int32_t *idx2arr = seq2->idxarr;
- int idx1now = seq1->idxnow;
-@@ -245,7 +435,7 @@ do_compare (coll_seq *seq1, coll_seq *seq2, int position,
- /* Test for position if necessary. */
- if (position && val1 != val2)
- {
-- result = val1 - val2;
-+ result = val1 > val2 ? 1 : -1;
- goto out;
- }
-
-@@ -334,57 +524,62 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
- memset (&seq1, 0, sizeof (seq1));
- seq2 = seq1;
-
-- /* We need the elements of the strings as unsigned values since they
-- are used as indices. */
-- seq1.us = (const USTRING_TYPE *) s1;
-- seq2.us = (const USTRING_TYPE *) s2;
--
- if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
- {
- seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
-- seq2.idxarr = &seq1.idxarr[s1len];
-- seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
-- seq2.rulearr = &seq1.rulearr[s1len];
--
-- if (seq1.idxarr == NULL)
-- /* No memory. Well, go with the stack then.
--
-- XXX Once this implementation is stable we will handle this
-- differently. Instead of precomputing the indices we will
-- do this in time. This means, though, that this happens for
-- every pass again. */
-- goto try_stack;
-- use_malloc = true;
-+
-+ /* If we failed to allocate memory, we leave everything as NULL so that
-+ we use the nocache version of traversal and comparison functions. */
-+ if (seq1.idxarr != NULL)
-+ {
-+ seq2.idxarr = &seq1.idxarr[s1len];
-+ seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
-+ seq2.rulearr = &seq1.rulearr[s1len];
-+ use_malloc = true;
-+ }
- }
- else
- {
-- try_stack:
- seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t));
- seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t));
- seq1.rulearr = (unsigned char *) alloca (s1len);
- seq2.rulearr = (unsigned char *) alloca (s2len);
- }
-
-- seq1.rulearr[0] = 0;
-+ int rule = 0;
-
- /* Cache values in the first pass and if needed, use them in subsequent
- passes. */
- for (int pass = 0; pass < nrules; ++pass)
- {
- seq1.idxcnt = 0;
-+ seq1.idx = 0;
-+ seq2.idx = 0;
- seq1.backw_stop = ~0ul;
- seq1.backw = ~0ul;
- seq2.idxcnt = 0;
- seq2.backw_stop = ~0ul;
- seq2.backw = ~0ul;
-
-+ /* We need the elements of the strings as unsigned values since they
-+ are used as indices. */
-+ seq1.us = (const USTRING_TYPE *) s1;
-+ seq2.us = (const USTRING_TYPE *) s2;
-+
- /* We assume that if a rule has defined `position' in one section
- this is true for all of them. */
-- int position = rulesets[seq1.rulearr[0] * nrules + pass] & sort_position;
-+ int position = rulesets[rule * nrules + pass] & sort_position;
-
- while (1)
- {
-- if (pass == 0)
-+ if (__glibc_unlikely (seq1.idxarr == NULL))
-+ {
-+ get_next_seq_nocache (&seq1, nrules, rulesets, weights, table,
-+ extra, indirect, pass);
-+ get_next_seq_nocache (&seq2, nrules, rulesets, weights, table,
-+ extra, indirect, pass);
-+ }
-+ else if (pass == 0)
- {
- get_next_seq (&seq1, nrules, rulesets, weights, table, extra,
- indirect);
-@@ -411,10 +606,18 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
- goto free_and_return;
- }
-
-- result = do_compare (&seq1, &seq2, position, weights);
-+ if (__glibc_unlikely (seq1.idxarr == NULL))
-+ result = do_compare_nocache (&seq1, &seq2, position, weights);
-+ else
-+ result = do_compare (&seq1, &seq2, position, weights);
- if (result != 0)
- goto free_and_return;
- }
-+
-+ if (__glibc_likely (seq1.rulearr != NULL))
-+ rule = seq1.rulearr[0];
-+ else
-+ rule = seq1.rule;
- }
-
- /* Free the memory if needed. */