ログ日記

作業ログと日記とメモ

PHPならではの

[PHP-users 6012] Re: PHP デザインパタン
この投稿からだいぶ時間が経ってるんだけど、PHPならではのパターンってあるのかな?
変数ではなく値に型があることを利用したようなパターン。。。


mixedを受け取ってそこからの派生クラスというかドライバクラスで型ごとに違う実装をするとか?
でも他の言語だとオーバーロードで出来ることをオーバーロードパターン(?)にしないといけないとか?うーん。

サニタイズ

凄く反応が遅いけど。
高木浩光@自宅の日記 - プログラミング解説書籍の脆弱性をどうするか, 「サニタイズ言うなキャンペーン」とは何か, ASPとかJSPとかPHPとかERBとか、逆だ..


最近のプログラム入門書は、文字列解析機構があるという考え方がないのかな。書いてる人もそういう意識があまり無いのかもしれない。


私が初めてプログラムを書いたのはPerlの掲示板だったように思う。(C言語の入門書は数列計算とかカレンダー表示とか面白くない例しかなかった)
初めにHTTPヘッダを出力して、リクエストを&と=で区切って変数に入れ、出力時にもまたまた正規表現を使って < を &lt; に変換していったりとか。
その上で例えばフォントタグを使いたいならフォントタグだけ許可する。
それも甘いチェックだと属性を使ってすぐ悪戯(?)されるから正確にパースしなければならなかったと思う。
禁止するタグだけ設定するとしたら、例えば

<script>

の文字列を単純にを禁止しても、すぐに

< script >

とかやられちゃう。
ファイルに保存するときも安易にタブ区切りにしてると、タブをコピペで入力されてバグったり。
そんなわけで文字列を解析して正しい処理をするということは普通だったわけで。
区切り文字(トークン?特別な意味がある文字)については入門の時点で解説されていた。


それがPHPになるとリクエストを$_GETで簡単に受け取れたり、DBが簡単に使えたりでそういう所に意識を向けにくいのかも。
DBにしてもシングルクォーテーションをデータとして記録できるべきだし、ファイル名にしても../を記録できるべきだ。
例えばアップローダでファイル名を../としてアップしても、タイトル一覧で../を表示できて内容を見れる方が普通だとまず考える。アプリケーション上のファイル名と実際のパスは別問題。実際のパスと同一にするのは手を抜くためだと考えれば、ただの文字列と実際のパスの扱い方について自然と意識する。


昔(5,6年前?)の入門書を読んだら自然とそういう考え方になった気がするんだけども、今は無理なのか。便利で簡単にプログラムが書けるようになっても頭が追いついていかない。むしろサニタイズとか刷り込みがある分だけ今の方が厄介か。


カーネルソースのパス探索部分を見てるとC言語で一文字一文字解析してるんだけど、そういう部分を実際に見たり情報系の授業で習ったりしているとだいぶ違ってくるんだろうな。

脆弱性

前の記事のリンクは

プログラミング解説書籍の脆弱性をどうするか

とあるが、脆弱性という単語もあまり好きじゃない。


どこかにバグという言葉について、あたかも自然発生したような印象を与えるからミスと言うべき(バグが発生したんじゃなくて純粋にミスをしているだけだ)、みたいな文章があったけどそれと同じ。
その世界全体が必然的に抱え込んでいる問題(まぁそれはそれで正しいんだろうけど)のように捉えてしまう。
脆弱性が元から存在していたわけじゃなくて、脆弱なシステムを作り込んだのだ。


IT用語辞典によると、システム上の欠陥や仕様上の問題のことらしい。
要するに「プログラミング解説書籍の欠陥」のこと。
完璧なものを作れっていうのは難しいし、役立っている部分も多いから柔らかく言っているのかな。




日本語の曖昧さは文学的にはいいんだろうけど、こういう分野だと考えることが多くなって大変だ。

ふと思い立ってmemcacheを入れる

まずはmemcached

apt-get install memcached


pecl install コマンドは、configureオプションを変えられないのかな?私の開発環境はPHP4とPHP5が共存*1しているので追加モジュールのインストールが簡単にいかない。
探しても見つからなかったしソースを追っても量が多すぎて挫折・・ひとつの関数が長いから追いにくいし違うクラスで同じメソッドを使ってるからgrepしづらい・・。


で、仕方なく

pecl download memcache
tar xvzf memcache-2.1.0.tgz
cd memcache-2.1.0
phpize5.1
./configure --with-php-config=php-config5.1
make
su
make install

とする。


/etc/php5.1/cgi/conf.d/ にファイルを作って(/etc/php5.1/conf.d/からリンクした方が良いかも)phpinfoで確認。


ここまでやって気付いたけど、リソース型は保存できないのか・・・そりゃそうだ。

memcacheの制限

きのうの memcached ネタ - にぽたん研究所
色々検索して、perlのコードをPHPに書き直して自分で実行してみて、やっと理解したorz


文字列は

$str = str_repeat('.', $size);

で作ってやってみたんだけど、デフォルトの設定じゃなかなかメモリを使い切らない。
段々上げていったら長さが1048538までしか受け付けなかったよ。この中途半端な数字は1MB-α?
そんで70回繰り返してみた。

<?php

$size = 1;
$count = 10;

if (isset($_SERVER['argv'][1])){
     $size = $_SERVER['argv'][1];
}
if (isset($_SERVER['argv'][2])){
    $count = $_SERVER['argv'][2];
}

$m = new Memcache();
$m->connect('localhost', 11211) or die("connect error\n");

$str = str_repeat('.', $size);
for ($i = 0; $i <= $count; $i++){
    $m->delete($i);
    $m->set($i, $str) or print "set error\n";
    echo "$i: " . strlen($m->get($i)) . "\n";
}

sleep(1);

for ($i = 0; $i <= $count; $i++){
    echo "$i: " . strlen($m->get($i)) . "\n";
}
?>

こんなコード。


flush()をやってもダメ。
あとflush()で気付いたけど、flush()後はすぐにキャッシュを登録できないっぽい。新しく登録されたデータまで消去対象になってるような動き。
usleep(100000)ぐらいしたら使える。
# キャッシュサイズやデータの数によって変わるかもしれないからこの関数は使わない方が安全か