Bug #44764 Segmentation fault caused by calling "correctly" mysql_free_result() function
Submitted: 10 May 2009 8:31 Modified: 14 Jun 2009 17:14
Reporter: Glen Cao Email Updates:
Status: No Feedback Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S1 (Critical)
Version:Ver 8.41 Distrib 5.0.45 OS:Linux (2.6.18-92.1.22.el5)
Assigned to: CPU Architecture:Any
Tags: fault, mysql_free_result, segment

[10 May 2009 8:31] Glen Cao
Description:
My program got a signal of segmentation fault and i got to know it was caused by a call to mysql_free_result function.

Codes following:

/******** db_mysql.h file *******/
#ifndef _DB_MYSQL_H
#define _DB_MYSQL_H

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif

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

typedef struct {
	unsigned long num_rows;
	unsigned num_fields;
	char (*fields_name)[16], ***row_set;
} ResultSet;

MYSQL *connect_db(void);
unsigned long query(MYSQL *, const char *, ResultSet *);
void close_db(MYSQL *);
void free_rs(ResultSet *);

#ifdef __cpluscplus
#if __cplusplus
}
#endif
#endif

#endif

/********** db_mysql.c file *******/
#include "db_mysql.h"

void close_db(MYSQL *mysql)
{
	if(mysql) {
		mysql_close(mysql);
		mysql = NULL;
	}
}

MYSQL *connect_db(void)
{
	extern char dbhost[];
	extern char dbuser[];
	extern char dbpass[];
	extern char dbname[];
	extern char dbport[];

	static MYSQL *mysql = NULL;

	if(!mysql) {
		if(!(mysql = mysql_init(mysql))) {
			fprintf(stderr, "Init MySQL error\n");
			return NULL;
		}
		if(!mysql_real_connect(mysql, dbhost, dbuser, dbpass, dbname, (unsigned)atoi(dbport), NULL, 0)) {
			fprintf(stderr, "%s\n", mysql_error(mysql));
			close_db(mysql);
			return NULL;
		}
		mysql_query(mysql, "SET NAMES utf8");
	}

	return mysql;
}

unsigned long query(MYSQL *mysql, const char *sql, ResultSet *rs)
{
	MYSQL_RES *res = NULL;
	MYSQL_ROW row = NULL;
	MYSQL_FIELD *fields = NULL;
	unsigned i;
	unsigned long j;

	if(mysql_query(mysql, sql)) {
		fprintf(stderr, "%s\n", mysql_error(mysql));
		//close_db(mysql);
		return 0;
	}

	//res = mysql_store_result(mysql);
	if(res = mysql_store_result(mysql)) {
		rs->num_fields = mysql_num_fields(res);
		rs->num_rows = mysql_num_rows(res);
		rs->fields_name = (char (*)[16])calloc(rs->num_fields, sizeof(char *));
		rs->row_set = (char ***)malloc(rs->num_rows * sizeof(char **));
		fields = mysql_fetch_fields(res);
		for(i=0; i<rs->num_fields; ++i)
			strcpy(*(rs->fields_name+i), fields[i].name);
		j = 0;
		while(row = mysql_fetch_row(res)) {
			*(rs->row_set+j) = (char **)malloc(rs->num_fields * sizeof(char *));
			for(i=0; i<rs->num_fields; ++i) {
				*(*(rs->row_set+j)+i) = (char *)calloc(strlen(*(row+i))+1, 1);
				strcpy(*(*(rs->row_set+j)+i), *(row+i));
			}
			++j;
		}
		mysql_free_result(res);    //HERE!!! segmentation fault!
	} else {
		if(mysql_field_count(mysql)) {
			fprintf(stderr, "%s\n", mysql_error(mysql));
			//close_db(mysql);
			return 0;
		} else
			return 1;	//
	}

	return rs->num_rows;
}

void free_rs(ResultSet *rs)
{
	if(rs->row_set) {
		unsigned long i;
		unsigned j;

		for(i=0; i<rs->num_rows; ++i)
			if(*(rs->row_set+i)) {
				for(j=0; j<rs->num_fields; ++j)
					if(*(*(rs->row_set+i)+j)) {
						free(*(*(rs->row_set+i)+j));
						*(*(rs->row_set+i)+j) = NULL;
					}
				free(*(rs->row_set+i));
				*(rs->row_set+i) = NULL;
			}
		free(rs->row_set);
		rs->row_set = NULL;
	}

	if(rs->fields_name) {
		free(rs->fields_name);
		rs->fields_name = NULL;
	}
}

How to repeat:
Write a small programe to query a MySQL database using the functions i provided.
[10 May 2009 8:33] Glen Cao
Header file

Attachment: db_mysql.h (application/octet-stream, text), 525 bytes.

[10 May 2009 8:34] Glen Cao
Definition file

Attachment: db_mysql.c (application/octet-stream, text), 2.40 KiB.

[14 May 2009 17:14] Sveta Smirnova
Thank you for the report.

But version 5.0.45. Additionally I can not repeat described behavior. Please update to current version 5.0.81, try with it and if problem still exists provide compete test case including function main.
[14 Jun 2009 23:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".