Description:
When using mysql++ libray, using Connection with no exceptions, and trying to get a SSQLS set from a mysql server, but passing a wrong table name, you get a Segmentation Fault.
Following is an example of execution using mysql++ 3.0.8. Similar results are obtained with mysql++ 3.0.9:
(gdb) run EJEMPLO localhost root ""
Starting program: /home/jk/kk/sample EJEMPLO localhost root ""
[Thread debugging using libthread_db enabled]
[New Thread 0xb7fe3730 (LWP 2999)]
There are rows in Table_A
Program received signal SIGSEGV, Segmentation fault.
mysql_fetch_row (res=0x0) at client.c:2917
2917 if (!res->data)
(gdb) bt
#0 mysql_fetch_row (res=0x0) at client.c:2917
#1 0x00139380 in mysqlpp::DBDriver::fetch_row () at lib/dbdriver.h:209
#2 mysqlpp::UseQueryResult::fetch_raw_row (this=0xbffff1a0) at lib/result.cpp:205
#3 0x0804e45f in mysqlpp::Query::storein_set<std::set<stock, std::less<stock>, std::allocator<stock> > > ()
#4 0x0804e615 in mysqlpp::Query::storein<stock> ()
#5 0x0804e672 in mysqlpp::Query::storein<std::set<stock, std::less<stock>, std::allocator<stock> > > ()
#6 0x0804af24 in main ()
How to repeat:
Use MySQL++ 3.0.9. and do not use exceptions.
Test the following code. You should create a table named Table_A with two fields, item CHAR and num BIGINT. Run the program with 4 arguments: database, server, user and password.
#include <mysql++.h>
#include <ssqls.h>
using namespace std;
sql_create_2(stock,
1,2,
mysqlpp::sql_char, item,
mysqlpp::sql_bigint, num);
int main (int argc, char *argv[])
{
const char *db=0, *server=0, *user=0, *pass="";
if(argc != 5) {
cerr << "Bad args" << endl;
return 1;
}
db=argv[1];
server=argv[2];
user=argv[3];
pass=argv[4];
//Establish the connection to the database server, NO EXCEPTIONS
mysqlpp::Connection con(false);
if(!con.connect(db, server, user, pass)) {
cerr << "Connection error: " << con.error() << endl;
}
//Create and insert a stock object
stock row("Hot Dogs",100);
stock::table("Table_A");
mysqlpp::Query query=con.query();
query.insert(row);
query.execute();
//Get all the rows in the table
query.reset();
query << "select * from Table_A";
set<stock> res1;
query.storein(res1); //---OK---
if(res1.size() > 0) cout << "There are rows in Table_A" << endl;
//Get all rows in a table that doesn't exist
query.reset();
query << "select * from NonExistentTable";
set<stock> res2;
query.storein(res2); //--- Segmentation fault ---
if(res2.size() > 0) cout << "There are rows in NonExistentTable" << endl;
return 0;
}
Suggested fix:
In lib/query.h file, there is no check for the return value from "use" method in storein_set and storein_sequence methods:
UseQueryResult result =use(s);
while (1) {
MYSQL_ROW d=result.fetch_raw_row();
...
If the query is wrong, result is NULL and SIGSEGV is signaled.
The simplest fix could be the following -in storein_set and storein_sequence-:
UseQueryResult result =use(s);
if (result)
{
while (1) {
MYSQL_ROW d=result.fetch_raw_row();
...
But maybe some other lines inside the while loop could be revised, similar to the code for "store_if" method in lib/query.h.