The Man Who Fell From The Wrong Side Of The Sky:2010年7月分

2010/7/4(Sun)

[NetBSD] BoF 発表資料

BoFに参加された方や、ustで中継を見ていた方々には退屈させてしまった内容かもしれませんが
発表資料は ここ[pdf]に置いておきます。

BoFの質問タイムに I hate UNICODE :-)で有名な(ぉ 山本さんから質問があったのですが
これらのPOSIXおよびプログラミング言語Cの最新動向は

あたりをチェックするとよいかと。

明日以降、このBoF資料をもっと掘り下げて記事を書いていく予定、ただしNetBSD時間(ぉ

[C1X] ISO/IEC JTC1/SC22 WG14ォチ

んで昨日の発表の最後にこれからガチバトルはじまるかもですねーといった
Blocks(Objective-C)とLambda(C++)ですが、 戦いははじまった模様ですぜw

結局 Objective-C も C++ も C の上位互換である必要があるわけでして
相手側の機能が C にバックポートされると必然的に自分たちも実装しなけりゃならんのですよね。
そういう意味ではC++0xが更に遅れる可能性も。
まぁ圧倒的に Apple の方が試合巧者ですな。

2010/7/13(Tue)

[BTS] Redmine

レイルズ!レイルズ!レイルズ!レイルズぅぅうううわぁああああああああああああああああああああああん!!!
あぁああああ…ああ…あっあっー!あぁああああああ!!!レイルズレイルズレイルズぅううぁわぁああああ!!!
あぁクンカクンカ!クンカクンカ!スーハースーハー!スーハースーハー!いい匂いだなぁ…くんくん
んはぁっ!ルビー・オン・レイルズたんの赤色(レッド)まいんの設定をクンカクンカしたいお!クンカクンカ!あぁあ!!

間違えた、 モフモフBitNami::Redmine のインストーラって mysql を無条件で latin1 で CREATE DATABASE しやがるので
8bit スルーのおかげで一見まともに日本語で動いてるふりして
実際には文字数の計算が腐って(例えばUTF-8の'あ'の3byteがそのまま3文字で計算される)
新しいプロジェクトの名称設定なんかで勝手に切り詰められたりするのよね。

対策としてはまずdatabaseの中身を退避。

$ mysqldump --host=localhost --port=3306 --user=bitnami --password=XXXXXXXXXX \
  --default-character-set=binary bitnami_redmine >hoge

次に以下の通り設定ファイルを修正。

$ diff -u mysql/my.ini.orig mysql/my.ini
--- mysql/my.ini.orig 2010-07-14 00:32:10.772000000 +0900
+++ mysql/my.ini      2010-07-14 00:32:39.812000000 +0900
@@ -79,9 +79,13 @@
 read_rnd_buffer_size = 512K
 myisam_sort_buffer_size = 8M

+default-character-set = utf8
+
 # The following options will be passed to all MySQL clients
 [mysql]
 port=3306
 no-auto-rehash
 # Remove the next comment character if you are not familiar with SQL
 #safe-updates
+
+default-character-set = utf8

$ diff -u apps/redmine/config/database.yml.orig apps/redmine/config/database.yml
--- apps/redmine/config/database.yml.orig       2010-07-14 00:37:50.619000000 +0900
+++ apps/redmine/config/database.yml    2010-07-14 00:38:46.369000000 +0900
@@ -13,6 +13,7 @@
   username: bitnami
   password: XXXXXXXXXX
   port: 3306
+  encoding: utf8

 development:
   adapter: mysql

んでさっき退避したダンプ中のDEFAULT CHARSET指定を、latin1でなくutf8に変更します

$ perl -pi -e "s/DEFAULT CHARSET=latin1/DEFAULT CHARSET=utf8/g" hoge

このdatabaseを再作成します。

$ mysql --host=localhost --port=3306 --user=bitnami --password=XXXXXXXXXX \
  --default-character-set=utf8 bitnami_redmine <hoge

んでいろいろと再起動かませば多分OK。

2010/7/30(Fri)

[OpenBSD] UTF-8 locale

死んでないより、UTF-8だけサポートしてmultibyte supportという神経が以下略

まぁ前も書いた通りお茶を濁して終わりの実装ですな、ウンコみがいてない。

ところで(バイザウェーUTF-8 以外の multibyte locale とか iconv の話はあるけど
もう 完全版の Citrus patch は配布しなくてもいいすかね。

ちうか Citrus じゃないコードに citrus prefix つけられても困るよな> citrus_utf8.[ch]
FreeBSD の実装ベースなので RFC3629 に忠実な実装だったりするし。

RFC3629 は UTF-8 の MB_CUR_MAX が 4byte なのか 6byte なのか混乱を生じさせたウンコ改定なのよな。
ISO/IEC 10646 の方の仕様ではまだ 5〜6byte は有効であることに注意、これどうなるんだろうNE。

すべてはセキュリティのためというものの、真のセキュリティパラノイアからすれば

最長 byte 数が変わる → 潜在的なバッファオーバーフローの危険性!

とドキがムネムネするはず。

まぁ清く正しくMB_{CUR,LEN}_MAXとmbrtowc使ってれば問題ないけど
世の中には数多くのオレオレUTF-8変換コードがあるからねぇ。

そこまで面倒みてられるかこのパラノイア、ここに病院を建てような気もするけど、
Wikiなんとかにも書いてあるぐらいだから俺以外にも病院が来いな人がいるんだろう。

つか RFC3629 そのものの10章に書いてあんじゃん。

   Another security issue occurs when encoding to UTF-8: the ISO/IEC
   10646 description of UTF-8 allows encoding character numbers up to
   U+7FFFFFFF, yielding sequences of up to 6 bytes.  There is therefore
   a risk of buffer overflow if the range of character numbers is not
   explicitly limited to U+10FFFF or if buffer sizing doesn't take into
   account the possibility of 5- and 6-byte sequences.

ということですな。

libcが考慮すべき点としては、UTF-8 localeで返すMB_CUR_MAXで確保したバッファに
オレオレUTF-8変換ルーチン(往々にしてlength checkなし)が書き込んだ場合に
buffer overflowさせないくらいは対策しといたほうがいいとかですな。
これでも十分パラノイアな気もするけど。

ちなみにNでは冗長表現は禁止したけど、5〜6バイトは有効にしたままなのはそういった理由。

逆にMB_CUR_MAX使わずに、4固定で確保したバッファを使ってwcrtomb呼ぶのは
仕様を正しく守ってないことになるのでdon't careです。

そもそも冗長な UTF-8 表現の禁止だって、ありゃ文字検査を multibyte でやってるから穴になるわけで
清く正しく wide charcter に変換した後に検査すりゃ問題にならんと思うのですけどね。
そりゃ Portable Chatacter Set の文字に冗長表現があったりするとまずいけどさ(L'x' == 'x'が一意にならない) *1

この程度の穴を踏むような人たちが stateful encoding 扱ったらそりゃ阿鼻叫喚の世界なので
外部エンコーディングとして ISO/IEC 2022 が広く使われなくて良かったともいえる。

元々 5〜6bit を禁止したのだって、UTF-16 の surrogate pair 問題で 21bit までしか扱えないからという
そういう半端モンを内部コードに採用した先見の明のないベンダのせいだしね *2

それに5〜6byte目がトラブルになるケースって、UTF-32の空き22〜32bitをケチビットよろしく
他の事に流用したりしてるような、うんこコードが狙われるくらいだろうし。

*1:その為の __STDC_MB_MIGHT_NEQ_WC__ だったのか(ぉ
*2:当時のマシンスペックを考えると同情の余地がないわけではないけど

[NetBSD] mbrtowc(3) bug

ところで NetBSD の mbrtowc(3) 実装おかしい。
いつもの仕様によると mbrtowc(NULL, NULL, 0 ...) は mbrtowc(NULL, "", 1 ...) と 同義なので

	mbstate_t st;

	setlocale(LC_CTYPE, "ja_JP.eucJP");
	memset(&ps, 0, sizeof(ps));
	mbrtowc(NULL, "\xA1", 1, &ps);
	mbrtowc(NULL, NULL, 0, &ps);
	printf("%s\n", strerror(errno));

の呼び出しは mbrtowc(NULL, "\xA1", 2, &ps)と同じで、EILSEQになるのが正しい動作な希ガス。

なんだけどもNetBSDでは強制初期化してるのよね。

	if (s0 == NULL) {
		_citrus_UTF8_init_state(ei, psenc);
		*nresult = 0; /* state independent */
		return 0;
	}

またお仕事増えちゃったい。

こんな記事書いたけど、1.のmbrtowc(NULL, NULL ...)で初期化をするのは、この mbstate_t が

という厳しい条件が必要ですな、これなら一律memset(3)使った方が間違いがない。
Keep It Simple, i'm Stupidの法則、お詫びして訂正するが賠償は(ry