Invalid read of size 1 [valgrind warning]

Discussion in 'C Programming' started by Flash Gordon, Dec 12, 2005.

  1. Flash Gordon

    Flash Gordon Guest

    Roman Mashak wrote:
    > Hello, All!
    >
    > I already posted my question and received valuable feedbacks, I changed my
    > code as was proposed here but still receive the same error of valgrind. SO,
    > the code is:
    >
    > #define DB_IS_FLD_EMPTY(x) (((x) && *(x)) ? 0 : 1)
    > int db_is_fld_empty(char *fld)
    > {
    > return DB_IS_FLD_EMPTY(fld);
    > }
    >
    > static int cli_auth2()
    > {
    > ...
    > /* the value of 'raw' is fetched from DB */
    > ...
    > if ( db_is_fld_empty(row[2+idx]) )
    > ...
    > }


    <snip>

    > The value of 'raw' is definitely not NULL, otherwise code would never jump
    > to the specified loop. Is it possible 'valgrind' makes wrong assumption and
    > warns me?


    That's possible, it's also possibly that you go off the end of the block
    of memory. We don't know because you have not provided a complete
    compilable program together with sample input exhibiting the problem.
    Until you do that all anyone can do is guess. So I suggest changing line
    42 of your source to:
    a = 6 * 9;
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
    Flash Gordon, Dec 12, 2005
    #1
    1. Advertising

  2. Flash Gordon

    Roman Mashak Guest

    Hello, All!

    I already posted my question and received valuable feedbacks, I changed my
    code as was proposed here but still receive the same error of valgrind. SO,
    the code is:

    #define DB_IS_FLD_EMPTY(x) (((x) && *(x)) ? 0 : 1)
    int db_is_fld_empty(char *fld)
    {
    return DB_IS_FLD_EMPTY(fld);
    }

    static int cli_auth2()
    {
    ...
    /* the value of 'raw' is fetched from DB */
    ...
    if ( db_is_fld_empty(row[2+idx]) )
    ...
    }

    Valgrind's error is:

    1 errors in context 1 of 10:
    Invalid read of size 1
    at 0x804A896: db_is_fld_empty (db.c:147)
    by 0x804B94F: cli_auth2 (daemon.c:130)
    by 0x804C002: process (daemon.c:336)
    by 0x804CADA: main (daemon.c:567)

    The value of 'raw' is definitely not NULL, otherwise code would never jump
    to the specified loop. Is it possible 'valgrind' makes wrong assumption and
    warns me?

    With best regards, Roman Mashak. E-mail:
    Roman Mashak, Dec 12, 2005
    #2
    1. Advertising

  3. Roman Mashak wrote:
    > Hello, All!
    >
    > I already posted my question and received valuable feedbacks, I changed my
    > code as was proposed here but still receive the same error of valgrind. SO,
    > the code is:
    >
    > #define DB_IS_FLD_EMPTY(x) (((x) && *(x)) ? 0 : 1)


    <snip to EOF>

    Why do you use the conditional operator? IMO the following would be
    much easier to read:

    #define DB_IS_FLD_EMPTY(x) (!((x) && *(x)))
    Antonio Contreras, Dec 12, 2005
    #3
  4. Roman Mashak wrote:
    > Hello, All!
    >
    > I already posted my question and received valuable feedbacks, I changed my
    > code as was proposed here but still receive the same error of valgrind. SO,
    > the code is:
    >
    > #define DB_IS_FLD_EMPTY(x) (((x) && *(x)) ? 0 : 1)
    > int db_is_fld_empty(char *fld)
    > {
    > return DB_IS_FLD_EMPTY(fld);
    > }
    >
    > static int cli_auth2()
    > {
    > ...
    > /* the value of 'raw' is fetched from DB */
    > ...
    > if ( db_is_fld_empty(row[2+idx]) )
    > ...
    > }
    >
    > Valgrind's error is:
    >
    > 1 errors in context 1 of 10:
    > Invalid read of size 1
    > at 0x804A896: db_is_fld_empty (db.c:147)
    > by 0x804B94F: cli_auth2 (daemon.c:130)
    > by 0x804C002: process (daemon.c:336)
    > by 0x804CADA: main (daemon.c:567)


    You need to provide the smallest but *complete* piece of code that will
    compile properly and demonstrate your issue. What you posted isn't
    complete, for example, what is row? If row is an array of char then
    try db_is_fld_empty(&row[2+idx]).

    Robert Gamble
    Robert Gamble, Dec 12, 2005
    #4
  5. Flash Gordon

    Roman Mashak Guest

    Hello, Robert!
    You wrote on 12 Dec 2005 05:27:45 -0800:

    RG> You need to provide the smallest but *complete* piece of code that will
    RG> compile properly and demonstrate your issue. What you posted isn't
    I should apologize in advance for possible inconvenience, because compilable
    piece of code demonstrating 'valgrind' warnings is pretty large and may be
    offtopic here (because it uses MySQL library which has nothing with standard
    C), anyway I'll take a chance.

    #define _GNU_SOURCE

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <mysql/mysql.h>

    /* responses */
    #define NS_UPDATE_PASS 3
    #define NS_DELETE_PASS 4
    #define NS_REGISTER_PASS 5

    #define FAIL 11
    #define NS_REGISTER_FAIL 16
    #define DB_NO_DATA 17
    #define AUTH_FAIL_1 18

    #define BUFFLEN 1024

    /* message type */
    #define MSG_REQ 0x01
    #define MSG_REPLY 0x02

    /* client message */
    typedef struct msg_s {
    unsigned char msg_flag; /* 0-register, 1-modify, 2-delete */
    unsigned char msg_type; /* message type: MSG_REQ, MSG_REPLY */
    unsigned char msg_rc; /* reply code */
    char msg_id[BUFFLEN];
    char msg_passwd[BUFFLEN];
    char msg_fqdn[BUFFLEN];
    char msg_ipaddr[BUFFLEN];
    char msg_serialno[BUFFLEN];
    } msg_t;

    /* DB connection properties */
    typedef struct db_connector_s {
    char db_host[BUFFLEN];
    char db_user[BUFFLEN];
    char db_passwd[BUFFLEN];
    char db_name[BUFFLEN];
    } db_connector_t;

    db_connector_t db_conn = {"127.0.0.1", "root", "core2003", "Cdisk2"};

    char *db_query_str[] = {
    "SELECT UserId,PassWord,FqDomainName1,FqDomainName2 from diskInfo WHERE
    SerialNumber=\"%s\";",
    "UPDATE diskInfo SET IpAddress=\"%s\",FqDomainName%d=\"%s\" WHERE
    SerialNumber=\"%s\";",
    "UPDATE diskInfo SET IpAddress=\"%s\",FqDomainName%d=\"\" WHERE
    SerialNumber=\"%s\";",
    "INSERT into diskInfo
    (UserId,PassWord,FqDomainName%d,IpAddress,SerialNumber,Date) VALUES (\"%s\",
    \"%s\", \"%s\", \"%s\", \"%s\", \"%s\");",
    "DELETE from diskInfo WHERE SerialNumber=\"%s\";"
    };

    /* db_init() - initialize DB object and establish connection */
    int db_init(MYSQL *Conn, db_connector_t *c)
    {
    /* initialize the connection object here */
    if ( mysql_init(Conn) == NULL )
    return -1;

    /* connect main database here */
    if( !mysql_real_connect(Conn, c->db_host, c->db_user, c->db_passwd,
    c->db_name, 0, NULL, 0) )
    return -1;

    /* select database */
    if( mysql_select_db(Conn, c->db_name) )
    return -1;

    return 0;
    }

    /* db_close() - close previously opened connection */
    void db_close(MYSQL *Conn)
    {
    mysql_close(Conn);
    }

    /* db_search() - run query and return pointer to result set */
    MYSQL_RES* db_search(MYSQL *Conn, char szQuery[])
    {
    MYSQL_RES *res, *tmp_res;

    res = malloc(sizeof(*res));
    tmp_res = malloc(sizeof(*tmp_res));
    if ( res == NULL || tmp_res == NULL )
    return NULL;

    if ( mysql_query(Conn, szQuery) ) {
    free(res);
    free(tmp_res);
    return NULL;
    }

    tmp_res = mysql_store_result(Conn);
    memcpy(res, tmp_res, sizeof(MYSQL_RES));
    if ( !tmp_res ) {
    /* must free allocated memory */
    mysql_free_result(tmp_res);
    free(res);
    free(tmp_res);
    return NULL;
    }
    else {
    mysql_free_result(tmp_res);
    return res;
    }
    }

    #define DB_IS_FLD_EMPTY(x) (((x) && *(x)) ? 0 : 1)

    /* db_is_field_empty() - return 1 if 'fld' is empty, otherwise 0 */
    int db_is_fld_empty(char *fld)
    {
    return DB_IS_FLD_EMPTY(fld);
    }

    /* xstrstr() - search substring in string: 1 if found, 0 otherwise */
    static int xstrstr(const char *s1, const char *s2)
    {
    return (strstr(s1, s2) == NULL ? 0 : 1);
    }

    /* authenticate client */
    static int cli_auth2(MYSQL_RES *res, msg_t *m)
    {
    int fld_idx;
    MYSQL_ROW row;

    fld_idx = xstrstr(m->msg_fqdn, ".cdisk.co.kr");
    if ( res ) {
    if ( res->row_count == 0 ) {
    return ( m->msg_flag == 0 ? _ERR_NO_ROWS : DB_NO_DATA );
    }
    else {
    row = mysql_fetch_row(res);
    if ( !strcmp(m->msg_id, row[0]) && !strcmp(m->msg_passwd, row[1]) ) {
    /* ID-PASSWD pair match */
    switch ( m->msg_flag ) {
    case 0:
    /* assume there are no both FQDNi empty fields */
    if ( !db_is_fld_empty(row[3-fld_idx]) &&
    !db_is_fld_empty(row[2+fld_idx]))
    return NS_REGISTER_FAIL;
    else
    if ( !db_is_fld_empty(row[2]) && fld_idx == 1 )
    return NS_REGISTER_FAIL;
    else
    if ( !db_is_fld_empty(row[3]) && fld_idx == 0 )
    return NS_REGISTER_FAIL;
    else
    /*return NS_UPDATE_PASS;*/
    return NS_REGISTER_PASS;
    break;
    default:
    break;
    }
    }
    else
    return AUTH_FAIL_1;
    } /* else */
    }
    else /* res is NULL */
    return FAIL;

    return FAIL;
    }

    /* process() - daemon's main tube, listen for connections and spawn */
    int main(void)
    {
    msg_t *msg;
    int r;

    MYSQL conn;
    MYSQL_RES *mysql_res;
    char szQuery[BUFFLEN] = { 0 };

    /* endless loop: get request and handle it */
    if ( !(msg = malloc(sizeof(msg_t))) ) {
    exit(EXIT_FAILURE);
    }

    msg->msg_flag = 0;
    msg->msg_flag = MSG_REQ;
    msg->msg_flag = 0;
    strcpy(msg->msg_id, "us");
    strcpy(msg->msg_passwd, "us");
    strcpy(msg->msg_fqdn, "mrv.cdisk.co.kr");
    strcpy(msg->msg_ipaddr, "192.168.1.1");
    strcpy(msg->msg_serialno, "1234");

    if (db_init(&conn, &db_conn) < 0) {
    goto cleanup;
    }

    if ( (mysql_res = malloc(sizeof(MYSQL_RES))) == NULL ) {
    goto cleanup;
    }

    memset(mysql_res, 0, sizeof(MYSQL_RES));

    /* build query */
    snprintf(szQuery, BUFFLEN, db_query_str[0], msg->msg_serialno);

    mysql_res = db_search(&conn, szQuery);

    switch ( r = cli_auth2(mysql_res, msg) ) {
    case NS_REGISTER_PASS:
    break;
    case _ERR_NO_ROWS:
    break;
    case NS_UPDATE_PASS:
    break;
    case NS_DELETE_PASS:
    break;
    default:
    break;
    }

    cleanup:
    db_close(&conn);
    free(msg);
    free(mysql_res);
    exit(EXIT_SUCCESS); /* for test only */

    return 0;
    }

    Actually, the upper first error indicated by 'valgrind' seems to be related
    to MySQL specific functions, so I suppose fixing of these errors may fix
    others:

    ==13580== Invalid read of size 4
    ==13580== at 0x4069700: mysql_fetch_row (in
    /usr/lib/libmysqlclient.so.15.0.0)
    ==13580== by 0x8048A5B: cli_auth2 (main.c:110)
    ==13580== by 0x8048CF7: main (main.c:181)
    ==13580== Address 0x4330B0C is 20 bytes inside a block of size 8,164 free'd
    ==13580== at 0x401B12C: free (vg_replace_malloc.c:235)
    ==13580== by 0x4044472: my_no_flags_free (in
    /usr/lib/libmysqlclient.so.15.0.0)
    ==13580== by 0x40476BF: free_root (in /usr/lib/libmysqlclient.so.15.0.0)
    ==13580== by 0x4066560: free_rows (in /usr/lib/libmysqlclient.so.15.0.0)
    ==13580== by 0x40669CA: mysql_free_result (in
    /usr/lib/libmysqlclient.so.15.0.0)
    ==13580== by 0x8048992: db_search (main.c:79)
    ==13580== by 0x8048CDD: main (main.c:179)

    With best regards, Roman Mashak. E-mail:
    Roman Mashak, Dec 13, 2005
    #5
  6. Roman Mashak wrote:
    > Hello, Robert!
    > You wrote on 12 Dec 2005 05:27:45 -0800:
    >
    > RG> You need to provide the smallest but *complete* piece of code that will
    > RG> compile properly and demonstrate your issue. What you posted isn't
    > I should apologize in advance for possible inconvenience, because compilable
    > piece of code demonstrating 'valgrind' warnings is pretty large and may be
    > offtopic here (because it uses MySQL library which has nothing with standard
    > C), anyway I'll take a chance.
    >


    [snip code and valgrind output]

    These errors are different from the ones you originally asked about and
    valgrind and MySQL are both off-topic here. At this point you
    definitely need to find a group that deals with MySQL API issues.
    Before you do though, you should try to isolate the code causing the
    error to the smallest possible complete program, you should be able to
    due this in about 20 lines of code or less. If you do this you will be
    in a better position to figure out the problem for yourself and someone
    else will be more likely to assist you if you still need help. You
    should also explain exactly how your program misbehaves so that you are
    not limiting yourself to answers from people who have experience with
    valgrind.

    Robert Gamble
    Robert Gamble, Dec 13, 2005
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alexandre

    leak detected using valgrind

    Alexandre, Nov 13, 2003, in forum: C++
    Replies:
    1
    Views:
    312
    Gianni Mariani
    Nov 13, 2003
  2. Replies:
    2
    Views:
    33,996
    Victor Bazarov
    Feb 17, 2005
  3. A.A

    Invalid read of size 1

    A.A, Dec 10, 2005, in forum: C Programming
    Replies:
    9
    Views:
    1,553
    Mark McIntyre
    Dec 10, 2005
  4. sanket

    Invalid write Valgrind

    sanket, Sep 21, 2011, in forum: C Programming
    Replies:
    1
    Views:
    621
    Harald van Dijk
    Sep 21, 2011
  5. Replies:
    12
    Views:
    1,210
    Xavier Roche
    Jan 19, 2013
Loading...

Share This Page