Mybb1.6을 1.8로 업그레이드하는 과정에서 최근 Mybb1.8 데이터베이스의 핵심 작업인 update_query 코드에서 앞에 오는 0이 누락되는 심각한 버그를 발견했습니다. 데이터를 저장한 후 몇 시간 후에 확인해보니 문제는 나에게 있는 것이 아니라 mybb의 업그레이드 코드에 있는 것이었습니다.
데이터 테이블: 테스트
필드
ID int(10) AUTO_INCREMENT
name varchar( 60) not null
category varchar(5)
이 표에서 카테고리는 분류를 나타내고, 분류는 공통코드인 총계로 표현합니다. of five 처음 두 자리인 0l~99는 대분류를 나타내고, 마지막 세 자리는 소분류를 나타냅니다. update 문에서 Ajax를 통해 텍스트를 업데이트하고, background 문에서 update_query를 통해 데이터를 업데이트합니다. 1.6레벨에서는 프로그램이 정상적으로 작동했는데 1.8레벨에서 업데이트가 엉망이더군요. 확인해본 결과 카테고리 필드 앞의 "0"이 누락된 것을 발견했습니다. 다양한 수단을 변경해도 문제가 해결되지 않습니다. 마지막으로 Mybb의 데이터 연산 코어 파일을 파헤쳐 버전 1.6과 비교한 결과 코드에 저수준 버그가 있어 오류가 발생하는 것을 발견했습니다.
下面是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论坛。