From 2086cc583c11cb919710c688a0f8e9c26731bd0f Mon Sep 17 00:00:00 2001 From: Manoj Srivastava Date: Sun, 4 May 2014 17:08:48 -0700 Subject: [PATCH 09/11] [handle_excessive_command_length]: Patch to fix large cmmand line When presented with a very very long command line (e.g. WebKit's linking of libWebCore.la in current git), make fails to execute the command as it doesn't split the command line to fit within the limits. This patch provides a POSIX specific fix. Signed-off-by: Manoj Srivastava --- configure.ac | 3 ++- job.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 7490b4d..404c7ae 100644 --- a/configure.ac +++ b/configure.ac @@ -62,7 +62,8 @@ AC_HEADER_DIRENT AC_HEADER_STAT AC_HEADER_TIME AC_CHECK_HEADERS([stdlib.h locale.h unistd.h limits.h fcntl.h string.h \ - memory.h sys/param.h sys/resource.h sys/time.h sys/timeb.h]) + memory.h sys/param.h sys/resource.h sys/time.h sys/timeb.h \ + sys/user.h linux/binfmts.h]) AM_PROG_CC_C_O AC_C_CONST diff --git a/job.c b/job.c index 7b061a6..63a6253 100644 --- a/job.c +++ b/job.c @@ -27,6 +27,14 @@ this program. If not, see . */ #include +#if defined (HAVE_LINUX_BINFMTS_H) && defined (HAVE_SYS_USER_H) +#include +#include +#endif +#ifndef PAGE_SIZE +# define PAGE_SIZE (sysconf(_SC_PAGESIZE)) +#endif + /* Default shell to use. */ #ifdef WINDOWS32 #include @@ -3067,6 +3075,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell, #ifdef WINDOWS32 char *command_ptr = NULL; /* used for batch_mode_shell mode */ #endif + char *args_ptr; # ifdef __EMX__ /* is this necessary? */ if (!unixy_shell && shellflags) @@ -3232,8 +3241,17 @@ construct_command_argv_internal (char *line, char **restp, char *shell, return new_argv; } +#ifdef MAX_ARG_STRLEN + static char eval_line[] = "eval\\ \\\"set\\ x\\;\\ shift\\;\\ "; +#define ARG_NUMBER_DIGITS 5 +#define EVAL_LEN (sizeof(eval_line)-1 + shell_len + 4 \ + + (7 + ARG_NUMBER_DIGITS) * 2 * line_len / (MAX_ARG_STRLEN - 2)) +#else +#define EVAL_LEN 0 +#endif + new_line = xmalloc ((shell_len*2) + 1 + sflags_len + 1 - + (line_len*2) + 1); + + (line_len*2) + 1 + EVAL_LEN); ap = new_line; /* Copy SHELL, escaping any characters special to the shell. If we don't escape them, construct_command_argv_internal will @@ -3253,6 +3271,30 @@ construct_command_argv_internal (char *line, char **restp, char *shell, #ifdef WINDOWS32 command_ptr = ap; #endif + +#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN) + if (unixy_shell && line_len > MAX_ARG_STRLEN) + { + unsigned j; + memcpy (ap, eval_line, sizeof (eval_line) - 1); + ap += sizeof (eval_line) - 1; + for (j = 1; j <= 2 * line_len / (MAX_ARG_STRLEN - 2); j++) + ap += sprintf (ap, "\\$\\{%u\\}", j); + *ap++ = '\\'; + *ap++ = '"'; + *ap++ = ' '; + /* Copy only the first word of SHELL to $0. */ + for (p = shell; *p != '\0'; ++p) + { + if (isspace ((unsigned char)*p)) + break; + *ap++ = *p; + } + *ap++ = ' '; + } +#endif + args_ptr = ap; + for (p = line; *p != '\0'; ++p) { if (restp != NULL && *p == '\n') @@ -3300,6 +3342,13 @@ construct_command_argv_internal (char *line, char **restp, char *shell, } #endif *ap++ = *p; +#if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN) + if (unixy_shell && line_len > MAX_ARG_STRLEN && (ap - args_ptr > MAX_ARG_STRLEN - 2)) + { + *ap++ = ' '; + args_ptr = ap; + } +#endif } if (ap == new_line + shell_len + sflags_len + 2) { -- 2.0.0