2011-10-02 85 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

相关问题