From 51c505fd1a7488d62088d5268ae1f8a5bc885b19 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 22 May 2008 10:21:48 +0000 Subject: [PATCH] Factor out common code for writing ls shell command. Rework its length checking so it doesn't rely on the return value of sprintf(), for the benefit of SunOS 4. --- ChangeLog | 7 +++++++ uip/whatnowsbr.c | 59 ++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index a3eff81..33485f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-05-22 Peter Maydell + + * uip/whatnowsbr.c: factor out common code for writing ls + shell command, and make it do more sensible buffer length + checks. Also avoid relying on the return value of sprintf(), + as some old systems don't return number of characters written. + 2008-05-21 Peter Maydell * sbr/utils.c (mh_xrealloc): don't assume realloc() can diff --git a/uip/whatnowsbr.c b/uip/whatnowsbr.c index 0a959db..72e9d1f 100644 --- a/uip/whatnowsbr.c +++ b/uip/whatnowsbr.c @@ -120,6 +120,7 @@ static int buildfile (char **, char *); static int check_draft (char *); static int whomfile (char **, char *); static int removefile (char *); +static void writelscmd(char *, int, char *, char **); #ifdef HAVE_LSTAT static int copyf (char *, char *); @@ -353,17 +354,7 @@ WhatNow (int argc, char **argv) * Use the user's shell so that we can take advantage of any * syntax that the user is accustomed to. */ - - cp = buf + sprintf(buf, "$SHELL -c \" cd %s;ls", cwd); - - while (*++argp != (char *)0) { - if (cp + strlen(*argp) + 2 >= buf + BUFSIZ) - adios((char *)0, "arguments too long"); - - cp += sprintf(cp, " %s", *argp); - } - - (void)strcat(cp, "\""); + writelscmd(buf, sizeof(buf), cwd, argp); (void)system(buf); break; @@ -423,17 +414,7 @@ WhatNow (int argc, char **argv) * Build a command line that causes the user's shell to list the file name * arguments. This handles and wildcard expansion, tilde expansion, etc. */ - - cp = buf + sprintf(buf, "$SHELL -c \" cd %s;ls", cwd); - - while (*++argp != (char *)0) { - if (cp + strlen(*argp) + 3 >= buf + BUFSIZ) - adios((char *)0, "arguments too long"); - - cp += sprintf(cp, " %s", *argp); - } - - (void)strcat(cp, "\""); + writelscmd(buf, sizeof(buf), cwd, argp); /* * Read back the response from the shell, which contains a number of lines @@ -560,6 +541,40 @@ WhatNow (int argc, char **argv) /*NOTREACHED*/ } + +/* + * Build a command line that causes the user's shell to list the file name + * arguments. This handles and wildcard expansion, tilde expansion, etc. + */ +static void +writelscmd(char *buf, int bufsz, char *cwd, char **argp) +{ + char *cp; + int ln = snprintf(buf, bufsz, "$SHELL -c \" cd %s;ls", cwd); + /* NB that some snprintf() return -1 on overflow rather than the + * new C99 mandated 'number of chars that would have been written' + */ + /* length checks here and inside the loop allow for the + * trailing " and NUL + */ + if (ln < 0 || ln + 2 > bufsz) + adios((char *)0, "arguments too long"); + + cp = buf + ln; + + while (*++argp != (char *)0) { + ln = strlen(*argp); + /* +3 for leading space and trailing quote and NUL */ + if (ln + 3 > bufsz - (cp-buf)) + adios((char *)0, "arguments too long"); + *cp++ = ' '; + memcpy(cp, *argp, ln+1); + cp += ln; + } + *cp++ = '"'; + *cp = 0; +} + /* * EDIT */ -- 1.7.10.4