▼2011年9月26日月曜日PostgreSQLは標準でバックスラッシュをエスケープしない仕様になったPostgreSQL9.1の仕様変更にて、デフォルト時の設定として、standard_conforming_stringsがonとみなされるようになりました。この仕様変更により、デフォルト設定でのPostgreSQLは、バックスラッシュをエスケープする必要がなくなり、ISO規格のSQLと同様のエスケープルール(シングルクォートを重ねるのみ)となります。PostgreSQLの文字列リテラルは、元々MySQL同様に、バックスラッシュをエスケープする仕様でした。場合、バックスラッシュをエスケープしない(ISO規格と同様の)仕様となりました。従来のリリースでは、standard_conforming_stringsを指定しない場合offとみなされていました。これは、後方互換性維持のためでしょう。リリース8.1のドキュメントには以下のように記述されています。standard_conforming_stringsの値は読み取りのみです。アプリケーションでは、この値を読み取ることで、どのようにバックスラッシュが解釈されるかが分かります。(また、このパラメータが存在するかどうかで、E''文字列構文がサポートされているかどうかが分かります。)今後のリリースでは、standard_conforming_stringsは真になる予定です。バージョン8.1への移行ここで、E''文字列構文という用語が出てきました。これは、PostgreSQL固有の機能で、standard_conforming_stringsの設定に関わらずバックスラッシュによるC言語風のエスケープを行う文字列形式です。ここで、standard_conforming_strings設定と、バックスラッシュのエスケープ要・不要の関係を下表にまとめました。表からも分かるように、PostgreSQLリリース9.1にバージョンアップして挙動が変わるのは、standard_conforming_stringsの設定をしていない場合です。この場合は、standard_conforming_stringsをoffにすることで従来通りの挙動となります。standard_conforming_stringsの設定を変更しない場合は、既存のアプリケーションはどのような影響を受けるでしょうか。以下、PHPとPerlで記述されたアプリケーションについて、この変更の影響を検討してみます。PHPのPostgreSQL関数(pg_xxxx)やPDOなどには、SQL文字列のエスケープ用の関数が用意されています。PostgreSQL関数ではpg_escape_string関数、PDOではquoteメソッドが該当します。これらを使用している場合、standard_conforming_stringsのオプションを自動的に反映して、適切にエスケープしてくれます。DBI/DBDのPgやPgPPを使っている場合、quoteメソッドで文字列をエスケープしている場合も同様です。これらの挙動を「a\'」という文字列がどうエスケープされるかによって調査しました。PgPP)は、いずれもエスケープするだけでなく、シングルクォートで文字列を囲むことにご注意下さい。上表から、これらの関数・メソッドを使っていれば、文字列は正しくエスケープされることが分かります。pg_escape_stringとPDOのquoteメソッドは、通常の文字列リテラル形式を用い、バックスラッシュのエスケープをstandard_conforming_stringsに応じて切り替えています。これに対して、PerlのPgとPgPPは、E''文字列形式を用いることによって、standard_conforming_stringsの影響を回避しています。プレースホルダを使ってSQLを呼び出している場合も、standard_conforming_stringsの影響は受けません。エスケープにaddslashesや自作のエスケープ関数を用いている場合は、対応が必要となります。PgPPの古いバージョンを使っている場合もstandard_conforming_stringsの設定を考慮しないので注意が必要です。既存アプリケーションのリリース9.1対応では、standard_conforming_stringsの意味を変えない方が無難だと思います。このため、既存アプリケーションでPostgreSQLのバージョンを9.1以降に変更する場合は以下のようにすればよいでしょう。standard_conforming_stringsを明示している場合はそのままでよいstandard_conforming_stringsを明示していない場合はoffを指定するこれにより、standard_conforming_stringsのデフォルト値の変更を吸収できます。新規アプリケーション場合は、standard_conforming_stringsを指定しない(あるいはonにする)と良いでしょう。その理由は、こちらの方がISOのSQL標準であり、またバックスラッシュをエスケープ対象にすると、セキュリティ上の問題になりやすいからです。MySQLとの互換性を気にする人もいるでしょうが、PDOやDBIなどの抽象度の高いライブラリを使って記述することにより、エスケープ対象の文字をアプリケーション側で意識する必要はなくなり、互換性も向上します。言えば、プレースホルダを用いてSQL呼び出しすることを強く推奨します。これにより、そもそも文字列リテラルのエスケープが必要なくなり、性能・互換性・セキュリティともに改善されます。[PR]「安全なWebアプリケーションの作り方」電子書籍版9月28日(水)販売開始します。