From d7b5289209131ae94b540b35f0f147d2302ec0c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 9 Apr 2010 14:58:40 +0200 Subject: [PATCH] xargs: do not decrease orig_arg_max to negative values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on patch by Nguyễn Thái Ngọc Duy Signed-off-by: Denys Vlasenko --- findutils/xargs.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/findutils/xargs.c b/findutils/xargs.c index f5dbc7825..3785f1ec0 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -25,10 +25,10 @@ /* COMPAT: SYSV version defaults size (and has a max value of) to 470. We try to make it as large as possible. */ #if !defined(ARG_MAX) && defined(_SC_ARG_MAX) -#define ARG_MAX sysconf (_SC_ARG_MAX) +# define ARG_MAX sysconf(_SC_ARG_MAX) #endif -#ifndef ARG_MAX -#define ARG_MAX 470 +#if !defined(ARG_MAX) +# define ARG_MAX 470 #endif @@ -378,8 +378,6 @@ int xargs_main(int argc, char **argv) int child_error = 0; char *max_args, *max_chars; int n_max_arg; - size_t n_chars = 0; - long orig_arg_max; const char *eof_str = NULL; unsigned opt; size_t n_max_chars; @@ -408,28 +406,35 @@ int xargs_main(int argc, char **argv) argc++; } - orig_arg_max = ARG_MAX; - if (orig_arg_max == -1) - orig_arg_max = LONG_MAX; - orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048 */ + n_max_chars = ARG_MAX; /* might be calling sysconf(_SC_ARG_MAX) */ + if (n_max_chars < 4*1024); /* paranoia */ + n_max_chars = LONG_MAX; + /* The Open Group Base Specifications Issue 6: + * "The xargs utility shall limit the command line length such that + * when the command line is invoked, the combined argument + * and environment lists (see the exec family of functions + * in the System Interfaces volume of IEEE Std 1003.1-2001) + * shall not exceed {ARG_MAX}-2048 bytes". + */ + n_max_chars -= 2048; + /* Sanity check for systems with huge ARG_MAX defines (e.g., Suns which + * have it at 1 meg). Things will work fine with a large ARG_MAX but it + * will probably hurt the system more than it needs to; an array of this + * size is allocated. + */ + if (n_max_chars > 20 * 1024) + n_max_chars = 20 * 1024; if (opt & OPT_UPTO_SIZE) { - n_max_chars = xatoul_range(max_chars, 1, orig_arg_max); + size_t n_chars = 0; + n_max_chars = xatoul_range(max_chars, 1, n_max_chars); for (i = 0; i < argc; i++) { n_chars += strlen(*argv) + 1; } - if (n_max_chars < n_chars) { + if (n_max_chars <= n_chars) { bb_error_msg_and_die("can't fit single argument within argument list size limit"); } n_max_chars -= n_chars; - } else { - /* Sanity check for systems with huge ARG_MAX defines (e.g., Suns which - have it at 1 meg). Things will work fine with a large ARG_MAX but it - will probably hurt the system more than it needs to; an array of this - size is allocated. */ - if (orig_arg_max > 20 * 1024) - orig_arg_max = 20 * 1024; - n_max_chars = orig_arg_max; } max_chars = xmalloc(n_max_chars); @@ -442,9 +447,9 @@ int xargs_main(int argc, char **argv) while ((list = read_args(list, eof_str, n_max_chars, max_chars)) != NULL || !(opt & OPT_NO_EMPTY)) { + size_t n_chars = 0; opt |= OPT_NO_EMPTY; n = 0; - n_chars = 0; #if ENABLE_FEATURE_XARGS_SUPPORT_TERMOPT for (cur = list; cur;) { n_chars += cur->length;