Unix C++ met libmysqlclient

Status
Niet open voor verdere reacties.

endymion

Nieuwe gebruiker
Lid geworden
21 mrt 2008
Berichten
4
Sinds kort heb ik weer C++ opgepakt, alles lukt perfect behalve een ding.

Ik heb zelf classes geschreven voor Sockets, MySQL en Clients. Het gaat hier met name om de MySQL. Omdat ik de mysql query aanmaak via user input (ik snap dat sql injection een mogelijkheid is, maar dit even ter zijde) is het nodig dat ik de variables juist escape. Zo moet abc'def omgezet worden in abc\'def om het juist uit te kunnen voeren in MySQL (als ik het niet af vang, dan geeft het programma een segfault).

Hiervoor heb ik twee commando's gevonden in de mysql.h header, namelijk mysql_escape_string en mysql_real_escape_string.

Ik gebruik nu de "real" functie omdat deze kijkt naar het huidige MySQL charset. Het probleem is dat ik het commando niet juist kan uitvoeren. Stel:

char *a = "abc'def"
char *newa;
int alen = strlen(a);
char *b = "def'hij"
char *newb;
int blen = strlen(b);
mysql_real_escape(&mysql,newa,a,alen); // ik weet dat &mysql nu niet bestaat.
mysql_real_escape(&mysql,newb,b,blen); // ik weet dat &mysql nu niet bestaat.

dan word newa netjes "abc\'def" zoals het hoort. Daar in tegen word newb "\\\\\\\\". Dus allemaal slashes.

Nou dacht ik bij mezelf, maak het script eens kleiner en probeer het opnieuw:

Code:
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <cctype>
#include "/usr/include/mysql/mysql.h"

MYSQL *mysql;                   /* MySQL Handler */
MYSQL_RES *mysql_res;           /* MySQL Result  */
MYSQL_FIELD *mysql_fields;      /* MySQL Fields  */
MYSQL_ROW mysql_row;            /* MySQL Row     */

int iRetValue = 0;

char *Test1 = "abc'def";
char *Escaped;
int Test1Len;

int main(int argc, char *argv[]){
        mysql = mysql_init(NULL);
        if (!mysql_real_connect(mysql,"10.0.0.2","roland","xxxxxxx","Cer",3306,NULL,0)) {
                printf("Failed to open connection to MySQL\n");
        }
        printf("Testing char *Test1 with %s length %i\n",Test1,strlen(Test1));
        Test1Len = strlen(Test1);
        //Escaped = malloc((1 + (Test1Len * 2)) * sizeof(char));
        mysql_real_escape_string(mysql,Escaped,Test1,Test1Len); << segfault
        printf("Escaped outcome %s\n",Test1);
        mysql_close(mysql);
}

Nu krijg ik deze code helemaal niet aan het werk, geeft een segfault bij het uitvoeren van de escape_string.

Heeft iemand enig idee?

Alvast bedankt.
 
Het zou niet verplicht moeten zijn, maar probeer voor mysql_init(), mysql_library_init() eens aan te roepen.

En ik neem aan dat die comment voor de geheugenallocatie weg was toen je het probeerde?:p

Ik heb ook wel eens mysql op linux gebruikt en kan me herinneren dat ik ook vaak segfaults kreeg, dat lag toen aan het linken van mijn executable. Gebruik je de mysqlconfig executable bij het compilen?
 
Bedankt voor de informatie.

Ik heb eens gekeken op de dev.mysql site voor mysql_library_init() maar ik word er niet veel wijzer van. Ik snap hoe je het kan toepassen, maar niet waarom dit mijn probleem zou op kunnen lossen. MySQL queries werken namelijk gewoon (SELECT, UPDATE, DELETE etc).

De malloc comment heb ik neer gezet omdat dit simpelweg niet werkt (al heb ik dit uit Anope IRC services, de mysql module, gehaald). Deze error melding verschijnt:

Main.cpp: In function 'int main(int, char**)':
Main.cpp:28: error: invalid conversion from 'void*' to 'char*'

Ik heb eens voor de grap een debug los gelaten op mijn a.out.core omdat ik het tot op heden niet heb opgelost (en zelf zit ik te denken om me eigen EscapeString functie te maken om van alles af te zijn). Dit is de debug log.

Bij de run:
Testing char *Test1 with abc'def length 7

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x28401100 (LWP 100225)]
0x280991c8 in escape_string_for_mysql ()
from /usr/local/lib/mysql/libmysqlclient_r.so.15

De backtrace:
#0 0x280991c8 in escape_string_for_mysql ()
from /usr/local/lib/mysql/libmysqlclient_r.so.15
#1 0x2808e9fa in mysql_real_escape_string ()
from /usr/local/lib/mysql/libmysqlclient_r.so.15
#2 0x08048851 in main ()

Zoals je kunt zien spreek ik "mysql_real_escape_string" aan, maar het gaat fout in de "escape_string_for_mysql". Het lijkt mij dat het probleem in de library zit waar ik mijn programma tegenaan compile.

Ik weet niet precies meer welk mysql commando ik heb gebruikt, maar er is een commando dat laat zien hoe je mysqlclient moet linken tegen je programma. De regel heb ik aangepast om Main.cpp te compilen:

g++ Main.cpp -L/usr/local/lib/mysql -lmysqlclient_r -lz -lcrypt -lm

[EDIT] Ik zie nu dat ik -lmysqlclient_r gebruik ipv -lmysqlclient. Dit heb ik gedaan om dat ik beide libraries heb gevonden op mijn systeem, geen van beide lost overigens de segfault op.
 
Laatst bewerkt:
Zonder die malloc probeert escape_string de string te kopieren (en escapen) naar een null adres, vandaar de segmentation fault.

Jammer genoeg kun je niet zomaar een void pointer opslaan in een char pointer, je moet hem dus casten:

Code:
Escaped = (char*) malloc((1 + (Test1Len * 2)) * sizeof(char));

success:thumb:

Sam.
 
Bedankt! Dit lost inderdaad de sergfault en het compile probleem op! Over de uitkomst van het programma valt echter nog te twisten:

Testing char *Test1 with abc'def length 7
Escaped outcome abc'def

:confused:
 
Code:
printf("Escaped outcome %s\n",Test1);

Zou hier niet Escaped moeten staan ipv Test1? :p
 
Haastige spoed is zelden goed. Waarschijnlijk ben ik gister in alle paas drukte vergeten de code overnieuw te bekijken :)

Ditmaal is de output wel goed:
Testing char *Test1 with abc'def length 7
Escaped outcome abc\'def

Bedankt voor alle hulp, nu nog implementeren in me echte code :thumb:
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan