From b5418f51344d7032d10ee641bf41d1f486b4e6e5 Mon Sep 17 00:00:00 2001 From: Garance A Drosehn Date: Wed, 13 Jul 2005 15:56:30 +0000 Subject: [PATCH] Fix two minor parsing bugs in -S processing: 1) An unquoted space is always a separator, even when not "in_arg". 2) When a new destination buffer must be allocated during variable substitution, only copy data from the active buffer to the new one when we *are* "in_arg". These were noticed when testing variable-substitution of variables which have null values, and are not inside quoted strings... MFC plans: after a few days, and re@ approval... --- usr.bin/env/envopts.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/usr.bin/env/envopts.c b/usr.bin/env/envopts.c index cf85b1fe19e..c62da6d48b5 100644 --- a/usr.bin/env/envopts.c +++ b/usr.bin/env/envopts.c @@ -44,8 +44,8 @@ __FBSDID("$FreeBSD$"); #include "envopts.h" static const char * - expand_vars(char **thisarg_p, char **dest_p, const char - **src_p); + expand_vars(int in_thisarg, char **thisarg_p, char **dest_p, + const char **src_p); static int is_there(char *candidate); /* @@ -222,8 +222,8 @@ split_spaces(const char *str, int *origind, int *origc, char ***origv) if (in_sq) copychar = *src; else { - copystr = expand_vars((nextarg - 1), &dest, - &src); + copystr = expand_vars(in_arg, (nextarg - 1), + &dest, &src); } break; case '\'': @@ -315,7 +315,7 @@ split_spaces(const char *str, int *origind, int *origc, char ***origv) default: if ((in_dq || in_sq) && in_arg) copychar = *src; - else if (in_arg && isspacech(*src)) + else if (isspacech(*src)) found_sep = 1; else { /* @@ -386,7 +386,7 @@ str_done: * possibly *thisarg_p in the calling routine. */ static const char * -expand_vars(char **thisarg_p, char **dest_p, const char **src_p) +expand_vars(int in_thisarg, char **thisarg_p, char **dest_p, const char **src_p) { const char *vbegin, *vend, *vvalue; char *newstr, *vname; @@ -441,15 +441,24 @@ expand_vars(char **thisarg_p, char **dest_p, const char **src_p) /* * The value is longer than the string it replaces, which means the * present destination area is too small to hold it. Create a new - * destination area, copy the present 'thisarg' value to it, and - * update the caller's 'thisarg' and 'dest' variables to match. - * Note that it is still the caller which will copy vvalue to *dest. + * destination area, and update the caller's 'dest' variable to match. + * If the caller has already started copying some info for 'thisarg' + * into the present destination, then the new destination area must + * include a copy of that data, and the pointer to 'thisarg' must also + * be updated. Note that it is still the caller which copies this + * vvalue to the new *dest. */ - **dest_p = '\0'; /* Provide terminator for 'thisarg' */ - newlen = strlen(*thisarg_p) + strlen(vvalue) + strlen(*src_p) + 1; - newstr = malloc(newlen); - strcpy(newstr, *thisarg_p); - *thisarg_p = newstr; + newlen = strlen(vvalue) + strlen(*src_p) + 1; + if (in_thisarg) { + **dest_p = '\0'; /* Provide terminator for 'thisarg' */ + newlen += strlen(*thisarg_p); + newstr = malloc(newlen); + strcpy(newstr, *thisarg_p); + *thisarg_p = newstr; + } else { + newstr = malloc(newlen); + *newstr = '\0'; + } *dest_p = strchr(newstr, '\0'); return (vvalue); }