2011-10-02 69 views
1

我試圖根據我在網上找到的這個例子建立一個準備好的聲明。 我只是想防止在grade =和username =中進行sql注入,但是語句沒有執行。如何在C中爲mysql查詢設置預準備語句?

MYSQL_STMT *stmt; 
MYSQL_BIND bind[2]; 
char* usrname = &uname[0]; //uname supplied by user 
char* choi = choice; //choice supplied by user 
stmt = mysql_stmt_init(connect); 

char* statement = "UPDATE grades SET grade='?' WHERE username='?'"; 
mysql_stmt_prepare(stmt, statement, strlen(statement)); 

memset(bind,0,sizeof(bind)); 


bind[0].buffer_type=MYSQL_TYPE_STRING; 
bind[0].buffer=usrname; 
bind[0].buffer_length=50; 
bind[0].is_null=0; 
bind[0].length= strlen(usrname); 

bind[1].buffer_type=MYSQL_TYPE_STRING; 
bind[1].buffer=choi; 
bind[1].buffer_length=50; 
bind[1].is_null=0; 
bind[1].length= 2; 

mysql_stmt_bind_param(stmt, bind); 
mysql_stmt_execute(stmt); 
+0

我不能肯定,關於MySQL,但在一些的DBMS,在''應該是* *加引號,就像'用戶名='? –

+0

我嘗試過並收到了seg故障。 – Takkun

+2

您可能需要仔細檢查'bind'設置,例如順序似乎倒退,緩衝區大小可能需要雙重檢查。 –

回答

3
bind[0].length= strlen(usrname); 
bind[1].length= 2; 

綁定[X]。長度是一個指針。它應該指向一個包含長度值的地址,或者被「忽略」爲NULL(零)當設置爲NULL(或零)時,我認爲length_value然後被使用......但我不知道如果用戶應該設置它,或者如果是爲了在內部使用它。但是,根據我的理解(我沒有嘗試它),這是爲了從數據庫中讀取字符串的長度,所以在這種情況下沒有用,因爲您沒有閱讀。

對於輸入,這是你的情況,buffer_length是你想要發送的字符串的長度。對於輸出,它是可以用從db讀取的值填充的緩衝區的大小,如果長度超過該值,則該值被截斷。

你應該有:

bind[0].buffer_type=MYSQL_TYPE_STRING; 
bind[0].buffer=usrname; 
bind[0].buffer_length=strlen(usrname); 
bind[0].is_null=0; 
bind[0].length=0; 

bind[1].buffer_type=MYSQL_TYPE_STRING; 
bind[1].buffer=choi; 
bind[1].buffer_length=strlen(choi); 
bind[1].is_null=0; 
bind[1].length=0; 

,但我沒有測試過這一點,你必須在你的緩衝區的實際字符串。您提供的樣本中的緩衝區未被初始化。

我也強烈建議你使用

memset(bind, 0, sizeof(bind)); 

爲零的整體結構。它將避免在你沒有設置任何東西的地方有垃圾值。

這可能是有用的: https://www.assembla.com/code/DelphiMS/subversion/nodes/Required%20Units/Zeos%207/plain/mysql_bind.txt?rev=32