Root/toolchain/uClibc/patches-0.9.33.2/010-backport_sscanf_alloc.patch

1From 8cfb43de636faa401634340d1a18404844f9ba5a Mon Sep 17 00:00:00 2001
2From: Mike Frysinger <vapier@gentoo.org>
3Date: Sun, 6 May 2012 03:50:44 -0400
4Subject: [PATCH] stdio: implement assignment-allocation "m" character
5
6The latest POSIX spec introduces a "m" character to allocate buffers for
7the user when using scanf type functions. This is like the old glibc "a"
8flag, but now standardized. With packages starting to use these, we need
9to implement it.
10
11for example:
12    char *s;
13    sscanf("foo", "%ms", &s);
14    printf("%s\n", s);
15    free(s);
16This will automatically allocate storage for "s", read in "foo" to it,
17and then display it.
18
19I'm not terribly familiar with the stdio layer, so this could be wrong.
20But it seems to work for me.
21
22Signed-off-by: Mike Frysinger <vapier@gentoo.org>
23Signed-off-by: Felix Fietkau <nbd@openwrt.org>
24---
25 extra/Configs/Config.in | 13 ----------
26 libc/stdio/_scanf.c | 68 ++++++++++++++++++++++++++++---------------------
27 2 files changed, 39 insertions(+), 42 deletions(-)
28
29--- a/extra/Configs/Config.in
30+++ b/extra/Configs/Config.in
31@@ -1597,19 +1597,6 @@ config UCLIBC_PRINTF_SCANF_POSITIONAL_AR
32 
33       Most people will answer 9.
34 
35-
36-config UCLIBC_HAS_SCANF_GLIBC_A_FLAG
37- bool "Support glibc's 'a' flag for scanf string conversions (not implemented)"
38- help
39- NOTE!!! Currently Not Implemented!!! Just A Place Holder!! NOTE!!!
40- NOTE!!! Conflicts with an ANSI/ISO C99 scanf flag!! NOTE!!!
41-
42- Answer Y to enable support for glibc's 'a' flag for the scanf string
43- conversions '%s', '%[', '%ls', '%l[', and '%S'. This is used to
44- auto-allocate sufficient memory to hold the data retrieved.
45-
46- Most people will answer N.
47-
48 choice
49     prompt "Stdio buffer size"
50     default UCLIBC_HAS_STDIO_BUFSIZ_4096
51--- a/libc/stdio/_scanf.c
52+++ b/libc/stdio/_scanf.c
53@@ -77,14 +77,6 @@
54 #include <bits/uClibc_fpmax.h>
55 #endif /* __UCLIBC_HAS_FLOATS__ */
56 
57-#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
58-#ifdef L_vfscanf
59-/* only emit this once */
60-#warning Forcing undef of __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ until implemented!
61-#endif
62-#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
63-#endif
64-
65 #undef __STDIO_HAS_VSSCANF
66 #if defined(__STDIO_BUFFERS) || !defined(__UCLIBC_HAS_WCHAR__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__)
67 #define __STDIO_HAS_VSSCANF 1
68@@ -433,8 +425,9 @@ libc_hidden_def(vswscanf)
69 
70 
71 /* float layout 0123456789012345678901 repeat n for "l[" */
72-#define SPEC_CHARS "npxXoudifFeEgGaACSncs["
73-/* npxXoudif eEgG CS cs[ */
74+#define SPEC_CHARS "npxXoudifFeEgGaACSnmcs["
75+/* npxXoudif eEgG CS cs[ */
76+/* NOTE: the 'm' flag must come before any convs that support it */
77 
78 /* NOTE: Ordering is important! In particular, CONV_LEFTBRACKET
79  * must immediately precede CONV_c. */
80@@ -444,7 +437,7 @@ enum {
81     CONV_p,
82     CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i,
83     CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A,
84- CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_c, CONV_s, CONV_leftbracket,
85+ CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_m, CONV_c, CONV_s, CONV_leftbracket,
86     CONV_percent, CONV_whitespace /* not in SPEC_* and no flags */
87 };
88 
89@@ -474,7 +467,7 @@ enum {
90     FLAG_SURPRESS = 0x10, /* MUST BE 1ST!! See DO_FLAGS. */
91     FLAG_THOUSANDS = 0x20,
92     FLAG_I18N = 0x40, /* only works for d, i, u */
93- FLAG_MALLOC = 0x80, /* only works for s, S, and [ (and l[)*/
94+ FLAG_MALLOC = 0x80, /* only works for c, s, S, and [ (and l[)*/
95 };
96 
97 
98@@ -491,7 +484,7 @@ enum {
99     /* fFeEgGaA */ (0x0c|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \
100     /* C */ ( 0|FLAG_SURPRESS), \
101     /* S and l[ */ ( 0|FLAG_SURPRESS|FLAG_MALLOC), \
102- /* c */ (0x04|FLAG_SURPRESS), \
103+ /* c */ (0x04|FLAG_SURPRESS|FLAG_MALLOC), \
104     /* s and [ */ (0x04|FLAG_SURPRESS|FLAG_MALLOC), \
105 }
106 
107@@ -904,17 +897,17 @@ int attribute_hidden __psfs_parse_spec(r
108         if (*psfs->fmt == *p) {
109             int p_m_spec_chars = p - spec_chars;
110 
111-#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
112-#error implement gnu a flag
113- if ((*p == 'a')
114- && ((psfs->fmt[1] == '[') || ((psfs->fmt[1]|0x20) == 's'))
115- ) { /* Assumes ascii for 's' and 'S' test. */
116- psfs->flags |= FLAG_MALLOC;
117+ if (*p == 'm' &&
118+ (psfs->fmt[1] == '[' || psfs->fmt[1] == 'c' ||
119+ /* Assumes ascii for 's' and 'S' test. */
120+ (psfs->fmt[1] | 0x20) == 's'))
121+ {
122+ if (psfs->store)
123+ psfs->flags |= FLAG_MALLOC;
124                 ++psfs->fmt;
125                 ++p;
126- continue; /* The related conversions follow 'a'. */
127+ continue; /* The related conversions follow 'm'. */
128             }
129-#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */
130 
131             for (p = spec_ranges; p_m_spec_chars > *p ; ++p) {}
132             if (((psfs->dataargtype >> 8) | psfs->flags)
133@@ -1265,12 +1258,6 @@ int VFSCANF (FILE *__restrict fp, const
134                 while (*wf && __isascii(*wf) && (b < buf + sizeof(buf) - 1)) {
135                     *b++ = *wf++;
136                 }
137-#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
138-#error this is wrong... we need to ched in __psfs_parse_spec instead since this checks last char in buffer and conversion my have stopped before it.
139- if ((*b == 'a') && ((*wf == '[') || ((*wf|0x20) == 's'))) {
140- goto DONE; /* Spec was excessively long. */
141- }
142-#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */
143                 *b = 0;
144                 if (b == buf) { /* Bad conversion specifier! */
145                     goto DONE;
146@@ -1390,13 +1377,36 @@ int VFSCANF (FILE *__restrict fp, const
147                 }
148 
149                 if (psfs.conv_num == CONV_s) {
150+ /* We might have to handle the allocation ourselves */
151+ int len;
152+ /* With 'm', we actually got a pointer to a pointer */
153+ unsigned char **ptr = (void *)b;
154+
155+ i = 0;
156+ if (psfs.flags & FLAG_MALLOC) {
157+ len = 0;
158+ b = NULL;
159+ } else
160+ len = -1;
161+
162                     /* Yes, believe it or not, a %s conversion can store nuls. */
163                     while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) {
164                         zero_conversions = 0;
165- *b = sc.cc;
166- b += psfs.store;
167+ if (i == len) {
168+ /* Pick a size that won't trigger a lot of
169+ * mallocs early on ... */
170+ len += 256;
171+ b = realloc(b, len + 1);
172+ }
173+ b[i] = sc.cc;
174+ i += psfs.store;
175                         fail = 0;
176                     }
177+
178+ if (psfs.flags & FLAG_MALLOC)
179+ *ptr = b;
180+ /* The code below takes care of terminating NUL */
181+ b += i;
182                 } else {
183 #ifdef __UCLIBC_HAS_WCHAR__
184                     assert((psfs.conv_num == CONV_LEFTBRACKET) || \
185

Archive Download this file



interactive