]> granicus.if.org Git - apache/commitdiff
* server/util.c (ap_resolve_env): Rewrite to avoid buffer overflows.
authorJoe Orton <jorton@apache.org>
Wed, 15 Sep 2004 11:44:05 +0000 (11:44 +0000)
committerJoe Orton <jorton@apache.org>
Wed, 15 Sep 2004 11:44:05 +0000 (11:44 +0000)
Submitted by: Andr�� Malo
Reviewed by: jorton, mjc

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@105130 13f79535-47bb-0310-9956-ffa450edef68

server/util.c

index 231bc9adb9f524e578756d96bb2441497368e999..a7d0d51cde5af3ca4a51f5d389b3b1d434cf74cf 100644 (file)
@@ -722,7 +722,7 @@ static char *substring_conf(apr_pool_t *p, const char *start, int len,
 
     *resp++ = '\0';
 #if RESOLVE_ENV_PER_TOKEN
-    return ap_resolve_env(p,result);
+    return (char *)ap_resolve_env(p,result);
 #else
     return result;
 #endif
@@ -782,39 +782,87 @@ AP_DECLARE(char *) ap_getword_conf(apr_pool_t *p, const char **line)
  */
 AP_DECLARE(const char *) ap_resolve_env(apr_pool_t *p, const char * word)
 {
-       char tmp[ MAX_STRING_LEN ];
-       const char *s, *e;
-       tmp[0] = '\0';
-
-       if (!(s=ap_strchr_c(word,'$')))
-               return word;
-
-       do {
-               /* XXX - relies on strncat() to add '\0'
-                */
-               strncat(tmp,word,s - word);
-               if ((s[1] == '{') && (e=ap_strchr_c(s,'}'))) {
-                       const char *e2 = e;
-                       char *var;
-                       word = e + 1;
-                       var = apr_pstrndup(p, s+2, e2-(s+2));
-                       e = getenv(var);
-                       if (e) {
-                           strcat(tmp,e);
-                       } else {
-                           strncat(tmp, s, e2-s);
-                           strcat(tmp,"}");
-                       }
-               } else {
-                       /* ignore invalid strings */
-                       word = s+1;
-                       strcat(tmp,"$");
-               };
-       } while ((s=ap_strchr_c(word,'$')));
-       strcat(tmp,word);
-
-       return apr_pstrdup(p,tmp);
+# define SMALL_EXPANSION 5
+    struct sll {
+        struct sll *next;
+        const char *string;
+        apr_size_t len;
+    } *result, *current, sresult[SMALL_EXPANSION];
+    char *res_buf, *cp;
+    const char *s, *e, *ep;
+    unsigned spc;
+    apr_size_t outlen;
+
+    s = ap_strchr_c(word, '$');
+    if (!s) {
+        return word;
+    }
+
+    /* well, actually something to do */
+    ep = word + strlen(word);
+    spc = 0;
+    result = current = &(sresult[spc++]);
+    current->next = NULL;
+    current->string = word;
+    current->len = s - word;
+    outlen = current->len;
+
+    do {
+        /* prepare next entry */
+        if (current->len) {
+            current->next = (spc < SMALL_EXPANSION)
+                            ? &(sresult[spc++])
+                            : (struct sll *)apr_palloc(p,
+                                                       sizeof(*current->next));
+            current = current->next;
+            current->next = NULL;
+            current->len = 0;
+        }
+
+        if (*s == '$') {
+            if (s[1] == '{' && (e = ap_strchr_c(s, '}'))) {
+                word = getenv(apr_pstrndup(p, s+2, e-s-2));
+                if (word) {
+                    current->string = word;
+                    current->len = strlen(word);
+                    outlen += current->len;
+                }
+                else {
+                    current->string = s;
+                    current->len = e - s + 1;
+                    outlen += current->len;
+                }
+                s = e + 1;
+            }
+            else {
+                current->string = s++;
+                current->len = 1;
+                ++outlen;
+            }
+        }
+        else {
+            word = s;
+            s = ap_strchr_c(s, '$');
+            current->string = word;
+            current->len = s ? s - word : ep - word;
+            outlen += current->len;
+        }
+    } while (s && *s);
+
+    /* assemble result */
+    res_buf = cp = apr_palloc(p, outlen + 1);
+    do {
+        if (result->len) {
+            memcpy(cp, result->string, result->len);
+            cp += result->len;
+        }
+        result = result->next;
+    } while (result);
+    res_buf[outlen] = '\0';
+
+    return res_buf;
 }
+
 AP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp)
 {
 #ifdef DEBUG