xargs: fix handling of quoted arguments, closes 11441
As reported in bug 11441 when presented with a large number of quoted arguments xargs can return 'argument line too long': seq 10000 29999 | sed -e 's/^/"/' -e 's/$/"/' | busybox xargs echo This happens because the variant of process_stdin() which handles quoted arguments doesn't preserve state between calls. If the allowed number of characters is exceeded part way through a quoted argument the next call to process_stdin() incorrectly treats the terminating quote as a starting quote, thus quoting all of the argument separators. function old new delta process_stdin 274 303 +29 xargs_main 731 745 +14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 43/0) Total: 43 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
16bcd504a3
commit
1ff7002b1d
@ -114,17 +114,28 @@ struct globals {
|
|||||||
int max_procs;
|
int max_procs;
|
||||||
#endif
|
#endif
|
||||||
smalluint xargs_exitcode;
|
smalluint xargs_exitcode;
|
||||||
|
#if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES
|
||||||
|
#define NORM 0
|
||||||
|
#define QUOTE 1
|
||||||
|
#define BACKSLASH 2
|
||||||
|
#define SPACE 4
|
||||||
|
smalluint process_stdin__state;
|
||||||
|
char process_stdin__q;
|
||||||
|
#endif
|
||||||
} FIX_ALIASING;
|
} FIX_ALIASING;
|
||||||
#define G (*(struct globals*)bb_common_bufsiz1)
|
#define G (*(struct globals*)bb_common_bufsiz1)
|
||||||
#define INIT_G() do { \
|
#define INIT_G() do { \
|
||||||
setup_common_bufsiz(); \
|
setup_common_bufsiz(); \
|
||||||
G.eof_str = NULL; /* need to clear by hand because we are NOEXEC applet */ \
|
IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.repl_str = "{}";) \
|
||||||
|
IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\n';) \
|
||||||
|
/* Even zero values are set because we are NOEXEC applet */ \
|
||||||
|
G.eof_str = NULL; \
|
||||||
G.idx = 0; \
|
G.idx = 0; \
|
||||||
IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.running_procs = 0;) \
|
IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.running_procs = 0;) \
|
||||||
IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.max_procs = 1;) \
|
IF_FEATURE_XARGS_SUPPORT_PARALLEL(G.max_procs = 1;) \
|
||||||
G.xargs_exitcode = 0; \
|
G.xargs_exitcode = 0; \
|
||||||
IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.repl_str = "{}";) \
|
IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__state = NORM;) \
|
||||||
IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\n';) \
|
IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__q = '\0';) \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
@ -257,12 +268,8 @@ static void store_param(char *s)
|
|||||||
#if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES
|
#if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES
|
||||||
static char* FAST_FUNC process_stdin(int n_max_chars, int n_max_arg, char *buf)
|
static char* FAST_FUNC process_stdin(int n_max_chars, int n_max_arg, char *buf)
|
||||||
{
|
{
|
||||||
#define NORM 0
|
#define q G.process_stdin__q
|
||||||
#define QUOTE 1
|
#define state G.process_stdin__state
|
||||||
#define BACKSLASH 2
|
|
||||||
#define SPACE 4
|
|
||||||
char q = '\0'; /* quote char */
|
|
||||||
char state = NORM;
|
|
||||||
char *s = buf; /* start of the word */
|
char *s = buf; /* start of the word */
|
||||||
char *p = s + strlen(buf); /* end of the word */
|
char *p = s + strlen(buf); /* end of the word */
|
||||||
|
|
||||||
@ -339,6 +346,8 @@ static char* FAST_FUNC process_stdin(int n_max_chars, int n_max_arg, char *buf)
|
|||||||
/* store_param(NULL) - caller will do it */
|
/* store_param(NULL) - caller will do it */
|
||||||
dbg_msg("return:'%s'", s);
|
dbg_msg("return:'%s'", s);
|
||||||
return s;
|
return s;
|
||||||
|
#undef q
|
||||||
|
#undef state
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* The variant does not support single quotes, double quotes or backslash */
|
/* The variant does not support single quotes, double quotes or backslash */
|
||||||
|
@ -41,4 +41,13 @@ testing "xargs -sNUM test 2" \
|
|||||||
"echo 1 2 3 4 5 6 7 8 9 0\n""echo 1 2 3 4 5 6 7 8 9\n""echo 1 00\n" \
|
"echo 1 2 3 4 5 6 7 8 9 0\n""echo 1 2 3 4 5 6 7 8 9\n""echo 1 00\n" \
|
||||||
"" "2 3 4 5 6 7 8 9 0 2 3 4 5 6 7 8 9 00\n"
|
"" "2 3 4 5 6 7 8 9 0 2 3 4 5 6 7 8 9 00\n"
|
||||||
|
|
||||||
|
# see that we don't get "argument line too long",
|
||||||
|
# but do see the last word, 99999, instead
|
||||||
|
optional FEATURE_XARGS_SUPPORT_QUOTES
|
||||||
|
testing "xargs argument line too long" \
|
||||||
|
"seq 10000 99999 | sed -e 's/^/\"/' -e 's/$/\"/' | xargs echo | grep -o 99999; echo \$?" \
|
||||||
|
"99999\n0\n" \
|
||||||
|
"" ""
|
||||||
|
SKIP=
|
||||||
|
|
||||||
exit $FAILCOUNT
|
exit $FAILCOUNT
|
||||||
|
Loading…
Reference in New Issue
Block a user