[rrd-developers] rrd_diff patch
Luca Deri
deri at ntop.org
Wed Jun 18 17:16:28 MEST 2003
Dear all,
I have found a problem on rrd_diff(). Basically the function is
accessing invalid memory. This is because the two function parameters
(*a and *b) can be of different length (e.g. a = "1234", b = "13") so
the statement
for (x=0; x<m; x++) { ... }
moves the pointers (a1, b1, r1) for m locations (a1--;b1--;r1--;) where
m = max(strlen(a),strlen(b));
In the above example m=4, but b1 cannot be shifted for more than 2
positions (strlen("13")=2), therefore the b1-- statement causes a crash
when b1 is moved for the third time.
I have enclosed a quick hack (see below): fell free to accept it or to
fix it the way you want. Anything is fine as long as the problem is fixed.
Regards, Luca
====
double
rrd_diff(char *a, char *b)
{
char res[LAST_DS_LEN+1], *a1, *b1, *r1, *fix, *_a, *_b;
int c,x,m;
char a_neg=0, b_neg=0;
double result;
m = max(strlen(a),strlen(b));
_a = malloc(m+1);
if(_a == NULL) {
rrd_set_error("allocating _a");
return(0);
}
memset(_a, ' ', m);
memcpy(&_a[m-strlen(a)], a, m);
_a[m] = '\0';
a = _a;
_b = malloc(m+1);
if(_b == NULL) {
rrd_set_error("allocating _b");
return(0);
}
memset(_b, ' ', m);
memcpy(&_b[m-strlen(b)], b, m);
_b[m] = '\0';
b = _b;
while (!(isdigit((int)*a) || *a==0)) {
if(*a=='-')
a_neg = 1;
a++;
}
fix=a;
while (isdigit((int)*fix))
fix++;
*fix = 0; /* maybe there is some non digit data in the string */
while (!(isdigit((int)*b) || *b==0)) {
if(*b=='-')
b_neg = 1;
b++;
}
fix=b;
while (isdigit((int)*fix))
fix++;
*fix = 0; /* maybe there is some non digit data in the string */
if(!isdigit((int)*a) || !isdigit((int)*b)) {
free(_a), free(_b);
return DNAN;
}
if(a_neg+b_neg == 1) /* can not handle numbers with different signs
yet */ {
free(_a), free(_b);
return DNAN;
}
a1 = &a[strlen(a)-1];
m = max(strlen(a),strlen(b));
if (m > LAST_DS_LEN) {
free(_a), free(_b);
return DNAN; /* result string too short */
}
r1 = &res[m+1];
for (b1 = res;b1 <= r1; b1++) *b1 = ' ';
b1 = &b[strlen(b)-1];
r1[1] = 0; /* Null terminate result */
c = 0;
for (x=0; x<m; x++) {
if (a1 >= a && b1 >= b) {
*r1 = ((*a1 - c) - *b1) + '0';
} else if (a1 >= a) {
*r1 = (*a1 - c);
} else {
*r1 = ('0' - *b1 - c) + '0';
}
if (*r1 < '0') {
*r1 += 10;
c=1;
} else
if (*r1 > '9') { /* 0 - 10 */
*r1 -= 10;
c=1;
} else {
c=0;
}
a1--;b1--;r1--;
}
if (c) {
r1 = &res[m+1];
for (x=0; isdigit((int)*r1) && x<m; x++,r1--) {
*r1 = ('9' - *r1 + c) + '0';
if (*r1 > '9') {
*r1 -= 10;
c=1;
} else {
c=0;
}
}
result = -atof(res);
} else
result = atof(res);
if(a_neg+b_neg==2) /* both are negatives, reverse sign */
result = -result;
free(_a), free(_b);
return result;
}
--
Luca Deri <deri at ntop.org> http://luca.ntop.org/
Hacker: someone who loves to program and enjoys being
clever about it - Richard Stallman
--
Unsubscribe mailto:rrd-developers-request at list.ee.ethz.ch?subject=unsubscribe
Help mailto:rrd-developers-request at list.ee.ethz.ch?subject=help
Archive http://www.ee.ethz.ch/~slist/rrd-developers
WebAdmin http://www.ee.ethz.ch/~slist/lsg2.cgi
More information about the rrd-developers
mailing list