[AD] config file patch

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Hi,

Annie was recently caught by some hardcoded limitations in the config
file functions, so she made this.

-vincent


Hi,

This patch removes buffer truncations in config.c

Four functions are modified:
 get_line: a config file line used to be truncated to 255 characters
 set_config: small modifications because get_line parameters have changed
(set_config calls get_line)
 get_config_argv: the config value used to be truncated to 255 characters
 get_config_text: the message used to be truncated to 255 characters

Potential incompatibilities:
 If client code relies on the fact that strings are truncated
 Functions can fail because the program is out of memory. In this case they
will behave as if the entry didn't exist in the config file (I hope)

Remarks:
 Config file names are still limited to 1024 bytes
 Section names are still limited to 256 bytes

How to apply the patch:
 Copy config.diff to your allegro directory
 cd to your allegro directory
 Type: patch -p1 < config.diff

Enjoy !

-- 
Annie

--- allegro_original/src/config.c	Mon Apr  1 12:33:06 2002
+++ allegro/src/config.c	Fri Oct 25 10:35:12 2002
@@ -247,10 +247,14 @@
 
 /* get_line: 
  *  Helper for splitting files up into individual lines.
+ *  Allocates *name and *val. If returned *name is NULL, either the line was
+ *  blank or a comment or there was a memory error. If returned *val is NULL
+ *  there was a memory error.
  */
