[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