CakePHPのコアライブラリ、Sanitize::clean()のodd_spacesオプションの謎

CakePHPのバリデーションは、基本的にデータベースへ格納する直前にするもので、コントローラーに処理が入るところでのチェックが気になっていました。
ブラウザから受け取った値をバイナリセーフじゃない関数で処理すれば、NULLバイトアタックを受けたりするかもだし、コントローラーであれこれ処理する前に想定外のデータがない状態にしておきたいところ。
Sanitizeクラスが使えるんじゃないかと助言をもらったので調べてみたら、なんか不思議な実装でした。
答えは見つけてないんですが、とりあえず書いておきます。

Sanitize::clean()

Sanitize::clean()はSanitizeクラスが持つ色んなサニタイズ処理を、まとめて適用するメソッドです。
オプション配列でどのサニタイズ処理をするか指定します。
それぞれ下記のようなコードで処理されます。
最初のif文の odd_spaces の処理がとても不思議です。

if ($options['odd_spaces']) {
$data = str_replace(chr(0xCA), '', str_replace(' ', ' ', $data));
}
if ($options['encode']) {
$data = Sanitize::html($data, array('remove' => $options['remove_html']));
}
if ($options['dollar']) {
$data = str_replace("\\\$", "$", $data);
}
if ($options['carriage']) {
$data = str_replace("\r", "", $data);
}

$data = str_replace("'", "'", str_replace("!", "!", $data));

if ($options['unicode']) {
$data = preg_replace("/&#([0-9]+);/s", "&#\\1;", $data);
}
if ($options['escape']) {
$data = Sanitize::escape($data, $options['connection']);
}
if ($options['backslash']) {
$data = preg_replace("/\\\(?!&#|\?#)/", "\\", $data);
}
return $data;

http://api13.cakephp.org/view_source/sanitize/#l-250

「0xCA」を含むおかしなスペース

「0xCA」を含むおかしなスペースを、標準的な半角スペースに置換する。

http://book.cakephp.org/ja/view/1187/clean

Odd spaces (including 0xCA) are replaced with regular spaces.

http://book.cakephp.org/view/1187/clean

odd_spaces - removes any non space whitespace characters

http://api13.cakephp.org/class/sanitize#method-Sanitizeclean

CookbookやAPIリファレンスを見ると、0xCAを含むおかしなスペースをサニタイズしてくれるようです。
0xCAを含んでいる変なスペースなのか、0xCAを含めて様々な変なスペースなのか、ちょっとよく分かりません。
おかしなスペースというと、ASCII制御文字でもあるタブ(0x09)や、混入してればエディタによってはスペースが空く垂直タブ(0x0B)とかかなー?と思ったけど、ソースを見るとそうじゃないようです。

if ($options['odd_spaces']) {
$data = str_replace(chr(0xCA), '', str_replace(' ', ' ', $data));
}

http://api13.cakephp.org/view_source/sanitize/#l-250

str_replace()で 0xCA を決め打で取り除いてます。
よく分かりませんが、16進数の 0xCA で表される文字はおかしなスペースに当たるようです。

0xCAとはなにか?

まずASCIIで0xCAは無いので、CakePHPのデフォルトの文字コードであるUTF-8だと思われます。

UTF-8コード表(1)

UTF-8の文字を本当に全て網羅してるか分かりませんが*1、ここで見るかぎり0xCAを含むUTF-8はあまり見当たりません。
「ca80」「ca90」「caa0」「cab0」の4行くらいです。

UTF-8 Browser Test for Unicode Block 'IPA Extensions'

「ca80」〜「caa0」の3行は、このページでちょうど「0x280」〜「0x2a0」の3行に当たります。

UTF-8 Browser Test for Unicode Block 'Spacing Modifier Letters'

「cab0」の行は、このページでのちょうど「0x2b0」の行に当たります。
Unicode blockとしては「IPA Extensions(IPA拡張)*2」と「Spacing Modifier Letters(前進を伴う修飾文字)」の一部分を跨いでいます。
どちらも目に見える文字や記号があるので、これがCakePHPでいうおかしなスペースに当たるとはちょっと考えにくいきがします。
何より、2バイト文字の先頭1バイトだけを取り除いて、いい状態になるとは思えません。


「0xCA」を含むおかしなスペースが何かは分かりませんでしたが、Sanitize::clean($data, array('odd_spaces'=>true)) をすると、これらの文字が壊れてしまいます。
まぁ、いつ使う文字なのかも分からない文字なので害はなさそうですけど。

半角スペースを半角スペースでstr_replace()するのは何故?

str_replace()で0xCAを取り除く前の処理で、どういうわけか半角スペースを半角スペースでstr_replace()してます。
正直さっぱり意味が分かりません。
何の意味があるんでしょうか?

$data = str_replace("'", "'", str_replace("!", "!", $data));

http://api13.cakephp.org/view_source/sanitize/#l-263

Sanitize::clean()では、数行下にこんな似たような処理もあります。
意味があってやってるんだとは思いますが、どういう効果があるんでしょう?


調べても全然分からないので、もしこういう事かな?ってのがあったらコメントくれるとうれしいです。

*1:UTF-8の16進数での文字コード表があまり見当たらない。Unicodeでの文字コード表はあるんですけど・・・

*2:IPA国際音声記号の事らしい。http://ja.wikipedia.org/wiki/%E5%9B%BD%E9%9A%9B%E8%A1%A8%E9%9F%B3%E6%96%87%E5%AD%97