aboutsummaryrefslogtreecommitdiff
path: root/localedata/xfrm-test.c
diff options
context:
space:
mode:
authorLeonhard Holz <leonhard.holz@web.de>2015-01-13 11:33:56 +0530
committerTulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>2016-07-11 13:52:20 -0300
commit1a43fd3240c587b403240cf316d241f91ce50d8f (patch)
tree172ee4be176fae0b1d6e0eaac9f3d18693c66ac4 /localedata/xfrm-test.c
parentce92632d1297d032e5781cfa077e300f5c167471 (diff)
downloadglibc-1a43fd3240c587b403240cf316d241f91ce50d8f.zip
glibc-1a43fd3240c587b403240cf316d241f91ce50d8f.tar.gz
glibc-1a43fd3240c587b403240cf316d241f91ce50d8f.tar.bz2
Fix memory handling in strxfrm_l [BZ #16009]
[Modified from the original email by Siddhesh Poyarekar] This patch solves bug #16009 by implementing an additional path in strxfrm that does not depend on caching the weight and rule indices. In detail the following changed: * The old main loop was factored out of strxfrm_l into the function do_xfrm_cached to be able to alternativly use the non-caching version do_xfrm. * strxfrm_l allocates a a fixed size array on the stack. If this is not sufficiant to store the weight and rule indices, the non-caching path is taken. As the cache size is not dependent on the input there can be no problems with integer overflows or stack allocations greater than __MAX_ALLOCA_CUTOFF. Note that malloc-ing is not possible because the definition of strxfrm does not allow an oom errorhandling. * The uncached path determines the weight and rule index for every char and for every pass again. * Passing all the locale data array by array resulted in very long parameter lists, so I introduced a structure that holds them. * Checking for zero src string has been moved a bit upwards, it is before the locale data initialization now. * To verify that the non-caching path works correct I added a test run to localedata/sort-test.sh & localedata/xfrm-test.c where all strings are patched up with spaces so that they are too large for the caching path. (cherry picked from commit 0f9e585480edcdf1e30dc3d79e24b84aeee516fa) Conflicts: NEWS string/strxfrm_l.c
Diffstat (limited to 'localedata/xfrm-test.c')
-rw-r--r--localedata/xfrm-test.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/localedata/xfrm-test.c b/localedata/xfrm-test.c
index d2aba7d..5cf29f6 100644
--- a/localedata/xfrm-test.c
+++ b/localedata/xfrm-test.c
@@ -23,7 +23,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
+/* Keep in sync with string/strxfrm_l.c. */
+#define SMALL_STR_SIZE 4095
struct lines
{
@@ -37,6 +40,7 @@ int
main (int argc, char *argv[])
{
int result = 0;
+ bool nocache = false;
size_t nstrings, nstrings_max;
struct lines *strings;
char *line = NULL;
@@ -44,7 +48,18 @@ main (int argc, char *argv[])
size_t n;
if (argc < 2)
- error (1, 0, "usage: %s <random seed>", argv[0]);
+ error (1, 0, "usage: %s <random seed> [-nocache]", argv[0]);
+
+ if (argc == 3)
+ {
+ if (strcmp (argv[2], "-nocache") == 0)
+ nocache = true;
+ else
+ {
+ printf ("Unknown option %s!\n", argv[2]);
+ exit (1);
+ }
+ }
setlocale (LC_ALL, "");
@@ -59,9 +74,9 @@ main (int argc, char *argv[])
while (1)
{
- char saved, *newp;
- int needed;
- int l;
+ char saved, *word, *newp;
+ size_t l, line_len, needed;
+
if (getline (&line, &len, stdin) < 0)
break;
@@ -83,10 +98,35 @@ main (int argc, char *argv[])
saved = line[l];
line[l] = '\0';
- needed = strxfrm (NULL, line, 0);
+
+ if (nocache)
+ {
+ line_len = strlen (line);
+ word = malloc (line_len + SMALL_STR_SIZE + 1);
+ if (word == NULL)
+ {
+ printf ("malloc failed: %m\n");
+ exit (1);
+ }
+ memset (word, ' ', SMALL_STR_SIZE);
+ memcpy (word + SMALL_STR_SIZE, line, line_len);
+ word[line_len + SMALL_STR_SIZE] = '\0';
+ }
+ else
+ word = line;
+
+ needed = strxfrm (NULL, word, 0);
newp = malloc (needed + 1);
- strxfrm (newp, line, needed + 1);
+ if (newp == NULL)
+ {
+ printf ("malloc failed: %m\n");
+ exit (1);
+ }
+ strxfrm (newp, word, needed + 1);
strings[nstrings].xfrm = newp;
+
+ if (nocache)
+ free (word);
line[l] = saved;
++nstrings;
}