xargs の落とし穴らしきもの

Mac OS X (10.4.9 (8P135)) 上で xargs を使っていたら変な挙動をしたりいきなり segfault したりしたので「ん?これはもしや vuln ?」と思っていろいろ深入りしてしまった。

% xargs -I@ echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
ahoahoahoahoaho
ahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoah
ahoahoahoahoaho
ahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoah
ahoahoahoahoaho
ahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoahoah
xargs(1309) malloc: *** error for object 0x300250: incorrect checksum for freed object - object was probably modified after being freed, break at szone_error to debug
xargs(1309) malloc: *** set a breakpoint in szone_error to debug
zsh: segmentation fault  xargs -I@ echo 

結論から言うともう本家の方では src/usr.bin/xargs/strnsubst.c:r1.7 で直ってる模様。問題は当該リビジョンのログメッセージだ。

revision 1.7
date: 2004/10/18 15:40:47; author: cperciva; state: Exp; lines: +2 -2
Modify behaviour of `xargs -I` in order to:

  1. Conform to IEEE Std 1003.1-2004, which state that "Constructed arguments cannot grow larger than 255 bytes", and
  2. Avoid a buffer overflow.

Unfortunately the standard doesn't indicate how xargs is supposed to handle arguments which (with the appropriate substitutions) would grow larger than 255 bytes; this solution handles those by making as many substitutions as possible without overflowing the buffer.

OpenBSD's xargs resolves this in a different direction, by making all the substitutions and then silently truncating the resulting string.

Since this change may break existing scripts which rely upon the buffer overflow (255 bytes isn't really all that long...) it will not be MFCed.

src/usr.bin/xargs/strnsubstr.c:r1.7@cvs.freebsd.org

255 バイトって短すぎやしませんか?と思って「site:opengroup.org」をつけてアレしてみたら、確かに次のように書かれているページを確認できた。

-I replstr
Insert mode: utility will be executed for each line from standard input, taking the entire line as a single argument, inserting it in arguments for each occurrence of replstr. A maximum of five arguments in arguments can each contain one or more instances of replstr. Any blank characters at the beginning of each line are ignored. Constructed arguments cannot grow larger than 255 bytes. Option -x is forced on. The -I and -i options are mutually exclusive; the last one specified takes effect.
xargs(1)@opengroup.org

POSIX の PATH_MAX が 256 バイトだから 255 バイトに制限にしてるってわけなのかこれは??んなアホな。