aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-09-21 16:25:58 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-09-21 16:25:58 +0200
commitb3f29b452a660a7293162897424bed205f7f9147 (patch)
treebd334b845e1affd68620bcffe60c3e6381606958 /shell/ash.c
parentd8330ca4a42a7f5d81b233a1cf7cbc7a7bd0be95 (diff)
downloadbusybox-w32-b3f29b452a660a7293162897424bed205f7f9147.tar.gz
busybox-w32-b3f29b452a660a7293162897424bed205f7f9147.tar.bz2
busybox-w32-b3f29b452a660a7293162897424bed205f7f9147.zip
ash: use glob() from libc
Adapted from dash. The "homegrown" glob code is retained (ifdef'ed out). This changes was inspired by bug 9261, which detected out-of bounds use of heap for 2098 byte long name in the "homegrown" code. This is still not fixed... function old new delta expandarg 960 982 +22 static.syntax_index_table 26 25 -1 static.spec_symbls 27 26 -1 static.metachars 4 - -4 addfname 42 - -42 msort 126 - -126 expmeta 528 - -528 ------------------------------------------------------------------------------ (add/remove: 0/4 grow/shrink: 1/2 up/down: 22/-702) Total: -680 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c102
1 files changed, 91 insertions, 11 deletions
diff --git a/shell/ash.c b/shell/ash.c
index d96e56851..267493708 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -39,6 +39,7 @@
39 39
40#include <setjmp.h> 40#include <setjmp.h>
41#include <fnmatch.h> 41#include <fnmatch.h>
42#include <glob.h>
42#include <sys/times.h> 43#include <sys/times.h>
43#include <sys/utsname.h> /* for setting $HOSTNAME */ 44#include <sys/utsname.h> /* for setting $HOSTNAME */
44 45
@@ -2808,18 +2809,27 @@ enum {
2808static int 2809static int
2809SIT(int c, int syntax) 2810SIT(int c, int syntax)
2810{ 2811{
2811 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~"; 2812 /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2813 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2814 /*
2815 * This causes '/' to be prepended with CTLESC in dquoted string,
2816 * making "./file"* treated incorrectly because we feed
2817 * ".\/file*" string to glob(), confusing it (see expandmeta func).
2818 * The "homegrown" glob implementation is okay with that,
2819 * but glibc one isn't. With '/' always treated as CWORD,
2820 * both work fine.
2821 */
2812# if ENABLE_ASH_ALIAS 2822# if ENABLE_ASH_ALIAS
2813 static const uint8_t syntax_index_table[] ALIGN1 = { 2823 static const uint8_t syntax_index_table[] ALIGN1 = {
2814 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */ 2824 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2815 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */ 2825 7, 8, 3, 3,/*3,*/3, 1, 1, /* "()*-/:;<" */
2816 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */ 2826 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2817 11, 3 /* "}~" */ 2827 11, 3 /* "}~" */
2818 }; 2828 };
2819# else 2829# else
2820 static const uint8_t syntax_index_table[] ALIGN1 = { 2830 static const uint8_t syntax_index_table[] ALIGN1 = {
2821 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */ 2831 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2822 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */ 2832 6, 7, 2, 2,/*2,*/2, 0, 0, /* "()*-/:;<" */
2823 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */ 2833 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2824 10, 2 /* "}~" */ 2834 10, 2 /* "}~" */
2825 }; 2835 };
@@ -2901,7 +2911,8 @@ static const uint8_t syntax_index_table[] ALIGN1 = {
2901 /* 44 "," */ CWORD_CWORD_CWORD_CWORD, 2911 /* 44 "," */ CWORD_CWORD_CWORD_CWORD,
2902 /* 45 "-" */ CWORD_CCTL_CCTL_CWORD, 2912 /* 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2903 /* 46 "." */ CWORD_CWORD_CWORD_CWORD, 2913 /* 46 "." */ CWORD_CWORD_CWORD_CWORD,
2904 /* 47 "/" */ CWORD_CCTL_CCTL_CWORD, 2914/* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2915 /* 47 "/" */ CWORD_CWORD_CWORD_CWORD,
2905 /* 48 "0" */ CWORD_CWORD_CWORD_CWORD, 2916 /* 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2906 /* 49 "1" */ CWORD_CWORD_CWORD_CWORD, 2917 /* 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2907 /* 50 "2" */ CWORD_CWORD_CWORD_CWORD, 2918 /* 50 "2" */ CWORD_CWORD_CWORD_CWORD,
@@ -5633,7 +5644,6 @@ rmescapes(char *str, int flag)
5633 while (*p) { 5644 while (*p) {
5634 if ((unsigned char)*p == CTLQUOTEMARK) { 5645 if ((unsigned char)*p == CTLQUOTEMARK) {
5635// Note: both inquotes and protect_against_glob only affect whether 5646// Note: both inquotes and protect_against_glob only affect whether
5636// CTLESC,<ch> gets converted to <ch> or to \<ch>
5637 inquotes = ~inquotes; 5647 inquotes = ~inquotes;
5638 p++; 5648 p++;
5639 protect_against_glob = globbing; 5649 protect_against_glob = globbing;
@@ -5697,11 +5707,14 @@ memtodest(const char *p, size_t len, int syntax, int quotes)
5697 unsigned char c = *p++; 5707 unsigned char c = *p++;
5698 if (c) { 5708 if (c) {
5699 int n = SIT(c, syntax); 5709 int n = SIT(c, syntax);
5700 if ((quotes & QUOTES_ESC) && 5710 if ((quotes & QUOTES_ESC)
5701 ((n == CCTL) || 5711 && ((n == CCTL)
5702 (((quotes & EXP_FULL) || syntax != BASESYNTAX) && 5712 || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5703 n == CBACK))) 5713 && n == CBACK)
5714 )
5715 ) {
5704 USTPUTC(CTLESC, q); 5716 USTPUTC(CTLESC, q);
5717 }
5705 } else if (!(quotes & QUOTES_KEEPNUL)) 5718 } else if (!(quotes & QUOTES_KEEPNUL))
5706 continue; 5719 continue;
5707 USTPUTC(c, q); 5720 USTPUTC(c, q);
@@ -6435,7 +6448,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6435 char *idx, *end; 6448 char *idx, *end;
6436 6449
6437 if (!repl) { 6450 if (!repl) {
6438 if ((repl=strchr(str, CTLESC))) 6451 repl = strchr(str, CTLESC);
6452 if (repl)
6439 *repl++ = '\0'; 6453 *repl++ = '\0';
6440 else 6454 else
6441 repl = nullstr; 6455 repl = nullstr;
@@ -6976,6 +6990,70 @@ addfname(const char *name)
6976 exparg.lastp = &sp->next; 6990 exparg.lastp = &sp->next;
6977} 6991}
6978 6992
6993/* If we want to use glob() from libc... */
6994#if 1
6995
6996/* Add the result of glob() to the list */
6997static void
6998addglob(const glob_t *pglob)
6999{
7000 char **p = pglob->gl_pathv;
7001
7002 do {
7003 addfname(*p);
7004 } while (*++p);
7005}
7006static void
7007expandmeta(struct strlist *str /*, int flag*/)
7008{
7009 /* TODO - EXP_REDIR */
7010
7011 while (str) {
7012 char *p;
7013 glob_t pglob;
7014 int i;
7015
7016 if (fflag)
7017 goto nometa;
7018 INT_OFF;
7019 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7020 /*
7021 * GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7022 * TODO?: GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7023 */
7024 i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7025 if (p != str->text)
7026 free(p);
7027 switch (i) {
7028 case 0:
7029 /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7030 if (!(pglob.gl_flags & GLOB_MAGCHAR))
7031 goto nometa2;
7032 addglob(&pglob);
7033 globfree(&pglob);
7034 INT_ON;
7035 break;
7036 case GLOB_NOMATCH:
7037nometa2:
7038 globfree(&pglob);
7039 INT_ON;
7040nometa:
7041 *exparg.lastp = str;
7042 rmescapes(str->text, 0);
7043 exparg.lastp = &str->next;
7044 break;
7045 default: /* GLOB_NOSPACE */
7046 globfree(&pglob);
7047 INT_ON;
7048 ash_msg_and_raise_error(bb_msg_memory_exhausted);
7049 }
7050 str = str->next;
7051 }
7052}
7053
7054#else
7055/* Homegrown globbing code. (dash also has both, uses homegrown one.) */
7056
6979/* 7057/*
6980 * Do metacharacter (i.e. *, ?, [...]) expansion. 7058 * Do metacharacter (i.e. *, ?, [...]) expansion.
6981 */ 7059 */
@@ -7179,7 +7257,8 @@ expandmeta(struct strlist *str /*, int flag*/)
7179 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP); 7257 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7180 { 7258 {
7181 int i = strlen(str->text); 7259 int i = strlen(str->text);
7182 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ 7260//BUGGY estimation of how long expanded name can be
7261 expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7183 } 7262 }
7184 expmeta(expdir, expdir, p); 7263 expmeta(expdir, expdir, p);
7185 free(expdir); 7264 free(expdir);
@@ -7204,6 +7283,7 @@ expandmeta(struct strlist *str /*, int flag*/)
7204 str = str->next; 7283 str = str->next;
7205 } 7284 }
7206} 7285}
7286#endif /* our globbing code */
7207 7287
7208/* 7288/*
7209 * Perform variable substitution and command substitution on an argument, 7289 * Perform variable substitution and command substitution on an argument,