diff options
Diffstat (limited to 'posix/wordexp.c')
-rw-r--r-- | posix/wordexp.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/posix/wordexp.c b/posix/wordexp.c index 0c89e02234..5e0e985006 100644 --- a/posix/wordexp.c +++ b/posix/wordexp.c @@ -1018,6 +1018,7 @@ parse_param (char **word, size_t *word_length, size_t *max_length, int colon_seen = 0; int depth = 0; int seen_hash = 0; + int free_value = 0; int error; for (; words[*offset]; ++(*offset)) @@ -1285,7 +1286,6 @@ envsubst: if (isdigit(*env)) { int n = *env - '0'; - char *param; free (env); if (n >= __libc_argc) @@ -1293,12 +1293,8 @@ envsubst: return 0; /* Replace with the appropriate positional parameter */ - param = __strdup (__libc_argv[n]); - if (!param) - return WRDE_NOSPACE; - - *word = w_addstr (*word, word_length, max_length, param); - return *word ? 0 : WRDE_NOSPACE; + value = __libc_argv[n]; + goto maybe_fieldsplit; } /* Is it `$$' ? */ else if (*env == '$') @@ -1347,6 +1343,7 @@ envsubst: } } + free_value = 1; if (value) goto maybe_fieldsplit; @@ -1666,31 +1663,42 @@ envsubst: return *word ? 0 : WRDE_NOSPACE; } - maybe_fieldsplit: if (quoted || !pwordexp) { /* Quoted - no field split */ *word = w_addstr (*word, word_length, max_length, value); + if (free_value) + free (value); + return *word ? 0 : WRDE_NOSPACE; } else { /* Need to field-split */ - char *field_begin = value; + char *value_copy = __strdup (value); /* Don't modify value */ + char *field_begin = value_copy; int seen_nonws_ifs = 0; + if (free_value) + free (value); + + if (value_copy == NULL) + return WRDE_NOSPACE; + do { char *field_end = field_begin; char *next_field; - char ch; /* If this isn't the first field, start a new word */ - if (field_begin != value) + if (field_begin != value_copy) { if (w_addword (pwordexp, *word) == WRDE_NOSPACE) - return WRDE_NOSPACE; + { + free (value_copy); + return WRDE_NOSPACE; + } *word = NULL; *word_length = *max_length = 0; @@ -1710,8 +1718,7 @@ envsubst: field_end++; /* Set up pointer to the character after end of field */ - ch = *field_end; - next_field = ch ? field_end : NULL; + next_field = *field_end ? field_end : NULL; /* Skip whitespace IFS after the field */ while (next_field && *next_field && strchr (ifs_white, *next_field)) @@ -1729,13 +1736,19 @@ envsubst: *field_end = 0; /* Tag a copy onto the current word */ - *word = w_addstr (*word, word_length, max_length, - __strdup (field_begin)); + *word = w_addstr (*word, word_length, max_length, field_begin); + if (*word == NULL) - return WRDE_NOSPACE; + { + free (value_copy); + return WRDE_NOSPACE; + } field_begin = next_field; - } while (seen_nonws_ifs || (field_begin && *field_begin)); + } + while (seen_nonws_ifs || (field_begin != NULL && *field_begin)); + + free (value_copy); } return 0; |