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>
This commit is contained in:
parent
d8330ca4a4
commit
b3f29b452a
102
shell/ash.c
102
shell/ash.c
@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
|
#include <glob.h>
|
||||||
#include <sys/times.h>
|
#include <sys/times.h>
|
||||||
#include <sys/utsname.h> /* for setting $HOSTNAME */
|
#include <sys/utsname.h> /* for setting $HOSTNAME */
|
||||||
|
|
||||||
@ -2808,18 +2809,27 @@ enum {
|
|||||||
static int
|
static int
|
||||||
SIT(int c, int syntax)
|
SIT(int c, int syntax)
|
||||||
{
|
{
|
||||||
static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
|
/* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
|
||||||
|
static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
|
||||||
|
/*
|
||||||
|
* This causes '/' to be prepended with CTLESC in dquoted string,
|
||||||
|
* making "./file"* treated incorrectly because we feed
|
||||||
|
* ".\/file*" string to glob(), confusing it (see expandmeta func).
|
||||||
|
* The "homegrown" glob implementation is okay with that,
|
||||||
|
* but glibc one isn't. With '/' always treated as CWORD,
|
||||||
|
* both work fine.
|
||||||
|
*/
|
||||||
# if ENABLE_ASH_ALIAS
|
# if ENABLE_ASH_ALIAS
|
||||||
static const uint8_t syntax_index_table[] ALIGN1 = {
|
static const uint8_t syntax_index_table[] ALIGN1 = {
|
||||||
1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
|
1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
|
||||||
7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
|
7, 8, 3, 3,/*3,*/3, 1, 1, /* "()*-/:;<" */
|
||||||
3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
|
3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
|
||||||
11, 3 /* "}~" */
|
11, 3 /* "}~" */
|
||||||
};
|
};
|
||||||
# else
|
# else
|
||||||
static const uint8_t syntax_index_table[] ALIGN1 = {
|
static const uint8_t syntax_index_table[] ALIGN1 = {
|
||||||
0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
|
0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
|
||||||
6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
|
6, 7, 2, 2,/*2,*/2, 0, 0, /* "()*-/:;<" */
|
||||||
2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
|
2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
|
||||||
10, 2 /* "}~" */
|
10, 2 /* "}~" */
|
||||||
};
|
};
|
||||||
@ -2901,7 +2911,8 @@ static const uint8_t syntax_index_table[] ALIGN1 = {
|
|||||||
/* 44 "," */ CWORD_CWORD_CWORD_CWORD,
|
/* 44 "," */ CWORD_CWORD_CWORD_CWORD,
|
||||||
/* 45 "-" */ CWORD_CCTL_CCTL_CWORD,
|
/* 45 "-" */ CWORD_CCTL_CCTL_CWORD,
|
||||||
/* 46 "." */ CWORD_CWORD_CWORD_CWORD,
|
/* 46 "." */ CWORD_CWORD_CWORD_CWORD,
|
||||||
/* 47 "/" */ CWORD_CCTL_CCTL_CWORD,
|
/* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
|
||||||
|
/* 47 "/" */ CWORD_CWORD_CWORD_CWORD,
|
||||||
/* 48 "0" */ CWORD_CWORD_CWORD_CWORD,
|
/* 48 "0" */ CWORD_CWORD_CWORD_CWORD,
|
||||||
/* 49 "1" */ CWORD_CWORD_CWORD_CWORD,
|
/* 49 "1" */ CWORD_CWORD_CWORD_CWORD,
|
||||||
/* 50 "2" */ CWORD_CWORD_CWORD_CWORD,
|
/* 50 "2" */ CWORD_CWORD_CWORD_CWORD,
|
||||||
@ -5633,7 +5644,6 @@ rmescapes(char *str, int flag)
|
|||||||
while (*p) {
|
while (*p) {
|
||||||
if ((unsigned char)*p == CTLQUOTEMARK) {
|
if ((unsigned char)*p == CTLQUOTEMARK) {
|
||||||
// Note: both inquotes and protect_against_glob only affect whether
|
// Note: both inquotes and protect_against_glob only affect whether
|
||||||
// CTLESC,<ch> gets converted to <ch> or to \<ch>
|
|
||||||
inquotes = ~inquotes;
|
inquotes = ~inquotes;
|
||||||
p++;
|
p++;
|
||||||
protect_against_glob = globbing;
|
protect_against_glob = globbing;
|
||||||
@ -5697,11 +5707,14 @@ memtodest(const char *p, size_t len, int syntax, int quotes)
|
|||||||
unsigned char c = *p++;
|
unsigned char c = *p++;
|
||||||
if (c) {
|
if (c) {
|
||||||
int n = SIT(c, syntax);
|
int n = SIT(c, syntax);
|
||||||
if ((quotes & QUOTES_ESC) &&
|
if ((quotes & QUOTES_ESC)
|
||||||
((n == CCTL) ||
|
&& ((n == CCTL)
|
||||||
(((quotes & EXP_FULL) || syntax != BASESYNTAX) &&
|
|| (((quotes & EXP_FULL) || syntax != BASESYNTAX)
|
||||||
n == CBACK)))
|
&& n == CBACK)
|
||||||
|
)
|
||||||
|
) {
|
||||||
USTPUTC(CTLESC, q);
|
USTPUTC(CTLESC, q);
|
||||||
|
}
|
||||||
} else if (!(quotes & QUOTES_KEEPNUL))
|
} else if (!(quotes & QUOTES_KEEPNUL))
|
||||||
continue;
|
continue;
|
||||||
USTPUTC(c, q);
|
USTPUTC(c, q);
|
||||||
@ -6435,7 +6448,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
|
|||||||
char *idx, *end;
|
char *idx, *end;
|
||||||
|
|
||||||
if (!repl) {
|
if (!repl) {
|
||||||
if ((repl=strchr(str, CTLESC)))
|
repl = strchr(str, CTLESC);
|
||||||
|
if (repl)
|
||||||
*repl++ = '\0';
|
*repl++ = '\0';
|
||||||
else
|
else
|
||||||
repl = nullstr;
|
repl = nullstr;
|
||||||
@ -6976,6 +6990,70 @@ addfname(const char *name)
|
|||||||
exparg.lastp = &sp->next;
|
exparg.lastp = &sp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we want to use glob() from libc... */
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
/* Add the result of glob() to the list */
|
||||||
|
static void
|
||||||
|
addglob(const glob_t *pglob)
|
||||||
|
{
|
||||||
|
char **p = pglob->gl_pathv;
|
||||||
|
|
||||||
|
do {
|
||||||
|
addfname(*p);
|
||||||
|
} while (*++p);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
expandmeta(struct strlist *str /*, int flag*/)
|
||||||
|
{
|
||||||
|
/* TODO - EXP_REDIR */
|
||||||
|
|
||||||
|
while (str) {
|
||||||
|
char *p;
|
||||||
|
glob_t pglob;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (fflag)
|
||||||
|
goto nometa;
|
||||||
|
INT_OFF;
|
||||||
|
p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
|
||||||
|
/*
|
||||||
|
* GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
|
||||||
|
* TODO?: GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
|
||||||
|
*/
|
||||||
|
i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
|
||||||
|
if (p != str->text)
|
||||||
|
free(p);
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
/* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
|
||||||
|
if (!(pglob.gl_flags & GLOB_MAGCHAR))
|
||||||
|
goto nometa2;
|
||||||
|
addglob(&pglob);
|
||||||
|
globfree(&pglob);
|
||||||
|
INT_ON;
|
||||||
|
break;
|
||||||
|
case GLOB_NOMATCH:
|
||||||
|
nometa2:
|
||||||
|
globfree(&pglob);
|
||||||
|
INT_ON;
|
||||||
|
nometa:
|
||||||
|
*exparg.lastp = str;
|
||||||
|
rmescapes(str->text, 0);
|
||||||
|
exparg.lastp = &str->next;
|
||||||
|
break;
|
||||||
|
default: /* GLOB_NOSPACE */
|
||||||
|
globfree(&pglob);
|
||||||
|
INT_ON;
|
||||||
|
ash_msg_and_raise_error(bb_msg_memory_exhausted);
|
||||||
|
}
|
||||||
|
str = str->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* Homegrown globbing code. (dash also has both, uses homegrown one.) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do metacharacter (i.e. *, ?, [...]) expansion.
|
* Do metacharacter (i.e. *, ?, [...]) expansion.
|
||||||
*/
|
*/
|
||||||
@ -7179,7 +7257,8 @@ expandmeta(struct strlist *str /*, int flag*/)
|
|||||||
p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
|
p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
|
||||||
{
|
{
|
||||||
int i = strlen(str->text);
|
int i = strlen(str->text);
|
||||||
expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
|
//BUGGY estimation of how long expanded name can be
|
||||||
|
expdir = ckmalloc(i < 2048 ? 2048 : i+1);
|
||||||
}
|
}
|
||||||
expmeta(expdir, expdir, p);
|
expmeta(expdir, expdir, p);
|
||||||
free(expdir);
|
free(expdir);
|
||||||
@ -7204,6 +7283,7 @@ expandmeta(struct strlist *str /*, int flag*/)
|
|||||||
str = str->next;
|
str = str->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* our globbing code */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform variable substitution and command substitution on an argument,
|
* Perform variable substitution and command substitution on an argument,
|
||||||
|
Loading…
Reference in New Issue
Block a user