From 6907983087af00b132327b5a120e2813d425accd Mon Sep 17 00:00:00 2001
From: Emil Bartczak <emil.bartczak@ts.fujitsu.com>
Date: Wed, 14 Oct 2015 10:48:17 +0200
Subject: [PATCH 1/2] iniparser: use upstream implementation

This fixes (resp. includes) the following
- don't exit() in iniparser
- iniparser: `dictionary_set' must return a value.
  add error checks for all dictionary manipulations
- Removed static array from functions strlwc, strcrop
  to make them thread-safe.
- Unchecked memory allocation in mem_double(), newptr
---
 src/lib/u/iniparser.c | 114 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 74 insertions(+), 40 deletions(-)

diff --git a/src/lib/u/iniparser.c b/src/lib/u/iniparser.c
index 3eb3f703516e..aa35136305fd 100644
--- a/src/lib/u/iniparser.c
+++ b/src/lib/u/iniparser.c
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 #ifndef WIN32
 #include <unistd.h>
 #endif
@@ -48,21 +49,19 @@ extern "C" {
 /**
   @brief    Convert a string to lowercase.
   @param    s   String to convert.
-  @return   ptr to statically allocated string.
+  @param    l   Pointer to destination string.
+  @return   ptr to the destination string.
 
-  This function returns a pointer to a statically allocated string
-  containing a lowercased version of the input string. Do not free
-  or modify the returned string! Since the returned string is statically
-  allocated, it will be modified at each function call (not re-entrant).
+  This function returns a pointer to string containing
+  a lowercased version of the input string.
  */
 /*--------------------------------------------------------------------------*/
 
-static char * strlwc(char * s)
+static char * strlwc(char * s, char * l)
 {
-    static char l[ASCIILINESZ+1];
     int i ;
 
-    if (s==NULL) return NULL ;
+    if ((s==NULL) || (l==NULL)) return NULL ;
     memset(l, 0, ASCIILINESZ+1);
     i=0 ;
     while (s[i] && i<ASCIILINESZ) {
@@ -103,23 +102,20 @@ static char * strskp(char * s)
 /**
   @brief    Remove blanks at the end of a string.
   @param    s   String to parse.
-  @return   ptr to statically allocated string.
+  @param    l   Pointer to destination string.
+  @return   ptr to the destination string.
 
-  This function returns a pointer to a statically allocated string,
+  This function returns a pointer to an array which contains string,
   which is identical to the input string, except that all blank
   characters at the end of the string have been removed.
-  Do not free or modify the returned string! Since the returned string
-  is statically allocated, it will be modified at each function call
-  (not re-entrant).
  */
 /*--------------------------------------------------------------------------*/
 
-static char * strcrop(char * s)
+static char * strcrop(char * s, char * l)
 {
-    static char l[ASCIILINESZ+1];
     char * last ;
 
-    if (s==NULL) return NULL ;
+    if ((s==NULL) || (l==NULL)) return NULL ;
     memset(l, 0, ASCIILINESZ+1);
     strcpy(l, s);
     last = l + strlen(l);
@@ -152,6 +148,10 @@ static void * mem_double(void * ptr, int size)
     void *newptr;
 
     newptr = calloc(2*size, 1);
+    if (newptr == NULL) {
+      fprintf(stderr, "mem_double: allocation failed\n");
+      return NULL;
+    }
     memcpy(newptr, ptr, size);
     free(ptr);
     return newptr ;
@@ -311,15 +311,17 @@ static char * dictionary_get(dictionary * d, char * key, char * def)
   content to NULL is equivalent to deleting the variable from the
   dictionary. It is not possible (in this implementation) to have a key in
   the dictionary without value.
+
+  return 0 on success, non-zero on failure.
  */
 /*--------------------------------------------------------------------------*/
 
-static void dictionary_set(dictionary * d, char * key, char * val)
+static int dictionary_set(dictionary * d, char * key, char * val)
 {
     int         i ;
     unsigned    hash ;
 
-    if (d==NULL || key==NULL) return ;
+    if (d==NULL || key==NULL) return 1 ;
 
     /* Compute hash for this key */
     hash = dictionary_hash(key) ;
@@ -335,7 +337,7 @@ static void dictionary_set(dictionary * d, char * key, char * val)
                         free(d->val[i]);
                     d->val[i] = val ? strdup(val) : NULL ;
                     /* Value has been modified: return */
-                    return ;
+                    return 0 ;
                 }
             }
         }
@@ -346,8 +348,20 @@ static void dictionary_set(dictionary * d, char * key, char * val)
 
         /* Reached maximum size: reallocate blackboard */
         d->val  = (char **)mem_double(d->val,  d->size * sizeof(char*)) ;
+        if (d->val == NULL) {
+          errno = -ENOMEM;
+          return 1;
+        }
         d->key  = (char **)mem_double(d->key,  d->size * sizeof(char*)) ;
+        if (d->key == NULL) {
+          errno = -ENOMEM;
+          return 1;
+        }
         d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
+        if (d->hash == NULL) {
+          errno = -ENOMEM;
+          return 1;
+        }
 
         /* Double size */
         d->size *= 2 ;
@@ -362,10 +376,21 @@ static void dictionary_set(dictionary * d, char * key, char * val)
     }
     /* Copy key */
     d->key[i]  = strdup(key);
-    d->val[i]  = val ? strdup(val) : NULL ;
+    if (d->key[i] == NULL) {
+      return 1;
+    }
+    if (val) {
+      d->val[i] = strdup(val);
+      if (d->val[i] == NULL) {
+        return 1;
+      }
+    }
+    else {
+      d->val[i] = NULL;
+    }
     d->hash[i] = hash;
     d->n ++ ;
-    return ;
+    return 0;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -451,8 +476,10 @@ static void dictionary_dump(dictionary *d, FILE *f)
 #define ASCIILINESZ         1024
 #define INI_INVALID_KEY     ((char*)-1)
 
-/* Private: add an entry to the dictionary */
-static void iniparser_add_entry(
+/* Private: add an entry to the dictionary
+   return 0 on success, non-zero on error
+ */
+static int iniparser_add_entry(
     dictionary * d,
     char * sec,
     char * key,
@@ -468,8 +495,7 @@ static void iniparser_add_entry(
     }
 
     /* Add (key,val) to dictionary */
-    dictionary_set(d, longkey, val);
-    return ;
+    return dictionary_set(d, longkey, val);
 }
 
 
@@ -664,16 +690,11 @@ char * iniparser_getstr(dictionary * d, char * key)
 /*--------------------------------------------------------------------------*/
 char * iniparser_getstring(dictionary * d, char * key, char * def)
 {
-    char * lc_key ;
-    char * sval ;
+    char lc_key[ASCIILINESZ+1];
 
     if (d==NULL || key==NULL)
         return def ;
-
-    lc_key = strdup(strlwc(key));
-    sval = dictionary_get(d, lc_key, def);
-    free(lc_key);
-    return sval ;
+    return dictionary_get(d, strlwc(key, lc_key), def);
 }
 
 
@@ -818,8 +839,9 @@ int iniparser_find_entry(
 
 int iniparser_setstr(dictionary * ini, char * entry, char * val)
 {
-    dictionary_set(ini, strlwc(entry), val);
-    return 0 ;
+    char lc_key[ASCIILINESZ+1];
+
+    return dictionary_set(ini, strlwc(entry, lc_key), val);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -834,7 +856,9 @@ int iniparser_setstr(dictionary * ini, char * entry, char * val)
 /*--------------------------------------------------------------------------*/
 void iniparser_unset(dictionary * ini, char * entry)
 {
-    dictionary_unset(ini, strlwc(entry));
+    char lc_key[ASCIILINESZ+1];
+
+    dictionary_unset(ini, strlwc(entry, lc_key));
 }
 
 
@@ -881,14 +905,22 @@ dictionary * iniparser_new(char *ininame)
         if (*where==';' || *where=='#' || *where==0)
             continue ; /* Comment lines */
         else {
+            char lc_key[ASCIILINESZ+1];
+
             if (sscanf(where, "[%[^]]", sec)==1) {
                 /* Valid section name */
-                strcpy(sec, strlwc(sec));
-                iniparser_add_entry(d, sec, NULL, NULL);
+                strcpy(sec, strlwc(sec, lc_key));
+                if (iniparser_add_entry(d, sec, NULL, NULL) != 0) {
+                  dictionary_del(d);
+                  fclose(ini);
+                  return NULL;
+                }
             } else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2
                    ||  sscanf (where, "%[^=] = '%[^\']'",   key, val) == 2
                    ||  sscanf (where, "%[^=] = %[^;#]",     key, val) == 2) {
-                strcpy(key, strlwc(strcrop(key)));
+                char crop_key[ASCIILINESZ+1];
+
+                strcpy(key, strlwc(strcrop(key, crop_key), lc_key));
                 /*
                  * sscanf cannot handle "" or '' as empty value,
                  * this is done here
@@ -896,9 +928,11 @@ dictionary * iniparser_new(char *ininame)
                 if (!strcmp(val, "\"\"") || !strcmp(val, "''")) {
                     val[0] = (char)0;
                 } else {
-                    strcpy(val, strcrop(val));
+                    strcpy(val, strcrop(val, crop_key));
+                }
+                if (iniparser_add_entry(d, sec, key, val) != 0) {
+                  return NULL;
                 }
-                iniparser_add_entry(d, sec, key, val);
             }
         }
     }
-- 
2.6.4

