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,SerialNu mber,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:
mr*@tusur.ru