diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-01-22 02:10:19 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-01-22 02:10:19 +0000 |
commit | dca33b72edbf15ae4378b6bbf0e336ca83a1b2c7 (patch) | |
tree | 86fc167b9eb359628b0e9683dbc542dd57f62a64 /pbx.c | |
parent | 9c5234dd0080e67e494d3523ac593c5413939d97 (diff) |
prevent writing outside of the provided workspace when calculating a
substring (issue #6271)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@8421 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'pbx.c')
-rw-r--r-- | pbx.c | 49 |
1 files changed, 23 insertions, 26 deletions
@@ -846,41 +846,38 @@ static int parse_variable_name(char *var, int *offset, int *length, int *isfunc) return 0; } -/*! \brief takes a substring. It is ok to call with value == workspace. */ -static char *substring(char *value, int offset, int length, char *workspace, size_t workspace_len) +/*! \brief takes a substring. It is ok to call with value == workspace. + * + * offset < 0 means start from the end of the string and set the beginning + * to be that many characters back. + * length is the length of the substring, -1 means unlimited + * (we take any negative value). + * Always return a copy in workspace. + */ +static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len) { char *ret = workspace; + int lr; /* length of the input string after the copy */ - /* No need to do anything */ - if (offset == 0 && length==-1) { - return value; - } + ast_copy_string(workspace, value, workspace_len); /* always make a copy */ - ast_copy_string(workspace, value, workspace_len); + if (offset == 0 && length < 0) /* take the whole string */ + return ret; - if (abs(offset) > strlen(ret)) { /* Offset beyond string */ - if (offset >= 0) - offset = strlen(ret); - else - offset =- strlen(ret); - } + lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ - /* Detect too-long length */ - if ((offset < 0 && length > -offset) || (offset >= 0 && offset+length > strlen(ret))) { - if (offset >= 0) - length = strlen(ret)-offset; - else - length = strlen(ret)+offset; + if (offset < 0) { /* translate negative offset into positive ones */ + offset = lr + offset; + if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ + offset = 0; } - /* Bounce up to the right offset */ - if (offset >= 0) - ret += offset; - else - ret += strlen(ret)+offset; + /* too large offset result in empty string so we know what to return */ + if (offset >= lr) + return ret + lr; /* the final '\0' */ - /* Chop off at the requisite length */ - if (length >= 0) + ret += offset; /* move to the start position */ + if (length >= 0 && length < lr - offset) /* truncate if necessary */ ret[length] = '\0'; return ret; |