aboutsummaryrefslogtreecommitdiffstats
path: root/lib/test-string_helpers.c
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2014-10-13 18:55:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 20:18:26 -0400
commitc8250381c8272a9828fdd353171727b154fbd296 (patch)
tree050650d45d87d430334939f0552deafbe36561f9 /lib/test-string_helpers.c
parent45ff337a54c154680edf0c538e5c9eb4a2f862cc (diff)
lib / string_helpers: introduce string_escape_mem()
This is almost the opposite function to string_unescape(). Nevertheless it handles \0 and could be used for any byte buffer. The documentation is supplied together with the function prototype. The test cases covers most of the scenarios and would be expanded later on. [akpm@linux-foundation.org: avoid 1k stack consumption] Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: "John W . Linville" <linville@tuxdriver.com> Cc: Johannes Berg <johannes@sipsolutions.net> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Joe Perches <joe@perches.com> Cc: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/test-string_helpers.c')
-rw-r--r--lib/test-string_helpers.c240
1 files changed, 236 insertions, 4 deletions
diff --git a/lib/test-string_helpers.c b/lib/test-string_helpers.c
index ac44c9245dcf..ab0d30e1e18f 100644
--- a/lib/test-string_helpers.c
+++ b/lib/test-string_helpers.c
@@ -5,6 +5,7 @@
5 5
6#include <linux/init.h> 6#include <linux/init.h>
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/slab.h>
8#include <linux/module.h> 9#include <linux/module.h>
9#include <linux/random.h> 10#include <linux/random.h>
10#include <linux/string.h> 11#include <linux/string.h>
@@ -62,10 +63,14 @@ static const struct test_string strings[] __initconst = {
62static void __init test_string_unescape(const char *name, unsigned int flags, 63static void __init test_string_unescape(const char *name, unsigned int flags,
63 bool inplace) 64 bool inplace)
64{ 65{
65 char in[256]; 66 int q_real = 256;
66 char out_test[256]; 67 char *in = kmalloc(q_real, GFP_KERNEL);
67 char out_real[256]; 68 char *out_test = kmalloc(q_real, GFP_KERNEL);
68 int i, p = 0, q_test = 0, q_real = sizeof(out_real); 69 char *out_real = kmalloc(q_real, GFP_KERNEL);
70 int i, p = 0, q_test = 0;
71
72 if (!in || !out_test || !out_real)
73 goto out;
69 74
70 for (i = 0; i < ARRAY_SIZE(strings); i++) { 75 for (i = 0; i < ARRAY_SIZE(strings); i++) {
71 const char *s = strings[i].in; 76 const char *s = strings[i].in;
@@ -100,6 +105,223 @@ static void __init test_string_unescape(const char *name, unsigned int flags,
100 105
101 test_string_check_buf(name, flags, in, p - 1, out_real, q_real, 106 test_string_check_buf(name, flags, in, p - 1, out_real, q_real,
102 out_test, q_test); 107 out_test, q_test);
108out:
109 kfree(out_real);
110 kfree(out_test);
111 kfree(in);
112}
113
114struct test_string_1 {
115 const char *out;
116 unsigned int flags;
117};
118
119#define TEST_STRING_2_MAX_S1 32
120struct test_string_2 {
121 const char *in;
122 struct test_string_1 s1[TEST_STRING_2_MAX_S1];
123};
124
125#define TEST_STRING_2_DICT_0 NULL
126static const struct test_string_2 escape0[] __initconst = {{
127 .in = "\f\\ \n\r\t\v",
128 .s1 = {{
129 .out = "\\f\\ \\n\\r\\t\\v",
130 .flags = ESCAPE_SPACE,
131 },{
132 .out = "\\f\\134\\040\\n\\r\\t\\v",
133 .flags = ESCAPE_SPACE | ESCAPE_OCTAL,
134 },{
135 .out = "\\f\\x5c\\x20\\n\\r\\t\\v",
136 .flags = ESCAPE_SPACE | ESCAPE_HEX,
137 },{
138 /* terminator */
139 }},
140},{
141 .in = "\\h\\\"\a\e\\",
142 .s1 = {{
143 .out = "\\\\h\\\\\"\\a\\e\\\\",
144 .flags = ESCAPE_SPECIAL,
145 },{
146 .out = "\\\\\\150\\\\\\042\\a\\e\\\\",
147 .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
148 },{
149 .out = "\\\\\\x68\\\\\\x22\\a\\e\\\\",
150 .flags = ESCAPE_SPECIAL | ESCAPE_HEX,
151 },{
152 /* terminator */
153 }},
154},{
155 .in = "\eb \\C\007\"\x90\r]",
156 .s1 = {{
157 .out = "\eb \\C\007\"\x90\\r]",
158 .flags = ESCAPE_SPACE,
159 },{
160 .out = "\\eb \\\\C\\a\"\x90\r]",
161 .flags = ESCAPE_SPECIAL,
162 },{
163 .out = "\\eb \\\\C\\a\"\x90\\r]",
164 .flags = ESCAPE_SPACE | ESCAPE_SPECIAL,
165 },{
166 .out = "\\033\\142\\040\\134\\103\\007\\042\\220\\015\\135",
167 .flags = ESCAPE_OCTAL,
168 },{
169 .out = "\\033\\142\\040\\134\\103\\007\\042\\220\\r\\135",
170 .flags = ESCAPE_SPACE | ESCAPE_OCTAL,
171 },{
172 .out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\015\\135",
173 .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
174 },{
175 .out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\r\\135",
176 .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_OCTAL,
177 },{
178 .out = "\eb \\C\007\"\x90\r]",
179 .flags = ESCAPE_NP,
180 },{
181 .out = "\eb \\C\007\"\x90\\r]",
182 .flags = ESCAPE_SPACE | ESCAPE_NP,
183 },{
184 .out = "\\eb \\C\\a\"\x90\r]",
185 .flags = ESCAPE_SPECIAL | ESCAPE_NP,
186 },{
187 .out = "\\eb \\C\\a\"\x90\\r]",
188 .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_NP,
189 },{
190 .out = "\\033b \\C\\007\"\\220\\015]",
191 .flags = ESCAPE_OCTAL | ESCAPE_NP,
192 },{
193 .out = "\\033b \\C\\007\"\\220\\r]",
194 .flags = ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_NP,
195 },{
196 .out = "\\eb \\C\\a\"\\220\\r]",
197 .flags = ESCAPE_SPECIAL | ESCAPE_SPACE | ESCAPE_OCTAL |
198 ESCAPE_NP,
199 },{
200 .out = "\\x1bb \\C\\x07\"\\x90\\x0d]",
201 .flags = ESCAPE_NP | ESCAPE_HEX,
202 },{
203 /* terminator */
204 }},
205},{
206 /* terminator */
207}};
208
209#define TEST_STRING_2_DICT_1 "b\\ \t\r"
210static const struct test_string_2 escape1[] __initconst = {{
211 .in = "\f\\ \n\r\t\v",
212 .s1 = {{
213 .out = "\f\\134\\040\n\\015\\011\v",
214 .flags = ESCAPE_OCTAL,
215 },{
216 .out = "\f\\x5c\\x20\n\\x0d\\x09\v",
217 .flags = ESCAPE_HEX,
218 },{
219 /* terminator */
220 }},
221},{
222 .in = "\\h\\\"\a\e\\",
223 .s1 = {{
224 .out = "\\134h\\134\"\a\e\\134",
225 .flags = ESCAPE_OCTAL,
226 },{
227 /* terminator */
228 }},
229},{
230 .in = "\eb \\C\007\"\x90\r]",
231 .s1 = {{
232 .out = "\e\\142\\040\\134C\007\"\x90\\015]",
233 .flags = ESCAPE_OCTAL,
234 },{
235 /* terminator */
236 }},
237},{
238 /* terminator */
239}};
240
241static __init const char *test_string_find_match(const struct test_string_2 *s2,
242 unsigned int flags)
243{
244 const struct test_string_1 *s1 = s2->s1;
245 unsigned int i;
246
247 if (!flags)
248 return s2->in;
249
250 /* Test cases are NULL-aware */
251 flags &= ~ESCAPE_NULL;
252
253 /* ESCAPE_OCTAL has a higher priority */
254 if (flags & ESCAPE_OCTAL)
255 flags &= ~ESCAPE_HEX;
256
257 for (i = 0; i < TEST_STRING_2_MAX_S1 && s1->out; i++, s1++)
258 if (s1->flags == flags)
259 return s1->out;
260 return NULL;
261}
262
263static __init void test_string_escape(const char *name,
264 const struct test_string_2 *s2,
265 unsigned int flags, const char *esc)
266{
267 int q_real = 512;
268 char *out_test = kmalloc(q_real, GFP_KERNEL);
269 char *out_real = kmalloc(q_real, GFP_KERNEL);
270 char *in = kmalloc(256, GFP_KERNEL);
271 char *buf = out_real;
272 int p = 0, q_test = 0;
273
274 if (!out_test || !out_real || !in)
275 goto out;
276
277 for (; s2->in; s2++) {
278 const char *out;
279 int len;
280
281 /* NULL injection */
282 if (flags & ESCAPE_NULL) {
283 in[p++] = '\0';
284 out_test[q_test++] = '\\';
285 out_test[q_test++] = '0';
286 }
287
288 /* Don't try strings that have no output */
289 out = test_string_find_match(s2, flags);
290 if (!out)
291 continue;
292
293 /* Copy string to in buffer */
294 len = strlen(s2->in);
295 memcpy(&in[p], s2->in, len);
296 p += len;
297
298 /* Copy expected result for given flags */
299 len = strlen(out);
300 memcpy(&out_test[q_test], out, len);
301 q_test += len;
302 }
303
304 q_real = string_escape_mem(in, p, &buf, q_real, flags, esc);
305
306 test_string_check_buf(name, flags, in, p, out_real, q_real, out_test,
307 q_test);
308out:
309 kfree(in);
310 kfree(out_real);
311 kfree(out_test);
312}
313
314static __init void test_string_escape_nomem(void)
315{
316 char *in = "\eb \\C\007\"\x90\r]";
317 char out[64], *buf = out;
318 int rc = -ENOMEM, ret;
319
320 ret = string_escape_str_any_np(in, &buf, strlen(in), NULL);
321 if (ret == rc)
322 return;
323
324 pr_err("Test 'escape nomem' failed: got %d instead of %d\n", ret, rc);
103} 325}
104 326
105static int __init test_string_helpers_init(void) 327static int __init test_string_helpers_init(void)
@@ -112,6 +334,16 @@ static int __init test_string_helpers_init(void)
112 test_string_unescape("unescape inplace", 334 test_string_unescape("unescape inplace",
113 get_random_int() % (UNESCAPE_ANY + 1), true); 335 get_random_int() % (UNESCAPE_ANY + 1), true);
114 336
337 /* Without dictionary */
338 for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++)
339 test_string_escape("escape 0", escape0, i, TEST_STRING_2_DICT_0);
340
341 /* With dictionary */
342 for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++)
343 test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1);
344
345 test_string_escape_nomem();
346
115 return -EINVAL; 347 return -EINVAL;
116} 348}
117module_init(test_string_helpers_init); 349module_init(test_string_helpers_init);