aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-17 05:11:43 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-17 05:11:43 +0000
commitb61e13d24741536fc713dab1c10a4925197b2072 (patch)
tree60608273ed2cf376466bd719c6cf4a745a2f0da0
parentccce59d5622dd32101e396580f7a148dfb3cb2d8 (diff)
downloadbusybox-w32-b61e13d24741536fc713dab1c10a4925197b2072.tar.gz
busybox-w32-b61e13d24741536fc713dab1c10a4925197b2072.tar.bz2
busybox-w32-b61e13d24741536fc713dab1c10a4925197b2072.zip
hush: fix memory leak. it was actually rather invloved problem.
Now finally glob/variable expansion is done IN THE RIGHT ORDER! It opens up a possibility to cleanly fix remaining known bugs. function old new delta o_save_ptr 115 286 +171 o_save_ptr_helper - 115 +115 done_word 591 690 +99 o_get_last_ptr - 31 +31 expand_on_ifs 125 97 -28 add_string_to_strings 28 - -28 run_list 1895 1862 -33 debug_print_strings 42 - -42 add_strings_to_strings 126 - -126 expand_variables 1550 1394 -156 o_debug_list 168 - -168 expand_strvec_to_strvec 388 10 -378 ------------------------------------------------------------------------------ (add/remove: 2/4 grow/shrink: 2/4 up/down: 416/-959) Total: -543 bytes
-rw-r--r--shell/hush.c313
1 files changed, 175 insertions, 138 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 0e1976443..0b92c29d4 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -104,6 +104,8 @@
104#define debug_printf_exec(...) do {} while (0) 104#define debug_printf_exec(...) do {} while (0)
105#define debug_printf_jobs(...) do {} while (0) 105#define debug_printf_jobs(...) do {} while (0)
106#define debug_printf_expand(...) do {} while (0) 106#define debug_printf_expand(...) do {} while (0)
107#define debug_printf_glob(...) do {} while (0)
108#define debug_printf_list(...) do {} while (0)
107#define debug_printf_clean(...) do {} while (0) 109#define debug_printf_clean(...) do {} while (0)
108 110
109#ifndef debug_printf 111#ifndef debug_printf
@@ -120,12 +122,27 @@
120 122
121#ifndef debug_printf_jobs 123#ifndef debug_printf_jobs
122#define debug_printf_jobs(...) fprintf(stderr, __VA_ARGS__) 124#define debug_printf_jobs(...) fprintf(stderr, __VA_ARGS__)
123#define DEBUG_SHELL_JOBS 1 125#define DEBUG_JOBS 1
126#else
127#define DEBUG_JOBS 0
124#endif 128#endif
125 129
126#ifndef debug_printf_expand 130#ifndef debug_printf_expand
127#define debug_printf_expand(...) fprintf(stderr, __VA_ARGS__) 131#define debug_printf_expand(...) fprintf(stderr, __VA_ARGS__)
128#define DEBUG_EXPAND 1 132#define DEBUG_EXPAND 1
133#else
134#define DEBUG_EXPAND 0
135#endif
136
137#ifndef debug_printf_glob
138#define debug_printf_glob(...) fprintf(stderr, __VA_ARGS__)
139#define DEBUG_GLOB 1
140#else
141#define DEBUG_GLOB 0
142#endif
143
144#ifndef debug_printf_list
145#define debug_printf_list(...) fprintf(stderr, __VA_ARGS__)
129#endif 146#endif
130 147
131/* Keep unconditionally on for now */ 148/* Keep unconditionally on for now */
@@ -143,6 +160,17 @@ static const char *indenter(int i)
143#define DEBUG_CLEAN 1 160#define DEBUG_CLEAN 1
144#endif 161#endif
145 162
163#if DEBUG_EXPAND
164static void debug_print_strings(const char *prefix, char **vv)
165{
166 fprintf(stderr, "%s:\n", prefix);
167 while (*vv)
168 fprintf(stderr, " '%s'\n", *vv++);
169}
170#else
171#define debug_print_strings(prefix, vv) ((void)0)
172#endif
173
146 174
147/* 175/*
148 * Leak hunting. Use hush_leaktool.sh for post-processing. 176 * Leak hunting. Use hush_leaktool.sh for post-processing.
@@ -309,6 +337,7 @@ typedef struct {
309 int length; 337 int length;
310 int maxlen; 338 int maxlen;
311 smallint o_quote; 339 smallint o_quote;
340 smallint o_glob;
312 smallint nonnull; 341 smallint nonnull;
313 smallint has_empty_slot; 342 smallint has_empty_slot;
314} o_string; 343} o_string;
@@ -531,6 +560,18 @@ static int set_local_var(char *str, int flg_export);
531static void unset_local_var(const char *name); 560static void unset_local_var(const char *name);
532 561
533 562
563static int glob_needed(const char *s)
564{
565 while (*s) {
566 if (*s == '\\')
567 s++;
568 if (*s == '*' || *s == '[' || *s == '?')
569 return 1;
570 s++;
571 }
572 return 0;
573}
574
534static char **add_strings_to_strings(int need_xstrdup, char **strings, char **add) 575static char **add_strings_to_strings(int need_xstrdup, char **strings, char **add)
535{ 576{
536 int i; 577 int i;
@@ -592,17 +633,6 @@ static char **alloc_ptrs(char **argv)
592} 633}
593#endif 634#endif
594 635
595#ifdef DEBUG_EXPAND
596static void debug_print_strings(const char *prefix, char **vv)
597{
598 fprintf(stderr, "%s:\n", prefix);
599 while (*vv)
600 fprintf(stderr, " '%s'\n", *vv++);
601}
602#else
603#define debug_print_strings(prefix, vv) ((void)0)
604#endif
605
606 636
607/* Function prototypes for builtins */ 637/* Function prototypes for builtins */
608static int builtin_cd(char **argv); 638static int builtin_cd(char **argv);
@@ -1260,7 +1290,33 @@ static void o_addQstr(o_string *o, const char *str, int len)
1260 * o_finalize_list() operation post-processes this structure - calculates 1290 * o_finalize_list() operation post-processes this structure - calculates
1261 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well. 1291 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
1262 */ 1292 */
1263static int o_save_ptr(o_string *o, int n) 1293#if DEBUG_EXPAND || DEBUG_GLOB
1294static void debug_print_list(const char *prefix, o_string *o, int n)
1295{
1296 char **list = (char**)o->data;
1297 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
1298 int i = 0;
1299 fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d\n",
1300 prefix, list, n, string_start, o->length, o->maxlen);
1301 while (i < n) {
1302 fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i],
1303 o->data + (int)list[i] + string_start,
1304 o->data + (int)list[i] + string_start);
1305 i++;
1306 }
1307 if (n) {
1308 const char *p = o->data + (int)list[n - 1] + string_start;
1309 fprintf(stderr, " total_sz:%d\n", (p + strlen(p) + 1) - o->data);
1310 }
1311}
1312#else
1313#define debug_print_list(prefix, o, n) ((void)0)
1314#endif
1315
1316/* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
1317 * in list[n] so that it points past last stored byte so far.
1318 * It returns n+1. */
1319static int o_save_ptr_helper(o_string *o, int n)
1264{ 1320{
1265 char **list = (char**)o->data; 1321 char **list = (char**)o->data;
1266 int string_start; 1322 int string_start;
@@ -1270,26 +1326,27 @@ static int o_save_ptr(o_string *o, int n)
1270 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); 1326 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
1271 string_len = o->length - string_start; 1327 string_len = o->length - string_start;
1272 if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */ 1328 if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
1273 //bb_error_msg("list[%d]=%d string_start=%d (growing)", n, string_len, string_start); 1329 debug_printf_list("list[%d]=%d string_start=%d (growing)", n, string_len, string_start);
1274 /* list[n] points to string_start, make space for 16 more pointers */ 1330 /* list[n] points to string_start, make space for 16 more pointers */
1275 o->maxlen += 0x10 * sizeof(list[0]); 1331 o->maxlen += 0x10 * sizeof(list[0]);
1276 o->data = xrealloc(o->data, o->maxlen + 1); 1332 o->data = xrealloc(o->data, o->maxlen + 1);
1277 list = (char**)o->data; 1333 list = (char**)o->data;
1278 memmove(list + n + 0x10, list + n, string_len); 1334 memmove(list + n + 0x10, list + n, string_len);
1279 o->length += 0x10 * sizeof(list[0]); 1335 o->length += 0x10 * sizeof(list[0]);
1280 } 1336 } else
1281 //else bb_error_msg("list[%d]=%d string_start=%d", n, string_len, string_start); 1337 debug_printf_list("list[%d]=%d string_start=%d", n, string_len, string_start);
1282 } else { 1338 } else {
1283 /* We have empty slot at list[n], reuse without growth */ 1339 /* We have empty slot at list[n], reuse without growth */
1284 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */ 1340 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
1285 string_len = o->length - string_start; 1341 string_len = o->length - string_start;
1286 //bb_error_msg("list[%d]=%d string_start=%d (empty slot)", n, string_len, string_start); 1342 debug_printf_list("list[%d]=%d string_start=%d (empty slot)", n, string_len, string_start);
1287 o->has_empty_slot = 0; 1343 o->has_empty_slot = 0;
1288 } 1344 }
1289 list[n] = (char*)string_len; 1345 list[n] = (char*)string_len;
1290 return n + 1; 1346 return n + 1;
1291} 1347}
1292 1348
1349/* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
1293static int o_get_last_ptr(o_string *o, int n) 1350static int o_get_last_ptr(o_string *o, int n)
1294{ 1351{
1295 char **list = (char**)o->data; 1352 char **list = (char**)o->data;
@@ -1298,14 +1355,89 @@ static int o_get_last_ptr(o_string *o, int n)
1298 return ((int)list[n-1]) + string_start; 1355 return ((int)list[n-1]) + string_start;
1299} 1356}
1300 1357
1358/* Convert every \x to x in-place, return ptr past NUL. */
1359static char *unbackslash(char *src)
1360{
1361 char *dst = src;
1362 while (1) {
1363 if (*src == '\\')
1364 src++;
1365 if ((*dst++ = *src++) == '\0')
1366 break;
1367 }
1368 return dst;
1369}
1370
1371static int o_glob(o_string *o, int n)
1372{
1373 glob_t globdata;
1374 int gr;
1375 char *pattern;
1376
1377 debug_printf_glob("start o_glob: n:%d o->data:%p", n, o->data);
1378 if (!o->data)
1379 return o_save_ptr_helper(o, n);
1380 pattern = o->data + o_get_last_ptr(o, n);
1381 debug_printf_glob("glob pattern '%s'", pattern);
1382 if (!glob_needed(pattern)) {
1383 literal:
1384 o->length = unbackslash(pattern) - o->data;
1385 debug_printf_glob("glob pattern '%s' is literal", pattern);
1386 return o_save_ptr_helper(o, n);
1387 }
1388
1389 memset(&globdata, 0, sizeof(globdata));
1390 gr = glob(pattern, 0, NULL, &globdata);
1391 debug_printf_glob("glob('%s'):%d\n", pattern, gr);
1392 if (gr == GLOB_NOSPACE)
1393 bb_error_msg_and_die("out of memory during glob");
1394 if (gr == GLOB_NOMATCH) {
1395 globfree(&globdata);
1396 goto literal;
1397 }
1398 if (gr != 0) { /* GLOB_ABORTED ? */
1399//TODO: testcase for bad glob pattern behavior
1400 bb_error_msg("glob(3) error %d on '%s'", gr, pattern);
1401 }
1402 if (globdata.gl_pathv && globdata.gl_pathv[0]) {
1403 char **argv = globdata.gl_pathv;
1404 o->length = pattern - o->data; /* "forget" pattern */
1405 while (1) {
1406 o_addstr(o, *argv, strlen(*argv) + 1);
1407 n = o_save_ptr_helper(o, n);
1408 argv++;
1409 if (!*argv)
1410 break;
1411 }
1412 }
1413 globfree(&globdata);
1414 if (DEBUG_GLOB)
1415 debug_print_list("o_glob returning", o, n);
1416 return n;
1417}
1418
1419/* o_save_ptr_helper + but glob the string so far remembered
1420 * if o->o_glob == 1 */
1421static int o_save_ptr(o_string *o, int n)
1422{
1423 if (o->o_glob)
1424 return o_glob(o, n); /* o_save_ptr_helper is inside */
1425 return o_save_ptr_helper(o, n);
1426}
1427
1428/* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
1301static char **o_finalize_list(o_string *o, int n) 1429static char **o_finalize_list(o_string *o, int n)
1302{ 1430{
1303 char **list = (char**)o->data; 1431 char **list;
1304 int string_start; 1432 int string_start;
1305 1433
1306 o_save_ptr(o, n); /* force growth for list[n] if necessary */ 1434 n = o_save_ptr(o, n); /* force growth for list[n] if necessary */
1307 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); 1435 if (DEBUG_EXPAND)
1308 list[n] = NULL; 1436 debug_print_list("finalized", o, n);
1437 debug_printf_expand("finalized n:%d", n);
1438 list = (char**)o->data;
1439 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
1440 list[--n] = NULL;
1309 while (n) { 1441 while (n) {
1310 n--; 1442 n--;
1311 list[n] = o->data + (int)list[n] + string_start; 1443 list[n] = o->data + (int)list[n] + string_start;
@@ -1313,28 +1445,6 @@ static char **o_finalize_list(o_string *o, int n)
1313 return list; 1445 return list;
1314} 1446}
1315 1447
1316#ifdef DEBUG_EXPAND
1317static void o_debug_list(const char *prefix, o_string *o, int n)
1318{
1319 char **list = (char**)o->data;
1320 int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
1321 int i = 0;
1322 fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d\n",
1323 prefix, list, n, string_start, o->length, o->maxlen);
1324 while (i < n) {
1325 fprintf(stderr, " list[%d]=%d '%s'\n", i, (int)list[i],
1326 o->data + (int)list[i] + string_start);
1327 i++;
1328 }
1329 if (n) {
1330 const char *p = o->data + (int)list[n] + string_start;
1331 fprintf(stderr, " total_sz:%d\n", (p + strlen(p) + 1) - o->data);
1332 }
1333}
1334#else
1335#define o_debug_list(prefix, o, n) ((void)0)
1336#endif
1337
1338 1448
1339/* 1449/*
1340 * in_str support 1450 * in_str support
@@ -1782,7 +1892,7 @@ static int checkjobs(struct pipe* fg_pipe)
1782 while ((childpid = waitpid(-1, &status, attributes)) > 0) { 1892 while ((childpid = waitpid(-1, &status, attributes)) > 0) {
1783 const int dead = WIFEXITED(status) || WIFSIGNALED(status); 1893 const int dead = WIFEXITED(status) || WIFSIGNALED(status);
1784 1894
1785#ifdef DEBUG_SHELL_JOBS 1895#if DEBUG_JOBS
1786 if (WIFSTOPPED(status)) 1896 if (WIFSTOPPED(status))
1787 debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n", 1897 debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n",
1788 childpid, WSTOPSIG(status), WEXITSTATUS(status)); 1898 childpid, WSTOPSIG(status), WEXITSTATUS(status));
@@ -2502,11 +2612,11 @@ static int expand_on_ifs(o_string *output, int n, const char *str)
2502 if (!*str) /* EOL - do not finalize word */ 2612 if (!*str) /* EOL - do not finalize word */
2503 break; 2613 break;
2504 o_addchr(output, '\0'); 2614 o_addchr(output, '\0');
2505 o_debug_list("expand_on_ifs", output, n); 2615 debug_print_list("expand_on_ifs", output, n);
2506 n = o_save_ptr(output, n); 2616 n = o_save_ptr(output, n);
2507 str += strspn(str, ifs); /* skip ifs chars */ 2617 str += strspn(str, ifs); /* skip ifs chars */
2508 } 2618 }
2509 o_debug_list("expand_on_ifs[1]", output, n); 2619 debug_print_list("expand_on_ifs[1]", output, n);
2510 return n; 2620 return n;
2511} 2621}
2512 2622
@@ -2530,9 +2640,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2530 ored_ch = 0; 2640 ored_ch = 0;
2531 2641
2532 debug_printf_expand("expand_vars_to_list: arg '%s'\n", arg); 2642 debug_printf_expand("expand_vars_to_list: arg '%s'\n", arg);
2533 o_debug_list("expand_vars_to_list", output, n); 2643 debug_print_list("expand_vars_to_list", output, n);
2534 n = o_save_ptr(output, n); 2644 n = o_save_ptr(output, n);
2535 o_debug_list("expand_vars_to_list[0]", output, n); 2645 debug_print_list("expand_vars_to_list[0]", output, n);
2536 2646
2537 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { 2647 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
2538#if ENABLE_HUSH_TICK 2648#if ENABLE_HUSH_TICK
@@ -2540,7 +2650,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2540#endif 2650#endif
2541 2651
2542 o_addQstr(output, arg, p - arg); 2652 o_addQstr(output, arg, p - arg);
2543 o_debug_list("expand_vars_to_list[1]", output, n); 2653 debug_print_list("expand_vars_to_list[1]", output, n);
2544 arg = ++p; 2654 arg = ++p;
2545 p = strchr(p, SPECIAL_VAR_SYMBOL); 2655 p = strchr(p, SPECIAL_VAR_SYMBOL);
2546 2656
@@ -2575,9 +2685,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2575 /* this argv[] is not empty and not last: 2685 /* this argv[] is not empty and not last:
2576 * put terminating NUL, start new word */ 2686 * put terminating NUL, start new word */
2577 o_addchr(output, '\0'); 2687 o_addchr(output, '\0');
2578 o_debug_list("expand_vars_to_list[2]", output, n); 2688 debug_print_list("expand_vars_to_list[2]", output, n);
2579 n = o_save_ptr(output, n); 2689 n = o_save_ptr(output, n);
2580 o_debug_list("expand_vars_to_list[3]", output, n); 2690 debug_print_list("expand_vars_to_list[3]", output, n);
2581 } 2691 }
2582 } 2692 }
2583 } else 2693 } else
@@ -2589,7 +2699,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2589 if (++i >= global_argc) 2699 if (++i >= global_argc)
2590 break; 2700 break;
2591 o_addchr(output, '\0'); 2701 o_addchr(output, '\0');
2592 o_debug_list("expand_vars_to_list[4]", output, n); 2702 debug_print_list("expand_vars_to_list[4]", output, n);
2593 n = o_save_ptr(output, n); 2703 n = o_save_ptr(output, n);
2594 } 2704 }
2595 } else { /* quoted $*: add as one word */ 2705 } else { /* quoted $*: add as one word */
@@ -2647,9 +2757,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2647 } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ 2757 } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
2648 2758
2649 if (arg[0]) { 2759 if (arg[0]) {
2650 o_debug_list("expand_vars_to_list[a]", output, n); 2760 debug_print_list("expand_vars_to_list[a]", output, n);
2651 o_addQstr(output, arg, strlen(arg) + 1); 2761 o_addQstr(output, arg, strlen(arg) + 1);
2652 o_debug_list("expand_vars_to_list[b]", output, n); 2762 debug_print_list("expand_vars_to_list[b]", output, n);
2653 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ 2763 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
2654 && !(ored_ch & 0x80) /* and all vars were not quoted. */ 2764 && !(ored_ch & 0x80) /* and all vars were not quoted. */
2655 ) { 2765 ) {
@@ -2662,106 +2772,33 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2662 return n; 2772 return n;
2663} 2773}
2664 2774
2665static char **expand_variables(char **argv, char or_mask) 2775static char **expand_variables(char **argv, int or_mask)
2666{ 2776{
2667 int n; 2777 int n;
2668 char **list; 2778 char **list;
2669 char **v; 2779 char **v;
2670 o_string output = NULL_O_STRING; 2780 o_string output = NULL_O_STRING;
2671 2781
2782 if (or_mask & 0x100)
2783 output.o_glob = 1;
2784
2672 n = 0; 2785 n = 0;
2673 v = argv; 2786 v = argv;
2674 while (*v) 2787 while (*v) {
2675 n = expand_vars_to_list(&output, n, *v++, or_mask); 2788 n = expand_vars_to_list(&output, n, *v, (char)or_mask);
2676 o_debug_list("expand_variables", &output, n); 2789 v++;
2790 }
2791 debug_print_list("expand_variables", &output, n);
2677 2792
2678 /* output.data (malloced in one block) gets returned in "list" */ 2793 /* output.data (malloced in one block) gets returned in "list" */
2679 list = o_finalize_list(&output, n); 2794 list = o_finalize_list(&output, n);
2795 debug_print_strings("expand_variables[1]", list);
2680 return list; 2796 return list;
2681} 2797}
2682 2798
2683/* Remove non-backslashed backslashes and add to "strings" vector.
2684 * XXX broken if the last character is '\\', check that before calling.
2685 */
2686static char **add_unq_string_to_strings(char **strings, const char *src)
2687{
2688 int cnt;
2689 const char *s;
2690 char *v, *dest;
2691
2692 for (cnt = 1, s = src; s && *s; s++) {
2693 if (*s == '\\') s++;
2694 cnt++;
2695 }
2696 v = dest = xmalloc(cnt);
2697 for (s = src; s && *s; s++, dest++) {
2698 if (*s == '\\') s++;
2699 *dest = *s;
2700 }
2701 *dest = '\0';
2702
2703 return add_string_to_strings(strings, v);
2704}
2705
2706/* XXX broken if the last character is '\\', check that before calling */
2707static int glob_needed(const char *s)
2708{
2709 for (; *s; s++) {
2710 if (*s == '\\')
2711 s++;
2712 if (strchr("*[?", *s))
2713 return 1;
2714 }
2715 return 0;
2716}
2717
2718static void xglob(char ***pglob, const char *pattern)
2719{
2720 if (glob_needed(pattern)) {
2721 glob_t globdata;
2722 int gr;
2723
2724 memset(&globdata, 0, sizeof(globdata));
2725 gr = glob(pattern, 0, NULL, &globdata);
2726 debug_printf("glob returned %d\n", gr);
2727 if (gr == GLOB_NOSPACE)
2728 bb_error_msg_and_die("out of memory during glob");
2729 if (gr == GLOB_NOMATCH) {
2730 globfree(&globdata);
2731 goto literal;
2732 }
2733 if (gr != 0) { /* GLOB_ABORTED ? */
2734 bb_error_msg("glob(3) error %d on '%s'", gr, pattern);
2735//TODO: testcase for bad glob pattern behavior
2736 }
2737 if (globdata.gl_pathv && globdata.gl_pathv[0])
2738 *pglob = add_strings_to_strings(1, *pglob, globdata.gl_pathv);
2739 globfree(&globdata);
2740 return;
2741 }
2742
2743 literal:
2744 /* quote removal, or more accurately, backslash removal */
2745 *pglob = add_unq_string_to_strings(*pglob, pattern);
2746 debug_print_strings("after xglob", *pglob);
2747}
2748
2749//LEAK is here: callers expect result to be free()able, but we
2750//actually require free_strings(). free() leaks strings.
2751static char **expand_strvec_to_strvec(char **argv) 2799static char **expand_strvec_to_strvec(char **argv)
2752{ 2800{
2753 char **exp; 2801 return expand_variables(argv, 0x100);
2754 char **res = xzalloc(sizeof(res[0]));
2755
2756 debug_print_strings("expand_strvec_to_strvec: pre expand", argv);
2757 exp = argv = expand_variables(argv, 0);
2758 debug_print_strings("expand_strvec_to_strvec: post expand", argv);
2759 while (*argv) {
2760 xglob(&res, *argv++);
2761 }
2762 free(exp);
2763 debug_print_strings("expand_strvec_to_strvec: res", res);
2764 return res;
2765} 2802}
2766 2803
2767/* used for expansion of right hand of assignments */ 2804/* used for expansion of right hand of assignments */