0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【C】初めてのC言語(26. strcpy関数の罠)

Posted at

はじめに

先日に書いた「【C】初めてのC言語(25. atoi関数の罠)」では、atoi関数が(初心者にとっては)予想外の挙動になるという話を書きました。

今回はstrcpy関数でも同様に初心者にとっては予想外の挙動が見つかったので、その点についてまとめてみました。

strcpy関数の概要

#include
char *strcpy(char *s1, const char *s2);

  • こちらのページを見ると、「文字型配列 *s1 に文字列 *s2 を '\0' までコピーします。'\0' もコピーするので s1 はその分も考えて大きさを宣言しておかなければなりません。」と書かれています。
  • 平たく言えば、「文字列型配列を終端文字の'\0'までコピーする」ということになります。

strcpy関数の挙動

  • 以下のコードを実行すると、コピー先のbuffの長さは3バイトであるにもかかわらず、長さが5バイトのtextの中身が全てコピーされてしまっています。
  • このように「コピー元の配列のサイズ > コピー先の配列のサイズ」という条件の時にstrcpy関数を使うと、「コピー先の配列のバッファサイズを超えた書き込み」が実行されてしまいます。
  • これは以前にも少し勉強したバッファオーバーフロー(バッファオーバーラン)という現象です。
strcpy関数を使った例
#include <stdio.h>

int main(void){
    char text[5] = "abcd";
    char buff[3];
    
    strcpy(buff, text);
    printf("buffの値:%s\n", buff);
}
実行結果
buffの値:abcd

改善策

コピー前に配列の長さをチェックする

  • 以下のコードでは、strcpy関数を呼び出す前にコピー先の配列の長さが十分であるかをチェックしています。
  • 以下のコードではコピー先の配列buffの長さが不十分なので、strcpy関数が呼び出されずに処理が終了しています。
    • char buff[5];とすると、正常にコピー処理が行われます。
  • JPCERTのページを見ると、コピー元のNULLチェックも入れているので、以下のコードにもNULLチェックをいれておきました。
コピー前に配列の長さをチェックする例
#include <stdio.h>

int main(void){
    char text[5] = "abcd";
    char buff[3];
    
    if (text != NULL && strlen(text) < sizeof(buff)) {
        strcpy(buff, text);
    }
    printf("buffの値:%s\n", buff);
}
実行結果
buffの値:

strncpy関数を使う

  • strncpy関数は長さを指定して文字列をコピーできる関数なので、以下のコードでは「コピー先の配列の長さで収まるように末尾を切り落としてコピー」しています。
  • 長さをsizeof(buff)としてしまうと、コピー先に終端文字\0が入らないので、sizeof(buff)-1としています。
  • 末尾が削られてしまってもOKであれば、strncpy関数を使うのも良さそうです。
strncpy関数を使う例
#include <stdio.h>

int main(void){
    char text[5] = "abcd";
    char buff[3];
    
    if (text != NULL) {
        strncpy(buff, text, sizeof(buff)-1);
    }
    printf("buffの値:%s\n", buff);
}
実行結果
buffの値:ab

参考URL

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?