testing and fixing str and string configuration variables with NULL values
authorMiklos Tirpak <miklos@iptel.org>
Wed, 30 Jan 2008 11:48:39 +0000 (11:48 +0000)
committerMiklos Tirpak <miklos@iptel.org>
Wed, 30 Jan 2008 11:48:39 +0000 (11:48 +0000)
cfg/cfg_ctx.c
cfg/cfg_script.c
cfg/cfg_select.c
cfg/cfg_struct.c
cfg/cfg_struct.h

index 62c0dca..4958e6c 100644 (file)
@@ -145,16 +145,26 @@ static int convert_val(unsigned int val_type, void *val,
                        break;
 
                } else if (val_type == CFG_VAR_STRING) {
+                       if (!val || (((char *)val)[0] == '\0')) {
+                               LOG(L_ERR, "ERROR: convert_val(): "
+                                       "cannot convert NULL string value to integer\n");
+                               return -1;
+                       }
                        *new_val = (void *)(long)strtol((char *)val, &end, 10);
                        if (*end != '\0') {
                                LOG(L_ERR, "ERROR: convert_val(): "
                                        "cannot convert string to integer '%s'\n",
-                                       s.s);
+                                       (char *)val);
                                return -1;
                        }
                        break;
 
                } else if (val_type == CFG_VAR_STR) {
+                       if (!((str *)val)->len || !((str *)val)->s) {
+                               LOG(L_ERR, "ERROR: convert_val(): "
+                                       "cannot convert NULL str value to integer\n");
+                               return -1;
+                       }
                        if (str2sint((str *)val, &i)) {
                                LOG(L_ERR, "ERROR: convert_val(): "
                                        "cannot convert string to integer '%.*s'\n",
@@ -177,6 +187,10 @@ static int convert_val(unsigned int val_type, void *val,
                        break;
 
                } else if (val_type == CFG_VAR_STR) {
+                       if (!((str *)val)->s) {
+                               *new_val = NULL;
+                               break;
+                       }
                        /* the value may not be zero-terminated, thus,
                        a new variable has to be allocated with larger memory space */
                        if (temp_string) pkg_free(temp_string);
@@ -203,7 +217,7 @@ static int convert_val(unsigned int val_type, void *val,
 
                } else if (val_type == CFG_VAR_STRING) {
                        s.s = (char *)val;
-                       s.len = strlen(s.s);
+                       s.len = (s.s) ? strlen(s.s) : 0;
                        *new_val = (void *)&s;
                        break;
 
@@ -322,8 +336,8 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
        case CFG_VAR_STRING:
                /* clone the string to shm mem */
                s.s = v;
-               s.len = strlen(v);
-               if (!(s.s = cfg_clone_str(s))) goto error;
+               s.len = (s.s) ? strlen(s.s) : 0;
+               if (cfg_clone_str(&s, &s)) goto error;
                memcpy(&old_string, p, sizeof(char *));
                memcpy(p, &s.s, sizeof(char *));
                break;
@@ -331,7 +345,7 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
        case CFG_VAR_STR:
                /* clone the string to shm mem */
                s = *(str *)v;
-               if (!(s.s = cfg_clone_str(s))) goto error;
+               if (cfg_clone_str(&s, &s)) goto error;
                memcpy(&old_string, p, sizeof(char *));
                memcpy(p, &s, sizeof(str));
                break;
@@ -565,15 +579,15 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
        case CFG_VAR_STRING:
                /* clone the string to shm mem */
                s.s = v;
-               s.len = strlen(v);
-               if (!(s.s = cfg_clone_str(s))) goto error;
+               s.len = (s.s) ? strlen(s.s) : 0;
+               if (cfg_clone_str(&s, &s)) goto error;
                memcpy(changed->new_val, &s.s, sizeof(char *));
                break;
 
        case CFG_VAR_STR:
                /* clone the string to shm mem */
                s = *(str *)v;
-               if (!(s.s = cfg_clone_str(s))) goto error;
+               if (cfg_clone_str(&s, &s)) goto error;
                memcpy(changed->new_val, &s, sizeof(str));
                break;
 
@@ -710,14 +724,16 @@ int cfg_commit(cfg_ctx_t *ctx)
                }
        }
 
-       /* allocate memory for the replaced string array */
-       size = sizeof(char *)*(replaced_num + 1);
-       replaced = (char **)shm_malloc(size);
-       if (!replaced) {
-               LOG(L_ERR, "ERROR: cfg_commit(): not enough shm memory\n");
-               goto error;
+       if (replaced_num) {
+               /* allocate memory for the replaced string array */
+               size = sizeof(char *)*(replaced_num + 1);
+               replaced = (char **)shm_malloc(size);
+               if (!replaced) {
+                       LOG(L_ERR, "ERROR: cfg_commit(): not enough shm memory\n");
+                       goto error;
+               }
+               memset(replaced, 0 , size);
        }
-       memset(replaced, 0 , size);
 
        /* make sure that nobody else replaces the global config
        while the new one is prepared */
@@ -742,7 +758,11 @@ int cfg_commit(cfg_ctx_t *ctx)
                if ((CFG_VAR_TYPE(changed->var) == CFG_VAR_STRING)
                || (CFG_VAR_TYPE(changed->var) == CFG_VAR_STR)) {
                        memcpy(&(replaced[replaced_num]), p, sizeof(char *));
-                       replaced_num++;
+                       if (replaced[replaced_num])
+                               replaced_num++;
+                       /* else do not increase replaced_num, because
+                       the cfg_block_free() will stop at the first
+                       NULL value */
                }
 
                memcpy( p,
@@ -814,7 +834,7 @@ int cfg_rollback(cfg_ctx_t *ctx)
                if ((CFG_VAR_TYPE(changed->var) == CFG_VAR_STRING)
                || (CFG_VAR_TYPE(changed->var) == CFG_VAR_STR)) {
                        memcpy(&new_string, changed->new_val, sizeof(char *));
-                       shm_free(new_string);
+                       if (new_string) shm_free(new_string);
                }
                shm_free(changed);
        }
index ad652d9..b9b1be7 100644 (file)
@@ -194,8 +194,7 @@ int cfg_script_fixup(cfg_group_t *group, unsigned char *block)
                        offset = ROUND_POINTER(offset);
                        mapping[i].offset = offset;
 
-                       if (!(s.s = cfg_clone_str(script_var->val.s))) goto error;
-                       s.len = script_var->val.s.len;
+                       if (cfg_clone_str(&(script_var->val.s), &s)) goto error;
                        memcpy(block + offset, &s, sizeof(str));
                        mapping[i].flag |= cfg_var_shmized;
 
index 15dba09..c0a532b 100644 (file)
@@ -96,7 +96,7 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
 
        case CFG_VAR_STRING:
                memcpy(&res->s, p, sizeof(char *));
-               res->len = strlen(res->s);
+               res->len = (res->s) ? strlen(res->s) : 0;
                break;
 
        case CFG_VAR_STR:
index ea89b73..25e9c54 100644 (file)
@@ -94,20 +94,31 @@ cfg_group_t *cfg_new_group(char *name, int name_len,
        return group;
 }
 
-/* clones a string to shared memory */
-char *cfg_clone_str(str s)
+/* clones a string to shared memory
+ * (src and dst can be the same)
+ */
+int cfg_clone_str(str *src, str *dst)
 {
        char    *c;
 
-       c = (char *)shm_malloc(sizeof(char)*(s.len+1));
+       if (!src->s) {
+               dst->s = NULL;
+               dst->len = 0;
+               return 0;
+       }
+
+       c = (char *)shm_malloc(sizeof(char)*(src->len+1));
        if (!c) {
                LOG(L_ERR, "ERROR: cfg_clone_str(): not enough shm memory\n");
-               return NULL;
+               return -1;
        }
-       memcpy(c, s.s, s.len);
-       c[s.len] = '\0';
+       memcpy(c, src->s, src->len);
+       c[src->len] = '\0';
+
+       dst->s = c;
+       dst->len = src->len;
 
-       return c;
+       return 0;
 }
 
 /* copies the strings to shared memory */
@@ -127,15 +138,17 @@ static int cfg_shmize_strings(cfg_group_t *group)
 
                if (CFG_VAR_TYPE(&mapping[i]) == CFG_VAR_STRING) {
                        memcpy(&s.s, group->vars + mapping[i].offset, sizeof(char *));
+                       if (!s.s) continue;
                        s.len = strlen(s.s);
 
                } else if (CFG_VAR_TYPE(&mapping[i]) == CFG_VAR_STR) {
                        memcpy(&s, group->vars + mapping[i].offset, sizeof(str));
+                       if (!s.s) continue;
 
                } else {
                        continue;
                }
-               if (!(s.s = cfg_clone_str(s))) return -1;
+               if (cfg_clone_str(&s, &s)) return -1;
                memcpy(group->vars + mapping[i].offset, &s.s, sizeof(char *));
                mapping[i].flag |= cfg_var_shmized;
        }
@@ -233,7 +246,7 @@ static void cfg_destory_groups(unsigned char *block)
                                                memcpy( &old_string,
                                                        block + group->offset + mapping[i].offset,
                                                        sizeof(char *));
-                                               shm_free(old_string);
+                                               if (old_string) shm_free(old_string);
                                }
 
                if (group->dynamic) {
index 6fd24da..3afca59 100644 (file)
@@ -260,7 +260,7 @@ int cfg_lookup_var(str *gname, str *vname,
 cfg_block_t *cfg_clone_global(void);
 
 /* clones a string to shared memory */
-char *cfg_clone_str(str s);
+int cfg_clone_str(str *src, str *dst);
 
 /* installs a new global config
  *