「都税クレジットカードお支払いサイト」不正アクセス事件の調査報告書

ざっとしか読んでないですが。

GMO-PG では、2008 年 12 月に最初の PCI DSS 認証を取得し、年次での再認証監査を 8 回経た上で、2016 年 12 月に最新の認証を取得しており、クレジットカード情報 を取扱う事業者として要求されるべき一定レベルの情報セキュリティ体制を具備して いたものの、本件ではそのような体制が Apache Struts 2 の未知の脆弱性を突いたゼロデイ攻撃に対しては、奏功しなかったという事案である。

S2-045は脆弱性情報公開と同時に対策済みバージョンがリリースされているので、そもそもゼロデイ攻撃じゃないよね。8、9ページの時系列の情報の所にもApache Struts 2の対策済みバージョンリリースの情報が出てこないのはミスリードしたいんでしょうかね。

とはいえ、セキュリティ情報提供サービスからのS2-045の情報提供自体が遅いとか危険度情報がないとかかわいそうな感じがしなくもない。大量の脆弱性情報をひとつひとつ精査はしてられないだろうしな。リモートコード実行(RCE)とか書いていたなら、危機感もてよ、という感じもありますが。

Oracle vs Googleのやつ

単純に疑問に思ったことなど。

Androidの非互換性

従来Javaと非互換な実装で、従来Javaのエコシステムが破壊されてんの?私が知らないだけで、今時のJavaライブラリは#ifdefみたいに、VM実装確認してスイッチしたりしてるんだろうか。
Javaと非互換の癖にJava名乗るなみたいな話であれば、それはそれでわかる。

トップレベルパッケージ

Android はまず、名前衝突を避けるために定められたパッケージ名の naming convention を完全に無視し、勝手に android というトップレベル・パッケージ名を宣言しました。

Android以外にもパッケージにドメイン名を入れない例は多い。ぱっと思いつく例だと、Groovyとか、Wekaとか、OpenNLPとか。
OSSなので、組織名入れたくないみたいな、事情はあるかもしれない。だったら、org.androidでいいんじゃね、という気もしますが。

OSSとして

OpenJDKをGPLでリリースしておいて、その一部であるAPIを無断使用として訴えるというのはどゆことだろ。まぁ、AndroidはOpenJDKではなく、Apache Harmonyの派生なので、そんな単純でもないが、Apache Harmonyを放置しておいて、Apache Harmony派生のAndroidだけ訴えるというのは、それこそ道義的にどうなんだ、という気はする。
仮にOpenJDKの派生として作られたら、GPLに従っている限りは文句を言われる筋合いはないはずだよね。

その他

AndroidのString.indexOf が壊れている件はソースを見る限り、Apache Harmonyから引き継いだバグっぽいですね。

git の sha1_to_hex のやつ

すこし調べた。

Linus が普通に Mailing List で明言していた。

Nothing magical, it's just "rounded up from 40 + NUL character".

単に、40バイト+NUL文字用の1バイトで切り上げて50バイトらしい。

が、masterのやつを見たら全然違うので、もう少し歴史を見てみる。
最初のは read-cache.c にあった。initial commitですね。

char * sha1_to_hex(unsigned char *sha1)
{
	static char buffer[50];
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	return buffer;
}

sha1_file.cに移動されたあと、ちゃんと毎回 NUL terminate されるようになる。commitは@1e80e0

char * sha1_to_hex(const unsigned char *sha1)
{
	static char buffer[50];
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}

static 領域のアドレスを返すためにエラーメッセージ作るのが面倒だとかそんな感じの文句が出たのか、簡易LRUキャッシュが導入される。commitは@dcb345

char * sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][50];
	static const char hex[] = "0123456789abcdef";
	char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}

さらに hex.c に移動して、マジックナンバーをマクロで置き換え、バッファサイズも変更。commit は @aa1c6f

char *sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
	static const char hex[] = "0123456789abcdef";
	char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
	int i;

	for (i = 0; i < GIT_SHA1_RAWSZ; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}
#define GIT_SHA1_RAWSZ 20
#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)

で、reentrant版の sha1_to_hex_r と非reentrant版のsha1_to_hexに分離して、だいたい今の形になっている。commitは@af49c6

char *sha1_to_hex_r(char *buffer, const unsigned char *sha1)
{
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < GIT_SHA1_RAWSZ; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}

char *sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
	return sha1_to_hex_r(hexbuffer[3 & ++bufno], sha1);
}

こんな小さな関数でも結構変わっているもんですな。

データがずれている

ブコメにも書いたけど国立大学の授業料のデータが5年ずれているっぽい。昭和50年は1975年ですからね。
というだけなのもなんなので、ちゃんとデータをまとめてみた。

1975年比でいうと、物価で補正すると8.26倍、給与で補正すると5.92倍になっとると。

注意点

  • 授業料のデータは文科省のページから
  • 物価は政府統計から「持家の家賃帰属を除く総合」
  • 給与は厚労省のページの所定内給与を使った
  • 1975年の所定内給与のデータがないようなので、1976年、1977年のデータから線形補間
  • 2006年以降の授業料のデータがなかったが、変わっていないようなので、2005年のデータのままとした
  • 一部手打ちしているので、間違っているかも

Emacs Lispでvariance

Lispらしく書くならこんな感じ?

(defun varp-1 (xs)
  (cl-labels ((varp-sub (xs s1 s2 len)
			(if (consp xs)
			    (let ((x (car xs)))
			      (varp-sub
			       (cdr xs)
			       (+ s1 (* x x))
			       (+ s2 x)
			       (1+ len)))
			  (let ((e1 (/ s1 (float len)))
				(e2 (/ s2 (float len))))
			    (- e1 (* e2 e2))))))
    (varp-sub xs 0 0 0)))

慣れないと読みづらいな。Python で書きなおすと、こう。

def varp_1(xs):
    def varp_sub(xs, s1, s2, length):
        if xs:
            x = xs[0]
            return varp_sub(xs[1:], s1 + x * x, s2 + x, length + 1)
        else:
            e1 = s1 / float(length)
            e2 = s2 / float(length)
            return e1 - e2 * e2

    return varp_sub(xs, 0, 0, 0)

Emacs LispはTail Call Optimization効かないのでdolistマクロのが一般的かも。

(defun varp-2 (xs)
  (let ((s1 0)
	(s2 0)
	(len 0))
    (progn
      (dolist (x xs)
	(progn
	  (setq s1 (+ s1 (* x x)))
	  (setq s2 (+ s2 x))
	  (setq len (1+ len))))
      (let ((e1 (/ s1 (float len)))
	    (e2 (/ s2 (float len))))
	(- e1 (* e2 e2))))))
(benchmark-run 100 (varp-1 large-list))
(0.009979 0 0.0)

(benchmark-run 100 (varp-2 large-list))
(0.00844 0 0.0)

dolistを使ったほうが少し早い。