]> granicus.if.org Git - curl/commitdiff
urlglob fix to prevent crashing when -o path is longer than url
authorDaniel Stenberg <daniel@haxx.se>
Wed, 6 Dec 2000 10:10:31 +0000 (10:10 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 6 Dec 2000 10:10:31 +0000 (10:10 +0000)
src/main.c
src/urlglob.c
src/urlglob.h

index ba5bcf9255bca24178d276b2e4faac77d01ba82d..a7d474cacb431acf8fee9a6c2cd54ac89bee662c 100644 (file)
@@ -1500,7 +1500,7 @@ operate(struct Configurable *config, int argc, char *argv[])
       else {
        /* fill '#1' ... '#9' terms from URL pattern */
         char *outfile = config->outfile;
-        config->outfile = match_url(config->outfile, *urls);
+        config->outfile = match_url(config->outfile, urls);
         free(outfile);
       }
       
index 246e9234fa783f33d0d8f5880cc0f707ba60fed7..1f7d3fe00a98ca2c6b361ee61065c33b755d4f71 100644 (file)
 #include "../lib/memdebug.h"
 #endif
 
-char *glob_buffer;
-URLGlob *glob_expand;
+int glob_word(URLGlob *, char*, int);
 
-int glob_word(char*, int);
-
-int glob_set(char *pattern, int pos) {
+int glob_set(URLGlob *glob, char *pattern, int pos)
+{
   /* processes a set expression with the point behind the opening '{'
      ','-separated elements are collected until the next closing '}'
   */
-  char* buf = glob_buffer;
+  char* buf = glob->glob_buffer;
   URLPattern *pat;
 
-  pat = (URLPattern*)&glob_expand->pattern[glob_expand->size / 2];
+  pat = (URLPattern*)&glob->pattern[glob->size / 2];
   /* patterns 0,1,2,... correspond to size=1,3,5,... */
   pat->type = UPTSet;
   pat->content.Set.size = 0;
   pat->content.Set.ptr_s = 0;
   pat->content.Set.elements = (char**)malloc(0);
-  ++glob_expand->size;
+  ++glob->size;
 
   while (1) {
     switch (*pattern) {
@@ -81,19 +79,22 @@ int glob_set(char *pattern, int pos) {
     case ',':
     case '}':                          /* set element completed */
       *buf = '\0';
-      pat->content.Set.elements = realloc(pat->content.Set.elements, (pat->content.Set.size + 1) * sizeof(char*));
+      pat->content.Set.elements =
+        realloc(pat->content.Set.elements,
+                (pat->content.Set.size + 1) * sizeof(char*));
       if (!pat->content.Set.elements) {
        printf("out of memory in set pattern\n");
        exit(CURLE_OUT_OF_MEMORY);
       }
-      pat->content.Set.elements[pat->content.Set.size] = strdup(glob_buffer);
+      pat->content.Set.elements[pat->content.Set.size] =
+        strdup(glob->glob_buffer);
       ++pat->content.Set.size;
 
       if (*pattern == '}')             /* entire set pattern completed */
        /* always check for a literal (may be "") between patterns */
-       return pat->content.Set.size * glob_word(++pattern, ++pos);
+       return pat->content.Set.size * glob_word(glob, ++pattern, ++pos);
 
-      buf = glob_buffer;
+      buf = glob->glob_buffer;
       ++pattern;
       ++pos;
       break;
@@ -115,7 +116,8 @@ int glob_set(char *pattern, int pos) {
   exit (CURLE_FAILED_INIT);
 }
 
-int glob_range(char *pattern, int pos) {
+int glob_range(URLGlob *glob, char *pattern, int pos)
+{
   /* processes a range expression with the point behind the opening '['
      - char range: e.g. "a-z]", "B-Q]"
      - num range: e.g. "0-9]", "17-2000]"
@@ -125,9 +127,9 @@ int glob_range(char *pattern, int pos) {
   URLPattern *pat;
   char *c;
   
-  pat = (URLPattern*)&glob_expand->pattern[glob_expand->size / 2];
+  pat = (URLPattern*)&glob->pattern[glob->size / 2];
   /* patterns 0,1,2,... correspond to size=1,3,5,... */
-  ++glob_expand->size;
+  ++glob->size;
 
   if (isalpha((int)*pattern)) {                /* character range detected */
     pat->type = UPTCharRange;
@@ -141,7 +143,7 @@ int glob_range(char *pattern, int pos) {
     pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
     /* always check for a literal (may be "") between patterns */
     return (pat->content.CharRange.max_c - pat->content.CharRange.min_c + 1) *
-      glob_word(pattern + 4, pos + 4);
+      glob_word(glob, pattern + 4, pos + 4);
   }
   if (isdigit((int)*pattern)) {                /* numeric range detected */
     pat->type = UPTNumRange;
@@ -162,17 +164,18 @@ int glob_range(char *pattern, int pos) {
     c = (char*)(strchr(pattern, ']') + 1);     /* continue after next ']' */
     /* always check for a literal (may be "") between patterns */
     return (pat->content.NumRange.max_n - pat->content.NumRange.min_n + 1) *
-      glob_word(c, pos + (c - pattern));
+      glob_word(glob, c, pos + (c - pattern));
   }
   printf("error: illegal character in range specification at pos %d\n", pos);
   exit (CURLE_URL_MALFORMAT);
 }
 
-int glob_word(char *pattern, int pos) {
+int glob_word(URLGlob *glob, char *pattern, int pos)
+{
   /* processes a literal string component of a URL
      special characters '{' and '[' branch to set/range processing functions
    */ 
-  char* buf = glob_buffer;
+  char* buf = glob->glob_buffer;
   int litindex;
 
   while (*pattern != '\0' && *pattern != '{' && *pattern != '[') {
@@ -192,17 +195,17 @@ int glob_word(char *pattern, int pos) {
     ++pos;
   }
   *buf = '\0';
-  litindex = glob_expand->size / 2;
+  litindex = glob->size / 2;
   /* literals 0,1,2,... correspond to size=0,2,4,... */
-  glob_expand->literal[litindex] = strdup(glob_buffer);
-  ++glob_expand->size;
+  glob->literal[litindex] = strdup(glob->glob_buffer);
+  ++glob->size;
   if (*pattern == '\0')
     return 1;                          /* singular URL processed  */
   if (*pattern == '{') {
-    return glob_set(++pattern, ++pos); /* process set pattern */
+    return glob_set(glob, ++pattern, ++pos);   /* process set pattern */
   }
   if (*pattern == '[') {
-    return glob_range(++pattern, ++pos);/* process range pattern */
+    return glob_range(glob, ++pattern, ++pos);/* process range pattern */
   }
   printf("internal error\n");
   exit (CURLE_FAILED_INIT);
@@ -214,18 +217,26 @@ int glob_url(URLGlob** glob, char* url, int *urlnum)
    * We can deal with any-size, just make a buffer with the same length
    * as the specified URL!
    */
-  glob_buffer=(char *)malloc(strlen(url)+1);
+  URLGlob *glob_expand;
+  char *glob_buffer=(char *)malloc(strlen(url)+1);
   if(NULL == glob_buffer)
     return CURLE_OUT_OF_MEMORY;
 
   glob_expand = (URLGlob*)malloc(sizeof(URLGlob));
+  if(NULL == glob_expand) {
+    free(glob_buffer);
+    return CURLE_OUT_OF_MEMORY;
+  }
   glob_expand->size = 0;
-  *urlnum = glob_word(url, 1);
+  glob_expand->urllen = strlen(url);
+  glob_expand->glob_buffer = glob_buffer;
+  *urlnum = glob_word(glob_expand, url, 1);
   *glob = glob_expand;
   return CURLE_OK;
 }
 
-void glob_cleanup(URLGlob* glob) {
+void glob_cleanup(URLGlob* glob)
+{
   int i, elem;
 
   for (i = glob->size - 1; i >= 0; --i) {
@@ -240,14 +251,14 @@ void glob_cleanup(URLGlob* glob) {
       }
     }
   }
+  free(glob->glob_buffer);
   free(glob);
-  free(glob_buffer);
 }
 
 char *next_url(URLGlob *glob)
 {
   static int beenhere = 0;
-  char *buf = glob_buffer;
+  char *buf = glob->glob_buffer;
   URLPattern *pat;
   char *lit;
   signed int i;
@@ -318,48 +329,83 @@ char *next_url(URLGlob *glob)
     }
   }
   *buf = '\0';
-  return strdup(glob_buffer);
+  return strdup(glob->glob_buffer);
 }
 
-char *match_url(char *filename, URLGlob glob) {
-  char *buf = glob_buffer;
+char *match_url(char *filename, URLGlob *glob)
+{
+  char *target;
   URLPattern pat;
   int i;
+  int allocsize;
+  int stringlen=0;
+  char numbuf[18];
+  char *appendthis;
+  size_t appendlen;
+
+  /* We cannot use the glob_buffer for storage here since the filename may
+   * be longer than the URL we use. We allocate a good start size, then
+   * we need to realloc in case of need.
+   */
+  allocsize=strlen(filename);
+  target = malloc(allocsize);
+  if(NULL == target)
+    return NULL; /* major failure */
 
   while (*filename != '\0') {
     if (*filename == '#') {
       if (!isdigit((int)*++filename) ||
          *filename == '0') {           /* only '#1' ... '#9' allowed */
-       printf("illegal matching expression\n");
-       exit(CURLE_URL_MALFORMAT);
+       /* printf("illegal matching expression\n");
+           exit(CURLE_URL_MALFORMAT);*/
+        continue;
       }
       i = *filename - '1';
-      if (i + 1 > glob.size / 2) {
-       printf("match against nonexisting pattern\n");
-       exit(CURLE_URL_MALFORMAT);
+      if (i + 1 > glob->size / 2) {
+       /*printf("match against nonexisting pattern\n");
+          exit(CURLE_URL_MALFORMAT);*/
+        continue;
       }
-      pat = glob.pattern[i];
+      pat = glob->pattern[i];
       switch (pat.type) {
       case UPTSet:
-       strcpy(buf, pat.content.Set.elements[pat.content.Set.ptr_s]);
-       buf += strlen(pat.content.Set.elements[pat.content.Set.ptr_s]);
+       appendthis = pat.content.Set.elements[pat.content.Set.ptr_s];
+       appendlen = strlen(pat.content.Set.elements[pat.content.Set.ptr_s]);
        break;
       case UPTCharRange:
-       *buf++ = pat.content.CharRange.ptr_c;
+        numbuf[0]=pat.content.CharRange.ptr_c;
+        numbuf[1]=0;
+        appendthis=numbuf;
+        appendlen=1;
        break;
       case UPTNumRange:
-       sprintf(buf, "%0*d", pat.content.NumRange.padlength, pat.content.NumRange.ptr_n);
-        buf += strlen(buf);
+       sprintf(numbuf, "%0*d", pat.content.NumRange.padlength, pat.content.NumRange.ptr_n);
+        appendthis = numbuf;
+        appendlen = strlen(numbuf);
        break;
       default:
        printf("internal error: invalid pattern type (%d)\n", pat.type);
-       exit (CURLE_FAILED_INIT);
+        return NULL;
       }
       ++filename;
     }
-    else
-      *buf++ = *filename++;
+    else {
+      appendthis=filename++;
+      appendlen=1;
+    }
+    if(appendlen + stringlen >= allocsize) {
+      char *newstr;
+      allocsize = (appendlen + stringlen)*2;
+      newstr=realloc(target, allocsize);
+      if(NULL ==newstr) {
+        free(target);
+        return NULL;
+      }
+      target=newstr;
+    }
+    memcpy(&target[stringlen], appendthis, appendlen);
+    stringlen += appendlen;
   }
-  *buf = '\0';
-  return strdup(glob_buffer);
+  target[stringlen]= '\0';
+  return target;
 }
index 4cb445106b2ca91589f59ce442540c714152190d..f7a7f5a850912ec84c6997092c93c5110750e1ab 100644 (file)
@@ -65,11 +65,13 @@ typedef struct {
   char* literal[10];
   URLPattern pattern[9];
   int size;
+  int urllen;
+  char *glob_buffer;
 } URLGlob;
 
 int glob_url(URLGlob**, char*, int *);
 char* next_url(URLGlob*);
-char* match_url(char*, URLGlob); 
+char* match_url(char*, URLGlob *); 
 void glob_cleanup(URLGlob* glob);
 
 #endif