fetus Diary

2008/02/04(月) - SQLStatement@Mojavi 2

今時 Mojavi 2 使うなという話は置いておいて…。昔作ったプログラムのバグ改修なので。

Mojavi 2 の SQLStatement::prepare がバグってる疑惑。

修正後:

function & prepare ($statement) {
    if (sizeof($this->attributes) > 0) {
        // replace conversion character values
        // cannot set the call back object in this constructor,
        // so it must be set here
        $this->pattern->setCallbackObject($this, 'callback');
        $this->pattern->setPattern($statement);
        $statement =& $this->pattern->parse();
    }
    
    $this->stat = $statement;
    
    if (strpos($statement, '?') !== FALSE) {
        // replace prepareable values
        $count        = strlen($this->stat);
        $index        = -1;
        $oldStatement = $this->stat;
        $statement    = '';
        
        // loop through statement
        for ($i = 0; $i < $count; $i++) {
            if ($oldStatement{$i} == '?') {
                $index++;
                if (isset($this->values[$index])) {
                    $statement .= $this->values[$index];
                } else {
                    $error = 'SQL statement does not contain a value for ' .
                             'preparable index #' . ($index + 1);
                    trigger_error($error, E_USER_ERROR);
                }
            } else {
                $statement .= $oldStatement{$i};
            }
        }
    }
    return $statement;
}

オリジナルのコードでは、最初の if(sizeof($this->attributes) > 0) ブロックが return $statement の直前に。要はこれ、順番入れ替えただけ。

なんでこんなことしなくちゃいけないかと言うと、この prepare 関数、%a{data_col} みたいなのを置き換える処理が入ってるのね。これが最初の if ブロックの内側(実際に処理しているのは、$this->pattern->parse())。

"%" がキーになっているのが重要。

ここで、プレースホルダ(SQL 中の "?")に置換設定した文字列中に例えば「100%発生する」とかいう文章があった場合、先に "?" の中身が展開されてしまっていたので、この "%" に誤爆して文字化けしてしまう。

本当はこの修正でも、%x{} で置き換えられた文字列中に? が混入しているとバグるから宜しくない。まじめに両方同時にやるのが正解。

コメント

コメントはありません。

名前
メール
コメント

※HTML タグは使えません。HTTP URL には自動リンクが張られます。

Captcha
画像から読み取れる文字を入力: