I'm getting segmentation fault on CentOS 7 64-bit, Release build (there's no issue in debug build)
I tried adding printf to locate where exactly the segfault happens, for below code, segfault raises at: memset(len_p, 0, sizeof(*len_p));
Also, If I add printf to print something right before memeset, there's no segfault, as if the printf is doing some magic here.
Please help me to understand the issue here.
core dump uploaded
Thanks a lot!
code snippet (mysql prepared statement to query something):
(this function was called couple of times, it doesn't always raise segfault)
int mysql_odb_read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid)
{
MYSQL_BIND bind_buffers[2];
MYSQL_BIND result_buffers[3];
memset(bind_buffers, 0, sizeof(bind_buffers));
// bind the repo passed to the statement
bind_buffers[0].buffer = &(backend->mysql->repo);
bind_buffers[0].buffer_length = sizeof(backend->mysql->repo);
bind_buffers[0].length = &bind_buffers[0].buffer_length;
bind_buffers[0].buffer_type = MYSQL_TYPE_LONGLONG;
// bind the oid passed to the statement
bind_buffers[1].buffer = (void*)oid->id;
bind_buffers[1].buffer_length = 20;
bind_buffers[1].length = &bind_buffers[1].buffer_length;
bind_buffers[1].buffer_type = MYSQL_TYPE_BLOB;
if (mysql_stmt_bind_param(backend->mysql->odb_read, bind_buffers) != 0)
return GIT_ERROR;
// execute the statement
if (mysql_stmt_execute(backend->mysql->odb_read) != 0)
return GIT_ERROR;
if (mysql_stmt_store_result(backend->mysql->odb_read) != 0)
return GIT_ERROR;
if (mysql_stmt_num_rows(backend->mysql->odb_read) == 1) {
memset(result_buffers, 0, sizeof(result_buffers));
result_buffers[0].buffer_type = MYSQL_TYPE_TINY;
result_buffers[0].buffer = type_p;
result_buffers[0].buffer_length = sizeof(*type_p);
result_buffers[0].is_null = 0;
result_buffers[0].length = &result_buffers[0].buffer_length;
memset(type_p, 0, sizeof(*type_p));
result_buffers[1].buffer_type = MYSQL_TYPE_LONG;
result_buffers[1].buffer = len_p;
result_buffers[1].buffer_length = sizeof(*len_p);
result_buffers[1].is_null = 0;
result_buffers[1].length = &result_buffers[1].buffer_length;
printf("len_p:%lu\n",*len_p);//if i remove this printf call, there will be segfault
memset(len_p, 0, sizeof(*len_p));
result_buffers[2].buffer_type = MYSQL_TYPE_LONG_BLOB;
result_buffers[2].buffer = *data_p;
result_buffers[2].is_null = 0;
result_buffers[2].buffer_length = data_len;
result_buffers[2].length = &data_len;
//memset(&data_len, 0, sizeof(data_len));
if (mysql_stmt_bind_result(backend->mysql->odb_read, result_buffers) != 0)
return GIT_ERROR;
error = mysql_stmt_fetch(backend->mysql->odb_read);
if (data_len > 0) {
*data_p = malloc(data_len);
if(*data_p){
result_buffers[2].buffer_type = MYSQL_TYPE_LONG_BLOB;
result_buffers[2].buffer = *data_p;
result_buffers[2].is_null = 0;
result_buffers[2].buffer_length = data_len;
result_buffers[2].length = &data_len;
if (mysql_stmt_fetch_column(backend->mysql->odb_read, &result_buffers[2], 2, 0) != 0)
return GIT_ERROR;
}
else{
printf("odb_read, malloc returned NULL\n");
return GITERR_NOMEMORY;
}
}
error = GIT_OK;
} else
error = GIT_ENOTFOUND;
// free result
if (mysql_stmt_free_result(backend->mysql->odb_read) != 0)
return GIT_ERROR;
mysql_free_result(meta_result);
// reset the statement for further use
if (mysql_stmt_reset(backend->mysql->odb_read) != 0)
return GIT_ERROR;
return error;
}
It's difficult to tell the exact problem without dumps or other informations, but a possible explanation may be that the
len_p
is a dangling pointer.This triggers the segfault, however, by calling
printf
, you are probably filling up the stack area wherelen_p
is pointing, withprintf
data, hence remapping the pointer with a new value, avoiding the segmentation fault.