-static int get_line(AL_CONST char *data, int length, char *name, int name_size, char *val, int val_size)
+static int get_line(AL_CONST char *data, int length, char **name, char **val)
 {
-   char buf[256], buf2[256];
+   char *buf;
+   int buf_size=256;
    int inpos, outpos, i, j;
    int c, c2, w0;
 
@@ -258,7 +262,14 @@
    outpos = 0;
    w0 = ucwidth(0);
 
-   while ((inpos<length) && (outpos<(int)sizeof(buf)-w0)) {
+   buf = malloc(buf_size);
+   if (!buf) {
+     *name = NULL;
+     *val = NULL;
+     return inpos;
+   }
+
+   while (inpos<length) {
       c = ugetc(data+inpos);
       if ((c == '\r') || (c == '\n')) {
 	 inpos += uwidth(data+inpos);
@@ -270,6 +281,13 @@
 	 break;
       }
 
+      if (outpos>=(int)buf_size-w0) {
+         char *tmp = realloc(buf, buf_size*2);
+         if (!tmp)
+            break;
+         buf_size *= 2;
+         buf = tmp;
+      }
       outpos += usetc(buf+outpos, c);
       inpos += uwidth(data+inpos);
    }
@@ -288,35 +306,41 @@
    /* read name string */
    j = 0;
 
+   /* Compute name length */
    while ((c) && (!uisspace(c)) && (c != '=') && (c != '#')) {
-      j += usetc(buf2+j, c);
+      j += ucwidth(c);
       i += uwidth(buf+i);
       c = ugetc(buf+i);
    }
 
    if (j) {
       /* got a variable */
-      usetc(buf2+j, 0);
-      ustrzcpy(name, name_size, buf2);
+      *name = malloc(j+w0);
+      if (*name) {
+        ustrzcpy(*name, j+w0, buf+i-j);
+      }
 
       while ((c) && ((uisspace(c)) || (c == '='))) {
 	 i += uwidth(buf+i);
 	 c = ugetc(buf+i);
       }
 
-      ustrzcpy(val, val_size, buf+i);
+      *val = ustrdup(buf+i);
 
-      /* strip trailing spaces */
-      i = ustrlen(val) - 1;
-      while ((i >= 0) && (uisspace(ugetat(val, i))))
-	 usetat(val, i--, 0);
+      if (*val) {
+         /* strip trailing spaces */
+         i = ustrlen(*val) - 1;
+         while ((i >= 0) && (uisspace(ugetat(*val, i))))
+            usetat(*val, i--, 0);
+      }
    }
    else {
       /* blank line or comment */
-      usetc(name, 0);
-      ustrzcpy(val, val_size, buf);
+      *name = NULL;
+      *val = ustrdup(buf);
    }
 
+   free(buf);
    return inpos;
 }
 
@@ -327,7 +351,6 @@
  */
 static void set_config(CONFIG **config, AL_CONST char *data, int length, AL_CONST char *filename)
 {
-   char name[256], val[256];
    CONFIG_ENTRY **prev, *p;
    int pos;
 
@@ -354,18 +377,16 @@
    pos = 0;
 
    while (pos < length) {
-      pos += get_line(data+pos, length-pos, name, sizeof(name), val, sizeof(val));
+      char *name;
+      char *val;
+      pos += get_line(data+pos, length-pos, &name, &val);
 
       p = malloc(sizeof(CONFIG_ENTRY));
       if (!p)
 	 return;
 
-      if (ugetc(name))
-         p->name = ustrdup(name);
-      else
-	 p->name = NULL;
-
-      p->data = ustrdup(val);
+      p->name = name;
+      p->data = val;
 
       p->next = NULL;
       *prev = p;
@@ -832,9 +853,11 @@
 {
    #define MAX_ARGV  16
 
-   static char buf[256];
+   static char *buf = NULL;
+   static int buf_size = 0;
    static char *argv[MAX_ARGV];
    int pos, ac, q, c;
+   int s_size;
 
    AL_CONST char *s = get_config_string(section, name, NULL);
 
@@ -843,7 +866,18 @@
       return NULL;
    }
 
-   ustrzcpy(buf, sizeof(buf), s);
+   /* Increase buffer size if needed */
+   s_size = ustrsizez(s);
+   if (s_size>buf_size) {
+      char *tmp = realloc(buf, s_size);
+      if (!tmp) {
+         *argc = 0;
+         return NULL;
+      }
+      buf_size = s_size;
+      buf = tmp;
+   }
+   ustrcpy(buf, s);
    pos = 0;
    ac = 0;
 
@@ -1149,16 +1183,38 @@
  */
 AL_CONST char *get_config_text(AL_CONST char *msg)
 {
-   char tmp1[256], tmp2[256], name[256];
+   char tmp1[256];
    AL_CONST char *section = uconvert_ascii("[language]", tmp1);
-   AL_CONST char *umsg = uconvert_ascii(msg, tmp2);
+   char *name;
+   AL_CONST char *umsg;
    AL_CONST char *s;
+   AL_CONST char *ret = NULL;
    CONFIG_HOOK *hook;
    CONFIG_ENTRY *p;
    int c, pos;
 
    init_config(TRUE);
 
+   /* Allocate memory for converted message and name, convert message */
+   if (need_uconvert(msg, U_ASCII, U_CURRENT)) {
+     int size = uconvert_size(msg, U_ASCII, U_CURRENT);
+     umsg = malloc(size);
+     name = malloc(size);
+     if (!umsg || !name) {
+        /* Remove umsg constness */
+        if (umsg)
+           free((char*) umsg);
+        return empty_string;
+     }
+     do_uconvert(msg, U_ASCII, (char*)umsg, U_CURRENT, -1);
+   }
+   else {
+     umsg = msg;
+     name = malloc(ustrsizez(msg));
+     if (!name)
+        return empty_string;
+   }
+
    s = umsg;
    pos = 0;
 
@@ -1176,29 +1232,41 @@
 
    while (hook) {
       if (ustricmp(section, hook->section) == 0) {
-	 if (hook->stringgetter)
-	    return hook->stringgetter(name, umsg);
+	 if (hook->stringgetter) {
+            ret = hook->stringgetter(name, umsg);
+            break;
+         }
       }
       hook = hook->next;
    }
 
-   /* find the string */
-   p = find_config_string(config_override, section, name, NULL);
-
-   if (!p) {
-      p = find_config_string(config[0], section, name, NULL);
+   if (!ret) {
+      /* find the string */
+      p = find_config_string(config_override, section, name, NULL);
 
-      if (!p)
-	 p = find_config_string(config_language, section, name, NULL);
-   }
+      if (!p) {
+         p = find_config_string(config[0], section, name, NULL);
 
-   if (p)
-      return (p->data ? p->data : empty_string);
+         if (!p)
+            p = find_config_string(config_language, section, name, NULL);
+      }
 
-   /* no translation, so store off this value in the file */
-   p = config_language->head;
-   insert_variable(config_language, NULL, name, umsg);
-   config_language->head->next = p;
-   return config_language->head->data;
+      if (p) {
+         ret = (p->data ? p->data : empty_string);
+      }
+      else {
+         /* no translation, so store off this value in the file */
+         p = config_language->head;
+         insert_variable(config_language, NULL, name, umsg);
+         config_language->head->next = p;
+         ret = config_language->head->data;
+      }
+   }
+   /* If the message needed conversion, umsg was allocated, remove its
+    * constness and free it */
+   if (umsg!=msg)
+      free((char*) umsg);
+   free(name);
+   return ret;
 }
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/