variable.c


To ng-spice-devel@ieee.ing.uniroma1.it
From "GLAO S. Dezai" <dezai@hotbot.com>
Date Thu, 30 Nov 2000 08:30:49 -0800
Delivered-To mailing list ng-spice-devel@ieee.ing.uniroma1.it
Mailing-List contact ng-spice-devel-help@ieee.ing.uniroma1.it; run by ezmlm
Organization HotBot Mail (http://mail.hotbot.mailcity.lycos.com:80)
Reply-To ng-spice-devel@ieee.ing.uniroma1.it

 
Hi all,
I think that i know now why variable.c fails to run in some cases.
The reason is to be found in the cp_setparse function.

I used previously to free the pointer ss  before call of the ft_numparse 
function:

                ss = cp_unquote(wl->wl_word);
                td = ft_numparse(&ss, FALSE);
                 ...          
                 tfree(ss);
Here is the problem. When ss contains a number, the ft_numparse increment ss 
so that at the end of the parsing ss points to the end of the allocated area. 
Freeing ss results to a segfault. If ss doesnot contains a number there is no 
problem.
So to fix the bug something like the following must be done.
                    
                copyval=ss = cp_unquote(wl->wl_word);
                td = ft_numparse(&ss, FALSE);
                 ...          
                 tfree(copyval);

Apologies.
glao






HotBot - Search smarter.
http://www.hotbot.com

struct variable *
cp_setparse(wordlist *wl)
{
    char *name, *val, *copyval, *s, *ss;
    double *td;
    struct variable *listv = NULL, *vv, *lv = NULL;
    struct variable *vars = NULL;
    int balance;

    while (wl) {
        name = cp_unquote(wl->wl_word);
        wl = wl->wl_next;
        if (((wl == NULL) || (*wl->wl_word != '=')) && 
               strchr(name, '=') == NULL) {
            vv = alloc(struct variable);
            vv->va_name = copy(name);
            vv->va_type = VT_BOOL;
            vv->va_bool = TRUE;
            vv->va_next = vars;
            vars = vv;
            tfree(name);/*DG: cp_unquote Memory leak*/
            continue;
        }
        if (wl && eq(wl->wl_word, "=")) {
            wl = wl->wl_next;
            if (wl == NULL) {
                fprintf(cp_err, "Error: bad set form.\n");
             tfree(name);/*DG: cp_unquote Memory leak*/
              return (NULL);
            }
            val = wl->wl_word;
            wl = wl->wl_next;
        } else if (wl && (*wl->wl_word == '=')) {
            val = wl->wl_word + 1;
            wl = wl->wl_next;
        } else if ((s =strchr(name, '='))) {
            val = s + 1;
            *s = '\0';
            if (*val == '\0') {
                if (!wl) {
                    fprintf(cp_err,
                        "Error:  %s equals what?.\n",
                        name);
                   tfree(name);/*DG: cp_unquote Memory leak: free name before 
exiting*/
                   return (NULL);
                } else {
                    val = wl->wl_word;
                    wl = wl->wl_next;
                }
            }
        } else {
            fprintf(cp_err, "Error: bad set form.\n");
             tfree(name);/*DG: cp_unquote Memory leak: free name befor 
exiting */
             return (NULL);
        }
     /*   val = cp_unquote(val);  DG: bad   old val is lost*/ 
          copyval=cp_unquote(val);/*DG*/
          strcpy(val,copyval);
          tfree(copyval);
        if (eq(val, "(")) { /* ) */
            /* The beginning of a list... We have to walk down the
             * list until we find a close paren... If there are nested
             * ()'s, treat them as tokens...  */
            balance = 1;
            while (wl && wl->wl_word) {
                if (eq(wl->wl_word, "(")) {
                    balance++;
                } else if (eq(wl->wl_word, ")")) {
                    if (!--balance)
                        break;
                }
                vv = alloc(struct variable);
                vv->va_next = NULL;
                copyval=ss = cp_unquote(wl->wl_word);
                td = ft_numparse(&ss, FALSE);
                if (td) {
                    vv->va_type = VT_REAL;
                    vv->va_real = *td;
                } else {
                    vv->va_type = VT_STRING;
                    vv->va_string = copy(ss);
                }
                 tfree(copyval);/*DG: must free copyval any way to avoid 
cp_unquote memory leak*/
                if (listv) {
                    lv->va_next = vv;
                    lv = vv;
                } else
                    listv = lv = vv;
                wl = wl->wl_next;
            }
            if (balance && !wl) {
                fprintf(cp_err, "Error: bad set form.\n");
                return (NULL);
            }
            
            vv = alloc(struct variable);
            vv->va_name = copy(name);
            vv->va_type = VT_LIST;
            vv->va_vlist = listv;
            vv->va_next = vars;
            vars = vv;

            wl = wl->wl_next;
            continue;
        }

       copyval= ss = cp_unquote(val);
        td = ft_numparse(&ss, FALSE);
        vv = alloc(struct variable);
        vv->va_name = copy(name);
        vv->va_next = vars;
        vars = vv;
        if (td) {
            /*** We should try to get VT_NUM's... */
            vv->va_type = VT_REAL;
            vv->va_real = *td;
        } else {
            vv->va_type = VT_STRING;
            vv->va_string = copy(ss);
        }
        tfree(copyval);/*DG: avoid cp_unquote memory leak */
    }
    return (vars);
}

Partial thread listing: