PDOへの移行はほぼ終了
2008年3月1日
アンケートの結果に従ってPDOを利用することにし、sqlクラスを全面的に書き換えた。次の例のように使うことになる。
これで、規約に沿ってコアやプラグインを書いている限り、SQLインジェクションはほぼ100%起こらない。
一箇所非常に悩んだところがあって、それはどうやらPDOのバグに起因するようだ。SQLクエリーのLIMIT節ではプリペアードステートメントによる代入ができない。これは、PHPのバージョンやDBエンジンの種類・バージョンによって出たり出なかったりするバグのようであるが、今日現在のPHP最新バージョン5.2.5でSQLite2.8を使った場合はこのバグが出る(SQLite2.8は、Windows版PHPでは最新)。
バグ回避策として、sqlite::query()メソッドで<%xxx%>に整数値を代入しようとするときは、PDOのプリペアードステートメントを使わずに直接クエリーに書き込むことにした。LIMIT節では整数値しか利用しないためである。整数なら文字コードの違いが原因のSQLインジェクションが起きる可能性もないし、バグが完全に解消されるまではこれでよいだろう。
$res=sql::query('SELECT * FROM jeans_item WHERE icat=<%catid%>',array('catid'=>$catid)); while ($row=$res->fetch()) core::p($row['ititle']);もしくは
$res=sql::prepare('SELECT * FROM jeans_item WHERE icat= :catid'); $res->bindParam(':catid',$catid); $res->execute(); while ($row=$res->fetch()) core::p($row['ititle']);もしくは
$res=sql::prepare('SELECT * FROM jeans_item WHERE icat= :catid'); $res->execute(array(':catid'=>$catid)); while ($row=$res->fetch()) core::p($row['ititle']);
これで、規約に沿ってコアやプラグインを書いている限り、SQLインジェクションはほぼ100%起こらない。
一箇所非常に悩んだところがあって、それはどうやらPDOのバグに起因するようだ。SQLクエリーのLIMIT節ではプリペアードステートメントによる代入ができない。これは、PHPのバージョンやDBエンジンの種類・バージョンによって出たり出なかったりするバグのようであるが、今日現在のPHP最新バージョン5.2.5でSQLite2.8を使った場合はこのバグが出る(SQLite2.8は、Windows版PHPでは最新)。
バグ回避策として、sqlite::query()メソッドで<%xxx%>に整数値を代入しようとするときは、PDOのプリペアードステートメントを使わずに直接クエリーに書き込むことにした。LIMIT節では整数値しか利用しないためである。整数なら文字コードの違いが原因のSQLインジェクションが起きる可能性もないし、バグが完全に解消されるまではこれでよいだろう。