prevent writing outside of the provided workspace when calculating a
authorRussell Bryant <russell@russellbryant.com>
Sun, 22 Jan 2006 02:10:19 +0000 (02:10 +0000)
committerRussell Bryant <russell@russellbryant.com>
Sun, 22 Jan 2006 02:10:19 +0000 (02:10 +0000)
substring (issue #6271)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@8421 65c4cc65-6c06-0410-ace0-fbb531ad65f3

pbx.c

diff --git a/pbx.c b/pbx.c
index 3e77042..76ce0e3 100644 (file)
--- a/pbx.c
+++ b/pbx.c
@@ -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;