ページ 1 / 1
文字列について
Posted: 2012年10月25日(木) 23:39
by みるく
こんばんは。質問です!
#include <stdio.h>
int main()
{
int i;
char str[]="Hello!¥n";
for(i=0;i<9;i++){
printf(&str);
}
}
このプログラムについてなのですが
i=6、7、8のときは表示がされません。
I=6のときは「¥n¥0」、i=7のときは「¥0」
が実際にはあると考えられるのですが、I=8のときは
実際は何が出力されているのでしょうか。
わかる方、お願いいたします。
Re: 文字列について
Posted: 2012年10月26日(金) 00:39
by nil
コードタグを使ってください。
まず6の時、何も表示されはしないでしょうが、改行はされているのではないでしょうか?
7の時は終端文字'\0'が1文字目に出てくるため文字は表示されません。
8の時はstrのバッファをオーバーしているため処理は未定です。
Re: 文字列について
Posted: 2012年10月26日(金) 08:00
by box
printf()を使うときは、書式文字列("%d"とか"%s"とか"%f"とか"%p"とか)を
必ず使いましょう。
Cの文法書に、そういう風に書いてあるはずです。それに従うべきです。
Re: 文字列について
Posted: 2012年10月26日(金) 08:06
by みけCAT
box さんが書きました:
printf()を使うときは、書式文字列("%d"とか"%s"とか"%f"とか"%p"とか)を
必ず使いましょう。
Cの文法書に、そういう風に書いてあるはずです。それに従うべきです。
それは迷信だと思いますが、違いますか?
Re: 文字列について
Posted: 2012年10月26日(金) 17:13
by ISLe
printfの第一引数を変数にすると不正アクセスのきっかけを作りやすく、脆弱性を高めることになると思いますけどね。
コード:
const char *sz = "%s";
printf(sz);
printf("%s", sz);
そもそも書式指定を使わないならprintfにとって役不足ですし。
コンパイラが最適化で置き換えてくれそうですが。
Re: 文字列について
Posted: 2012年10月26日(金) 17:39
by box
みけCAT さんが書きました:
それは迷信だと思いますが、違いますか?
違いますよ。
本来第1引数に書くべき書式文字列を省略して、
第2引数以降に書くべき(文字列の)中に書式文字列に相当する内容があった場合、
何が起こるかわかったものではありません。よく理解しましょう。
そもそも、printf()のプロトタイプに反する記述をすることが正しいとは、どうしても思えません。
プロトタイプに反する記述をすることは正しいですか?
Re: 文字列について
Posted: 2012年10月26日(金) 19:08
by shiro4ao
フォーマット文字列攻撃
http://ow.ly/eMKt8
こちらがわかりやすいかなと思います。
とした場合、引数に%xを指定するとスタック上の4バイトが出力されます。
%xをたくさん渡すことでスタックのデータを順番に見ることができるようになります。
無害そうですが、今度は引数に%nを渡すとアドレスに書き込みが行えます・・・・・・・ orz
任意のアドレスの書き換えができるので、プログラム作成者の意図しない挙動をさせることが可能になります。
つまり、不幸にして管理者権限をもったプロセスがフォーマット文字列攻撃を受ければ
管理者権限のシェルを奪取されることになります。
Re: 文字列について
Posted: 2012年10月26日(金) 19:28
by beatle
boxさんの、printfの第一引数には文字列リテラルを書くべき、という指摘は僕も同意するところです。
単純に文字配列を表示したいだけならputsやfputsでいいでしょう。
その上で、純粋な疑問なのですが、以下の発言の「プロトタイプに反する記述」が何を指しているのか良くわかりません。
printf(&str
);
は特にプロトタイプ宣言に違反しているわけではないですよね?
(printfのプロトタイプはint printf(const char*, ...)です。printf(&str);はこれに合致していると思います)
だとすると他に何がプロトタイプに反しているか見つけられませんでした。
box さんが書きました:
そもそも、printf()のプロトタイプに反する記述をすることが正しいとは、どうしても思えません。
プロトタイプに反する記述をすることは正しいですか?
Re: 文字列について
Posted: 2012年10月26日(金) 20:57
by box
【編集後】
別に荒れてないですよ。ご心配なく。
そういえば、
とか書いてたんですよね~。でも、
コード:
char *p = "%s";
printf(p);
とか書くのは、さすがにまずいんだろ~な~。なんてね。
ちゃんちゃん♪
Re: 文字列について
Posted: 2012年10月26日(金) 21:06
by だんごさん
荒れているように見えますが、質問者さんの質問に答えてあげてください。
printfの引数がどうのこうのは別にトピックを立ててください。
printfで議論する場所では無いので。あくまで意見として受け止めては?
…と言っても質問者さんの返信が一件もないのであまり話が進めませんがね…。
Re: 文字列について
Posted: 2012年10月26日(金) 22:15
by softya(ソフト屋)
問題点を指摘するのは必要な事だと思いますが波風の立たないやり方や他者からきつく見えない書き方を考えて頂くと助かります。
それと重箱の隅をつつくような話は別トピックを立てることやプライベートメッセージでお願いします。
以上、よろしくおねがいします。
Re: 文字列について
Posted: 2012年10月27日(土) 16:37
by ISLe
個人的にはせっかく滅多にないセキュアなプログラミングの知識を得る機会を重箱の隅と非難されるのは悲しい気がしますね。
Re: 文字列について
Posted: 2012年10月27日(土) 16:47
by softya(ソフト屋)
ISLe さんが書きました:個人的にはせっかく滅多にないセキュアなプログラミングの知識を得る機会を重箱の隅と非難されるのは悲しい気がしますね。
セキュアな話は大事だと思いますが、どう見ても違う方向に流れている部分が見受けられるのでコメントさせていただきました。
ちゃんと流れを読んで穏やかに話し合って頂く分には問題ありませんので、よろしくお願いします。
Re: 文字列について
Posted: 2012年10月27日(土) 16:59
by box
いずれにしても、
コード:
#include <stdio.h>
int main(void)
{
char *p = "Hello%s";
printf(&p[0]);
return 0;
}
こんなコードを書いた日には何が起きても知らんぜよ、という点においては、
みなさん納得していただけるのではないかと思います。
Re: 文字列について
Posted: 2012年10月27日(土) 20:58
by みけCAT
box さんが書きました:いずれにしても、
コード:
#include <stdio.h>
int main(void)
{
char *p = "Hello%s";
printf(&p[0]);
return 0;
}
こんなコードを書いた日には何が起きても知らんぜよ、という点においては、
みなさん納得していただけるのではないかと思います。
これは間違いないですが、
box さんが書きました:printf()を使うときは、書式文字列("%d"とか"%s"とか"%f"とか"%p"とか)を
必ず使いましょう。
Cの文法書に、そういう風に書いてあるはずです。それに従うべきです。
これはおかしいと思います。
box さんが書きました:そもそも、printf()のプロトタイプに反する記述をすることが正しいとは、どうしても思えません。
プロトタイプに反する記述をすることは正しいですか?
コンパイルしてもエラーは出ませんが、本当にプロトタイプに反していますか?
http://ideone.com/KWyK1i
Re: 文字列について
Posted: 2012年10月27日(土) 21:07
by box
みけCAT さんが書きました:
これはおかしいと思います。
はい。おかしいです。あなたの方が当方よりも優秀なことはよくわかりましたから、もう勘弁してください。
Re: 文字列について
Posted: 2012年10月28日(日) 00:39
by Dixq (管理人)
えーと、このままではみるくさんが、質問しにくいと思いますので話を戻しますね。
質問の件に関して、
char str[]="Hello!¥n";
で必要になる配列要素数は終端記号を含めた8個であるため、strのサイズは8で用意されています。
従って要素9個目にアクセスしようとすると、バッファオーバー(やってはいけない処理)になります。
これを踏まえてもし不明点があれば、また聞いて下さい。
Re: 文字列について
Posted: 2012年10月29日(月) 20:45
by AKIЯA
printf(&str
)は初めて見ました。
動くけども、親切ではないかと思いますね。
親切に作ると多分こうなるかと思います。
sizeof()を使ってオーバーフローしないようにしてます。
コード:
#include <stdio.h>
int main()
{
int i;
int len;
char str[]="Hello!\n";
len = sizeof(str);
for(i=0;i<len;i++){
printf("%s"&str[i]);
}
}
Re: 文字列について
Posted: 2012年10月29日(月) 21:11
by みけCAT
改行したくなければ、fputsを使う方法があります。
コード:
#include <stdio.h>
int main(void) {
int i;
int len;
char str[]="Hello!\n";
len = sizeof(str);
for(i=0;i<len;i++){
fputs(&str[i],stdout);
}
return 0;
}