diff --git a/pgrep.c b/pgrep.c index 86b7be2d..01563db0 100644 --- a/pgrep.c +++ b/pgrep.c @@ -42,8 +42,6 @@ #define EXIT_FATAL 3 #define XALLOC_EXIT_CODE EXIT_FATAL -#define CMDSTRSIZE 4096 - #include "c.h" #include "fileutils.h" #include "nsutils.h" @@ -499,9 +497,10 @@ static struct el * select_procs (int *num) regex_t *preg; pid_t myself = getpid(); struct el *list = NULL; - char cmdline[CMDSTRSIZE] = ""; - char cmdsearch[CMDSTRSIZE] = ""; - char cmdoutput[CMDSTRSIZE] = ""; + long cmdlen = sysconf(_SC_ARG_MAX) * sizeof(char); + char *cmdline = xmalloc(cmdlen); + char *cmdsearch = xmalloc(cmdlen); + char *cmdoutput = xmalloc(cmdlen); proc_t ns_task; ptp = do_openproc(); @@ -563,7 +562,7 @@ static struct el * select_procs (int *num) if (task.cmdline && (opt_longlong || opt_full) ) { int i = 0; - int bytes = sizeof (cmdline); + long bytes = cmdlen; char *str = cmdline; /* make sure it is always NUL-terminated */ @@ -586,18 +585,18 @@ static struct el * select_procs (int *num) if (opt_long || opt_longlong || (match && opt_pattern)) { if (opt_longlong && task.cmdline) - strncpy (cmdoutput, cmdline, sizeof cmdoutput - 1); + strncpy (cmdoutput, cmdline, cmdlen - 1); else - strncpy (cmdoutput, task.cmd, sizeof cmdoutput - 1); - cmdoutput[sizeof cmdoutput - 1] = '\0'; + strncpy (cmdoutput, task.cmd, cmdlen - 1); + cmdoutput[cmdlen - 1] = '\0'; } if (match && opt_pattern) { if (opt_full && task.cmdline) - strncpy (cmdsearch, cmdline, sizeof cmdsearch - 1); + strncpy (cmdsearch, cmdline, cmdlen - 1); else - strncpy (cmdsearch, task.cmd, sizeof cmdsearch - 1); - cmdsearch[sizeof cmdsearch - 1] = '\0'; + strncpy (cmdsearch, task.cmd, cmdlen - 1); + cmdsearch[cmdlen - 1] = '\0'; if (regexec (preg, cmdsearch, 0, NULL, 0) != 0) match = 0; @@ -661,6 +660,10 @@ static struct el * select_procs (int *num) closeproc (ptp); *num = matches; + free(cmdline); + free(cmdsearch); + free(cmdoutput); + return list; } diff --git a/testsuite/config/unix.exp b/testsuite/config/unix.exp index bbee2333..61a329ed 100644 --- a/testsuite/config/unix.exp +++ b/testsuite/config/unix.exp @@ -118,7 +118,7 @@ proc expect_table_dsc { test match_header match_item } { } proc make_testproc { } { - global testproc_path testproc_comm testproc1_pid testproc2_pid topdir + global testproc_path testproc_comm testproc_arg_str testproc1_pid testproc2_pid topdir set testproc_realpath "${topdir}/lib/test_process" set testproc_comm "spcorp" @@ -133,8 +133,19 @@ proc make_testproc { } { eof { perror "test proc does not link to test process" } } - - set testproc1_pid [ exec $testproc_path & ] + # make a process with the argument set to a fraction of ARG_MAX length + # but small enough we do not run TCL out of memory for regular expressions + # nor do we get argument list too long (104857 was found to work on Ubuntu 18.04) + set max_arg_len [ expr min([ exec /usr/bin/getconf ARG_MAX ], 104857) ] + # ensure we have enough slack to launch the test prog and pgrep + set reserved_space [expr max([ string length $testproc_path ], [ string length $topdir ] + 10)] + set testproc_arg_str "a" + set i $reserved_space + while {$i<$max_arg_len} { + incr i + append testproc_arg_str "a" + } + set testproc1_pid [ exec $testproc_path $testproc_arg_str & ] set testproc2_pid [ exec $testproc_path & ] } diff --git a/testsuite/pgrep.test/pgrep.exp b/testsuite/pgrep.test/pgrep.exp index 9f935e60..c7fae1a4 100644 --- a/testsuite/pgrep.test/pgrep.exp +++ b/testsuite/pgrep.test/pgrep.exp @@ -34,9 +34,9 @@ set test "pgrep with : delimiter" spawn $pgrep -d : $testproc_comm expect_pass "$test" "^${testproc1_pid}:${testproc2_pid}\\s*$" -# FIXME - Need to test against -f flag set test "pgrep match against full process name" -untested $test +spawn $pgrep -f "$testproc_path\\s+$testproc_arg_str" +expect_pass "$test" "^$testproc1_pid\\s*$" set test "pgrep with matching gid" spawn $pgrep -G $gid $testproc_comm @@ -51,8 +51,8 @@ spawn $pgrep -l $testproc_comm expect_pass "$test" "^$testproc1_pid\\s+$testproc_comm\\s+$testproc2_pid\\s+$testproc_comm\\s*$" set test "pgrep with full command line" -spawn $pgrep -a $testproc_comm -expect_pass "$test" "^$testproc1_pid\\s+$testproc_path\\s+$testproc2_pid\\s+$testproc_path\\s*$" +spawn $pgrep -af "$testproc_path$" +expect_pass "$test" "^$testproc2_pid\\s+$testproc_path\\s*$" set test "pgrep find newest test pid" spawn $pgrep -n $testproc_comm