aboutsummaryrefslogtreecommitdiff
path: root/toys/posix
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2017-09-20 13:53:23 -0700
committerRob Landley <rob@landley.net>2017-10-01 16:55:06 -0500
commitb89af5ed5c95ebe0466830d90eedd430593a3584 (patch)
tree946632d0bceddb6209681b04480bc969d529589c /toys/posix
parentb542295cd8d906647e013056ab049323ce11e910 (diff)
downloadtoybox-b89af5ed5c95ebe0466830d90eedd430593a3584.tar.gz
Fix xargs to obey POSIX's ARG_MAX restrictions.
This avoids "xargs: exec echo: Argument list too long" errors in practice. find(1) needs to be fixed too, but that's a bit more complicated and a working xargs provides a workaround. Bug: http://b/65818597 Test: find /proc | strace -f -e execve ./toybox xargs echo > /dev/null
Diffstat (limited to 'toys/posix')
-rw-r--r--toys/posix/xargs.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/toys/posix/xargs.c b/toys/posix/xargs.c
index b4cb80a0..e7dd10b5 100644
--- a/toys/posix/xargs.c
+++ b/toys/posix/xargs.c
@@ -79,6 +79,8 @@ static char *handle_entries(char *data, char **entry)
if (!*s) break;
save = s;
+ TT.bytes += sizeof(char *);
+
for (;;) {
if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save;
if (!*s || isspace(*s)) break;
@@ -95,7 +97,7 @@ static char *handle_entries(char *data, char **entry)
// -0 support
} else {
- TT.bytes += strlen(data)+1;
+ TT.bytes += sizeof(char *)+strlen(data)+1;
if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data;
if (TT.max_entries && TT.entries >= TT.max_entries)
return (char *)1;
@@ -112,6 +114,16 @@ void xargs_main(void)
int entries, bytes, done = 0, status;
char *data = NULL, **out;
pid_t pid;
+ long posix_max_bytes;
+
+ // POSIX requires that we never hit the ARG_MAX limit, even if we try to
+ // with -s. POSIX also says we have to reserve 2048 bytes "to guarantee
+ // that the invoked utility has room to modify its environment variables
+ // and command line arguments and still be able to invoke another utility",
+ // though obviously that's not really something you can guarantee.
+ posix_max_bytes = sysconf(_SC_ARG_MAX) - environ_bytes() - 2048;
+ if (TT.max_bytes == 0 || TT.max_bytes > posix_max_bytes)
+ TT.max_bytes = posix_max_bytes;
if (!(toys.optflags & FLAG_0)) TT.delim = '\n';