Thu May 9 21:04:31 JST 2019 (modified: Fri May 10 00:12:42 JST 2019)
views: 8470, keywords:AWK この記事は最終更新日が5年以上前のものです。
%
の入った文字列をawkでprintf $0
するとエラーに
知ってる人は知ってることだと思いますが、10年AWKを使ってきて見落としていた仕様があり、あまり検索しても解説が引っかからなかったのでメモします。結論から言うと、どんな文字列が標準入力やファイルから来るか分からないときは、AWKではprintf $0
と書かないでprintf("%s",$0)
とちゃんと書かないとエラーになることがあります。
例
次のように、標準入力から読み込んだ%
をフォーマット指定子を間違えて、指定子があるのに対象の文字列がないと叱られます。
- one true awkの場合
$ /usr/bin/awk --version
awk version 20070501
uedambp2:20190509 ueda$ echo 'aa%aa' | /usr/bin/awk '{printf $0}'
/usr/bin/awk: weird printf conversion %a
input record number 1, file
source line number 1
/usr/bin/awk: not enough args in printf(aa%aa)
input record number 1, file
source line number 1
- GNU Awkの場合
$ gawk --version
GNU Awk 5.0.0, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.1.2)
Copyright (C) 1989, 1991-2019 Free Software Foundation.
(略)
$ echo 'aa%aa' | gawk '{printf $0}'
gawk: コマンドライン:1: (FILENAME=- FNR=1) 致命的: 書式文字列を満たす十分な数の引数がありません
`aa%aa'
^ ここから足りません
対策
めんどくさがらずにprintf("%s",$0)
と書く。
$ echo 'aa%aa' | /usr/bin/awk '{printf("%s\n",$0)}'
aa%aa
$ echo 'aa%aa' | gawk '{printf("%s\n",$0)}'
aa%aa
現場からは以上です。
追記
ちゃんと攻撃方法にあるんですね。Cならフォーマットなしのprintf
はやめてputs
を使いましょう・・・。あと、教員はC言語を教えるときに、printf
の前にputs
を教えてくださいね。
awkのprintfで書式文字列攻撃が可能とか言われても「お、、おぅ、、、」となる気はするが、それが可能なら対処は必要か。
— mutz0623 (@mutz0623) May 9, 2019
さらに追記
GNU Awk 4.x系では出ない・・・けど%d
だとエラー。GNU Awkで%a
があるのは5.x系以降だからこうなるものと思われます。
$ awk --version
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)
Copyright (C) 1989, 1991-2016 Free Software Foundation.
(略)
$ echo 'aa%aa' | awk '{printf $0}'
aa%aa
$ echo 'aa%da' | awk '{printf $0}'
awk: コマンドライン:1: (FILENAME=- FNR=1) 致命的: 書式文字列を満たす十分な数の引数がありません
`aa%da'
^ ここから足りません
バージョンによるかも?gawkの4系と3系はエラー出ないような・・・
— きゃろさん (@Carol_815) May 9, 2019
%aはおっけ、%dはダメ。
— ぱぴろんちゃん👓 (@papiron) May 9, 2019
echo 'aa%d' | awk '{printf $0}'
one true awkはさておき、たぶん、GNU Awkについては5.0のリリースノートか何かに書いてあるかもしれない・・・。寝たい・・・。
さらにさらに追記
mawk
はエラーが出ました。
$ mawk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan
compiled limits:
max NF 32767
sprintf buffer 2040
ueda@remote:~$ echo 'aa%aa' | mawk '{printf $0}'
mawk: run time error: not enough arguments passed to printf("aa%aa")
FILENAME="-" FNR=1 NR=1
寝たい・・・。