Invalid read of size 1 [valgrind warning]

F

Flash Gordon

Roman said:
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]) )
...
}

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;
 
R

Roman Mashak

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: (e-mail address removed)
 
A

Antonio Contreras

Roman said:
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)))
 
R

Robert Gamble

Roman said:
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
 
R

Roman Mashak

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: (e-mail address removed)
 
R

Robert Gamble

Roman said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top