variable.c
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: