In the process of upgrading Mybb1.6 to 1.8, we encountered numerous problems. Recently, we discovered a serious bug in the code of the core operation update_query of the Mybb1.8 database, which caused the leading zeros to be missed when the data was saved. After a few hours, I found that the fault was not with me, but with mybb's upgrade code.
Data table: test
field
ID int(10) AUTO_INCREMENT
name varchar (60) not null
category varchar(5)
In this table, category represents the classification, and the classification is represented by common codes, a total of five The first two digits, 0l to 99, represent major categories, and the last three digits represent small categories. Update the text through Ajax in the update statement, and update the data through update_query in the background statement. The program worked normally at level 1.6, but the update was chaotic at level 1.8. After checking, I found that the "0" in front of the category field was missing. The problem cannot be solved by changing various means. Finally, I dug out the data operation core file of Mybb and compared it with version 1.6 and found that there was a low-level bug in the code, causing the error.
下面是1.8版数据更新过程
Php代码
function update_query($table, $array, $where="", $limit="", $no_quote=false) { global $mybb; if(!is_array($array)) { return false; } $comma = ""; $query = ""; $quote = "'"; if($no_quote == true) { $quote = ""; } foreach($array as $field => $value) { if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) { if($value[0] != 'X') // Not escaped? { $value = $this->escape_binary($value); } $query .= $comma."`".$field."`={$value}"; } else { if(is_numeric($value)) { $query .= $comma."`".$field."`={$value}"; } else { $query .= $comma."`".$field."`={$quote}{$value}{$quote}"; } } $comma = ', '; } if(!emptyempty($where)) { $query .= " WHERE $where"; } if(!emptyempty($limit)) { $query .= " LIMIT $limit"; } return $this->write_query(" UPDATE {$this->table_prefix}$table SET $query "); }
而1.6版本是这样的
Php代码
function update_query($table, $array, $where="", $limit="", $no_quote=false) { if(!is_array($array)) { return false; } $comma = ""; $query = ""; $quote = "'"; if($no_quote == true) { $quote = ""; } foreach($array as $field => $value) { $query .= $comma."`".$field."`={$quote}{$value}{$quote}"; $comma = ', '; } if(!emptyempty($where)) { $query .= " WHERE $where"; } if(!emptyempty($limit)) { $query .= " LIMIT $limit"; } return $this->write_query(" UPDATE {$this->table_prefix}$table SET $query "); }
发生错误的是这样几句
Php代码
if(is_numeric($value)) { $query .= $comma."`".$field."`={$value}"; } else { $query .= $comma."`".$field."`={$quote}{$value}{$quote}"; }
传过来category的值可能是01002或08003,只要is_numeric($value)为真就是数字类型?!这是什么逻辑。其时mysql能自动处理识别字符型和数字型的差别,升级的1.8版把简单的事情复杂化,错误的逻辑导致bug发生,导致传过来的由数字组成的字符串存入数据库时前面的0丢失。如果前面不为0,就不会出错,这样导致数据一片混乱。
一直以来很欣赏Mybb简洁的代码和漂亮的系统架构,2M代码包括图片CSS等竟然能完成如此多的功能,给予用户良好的扩展能力。没想到翻出这样一个bug,见笑了。1.6至1.8改动很大,发布过于仓促。总体说来,Mybb不失一个漂亮简洁的php论坛。