2025
01
18
2012
06
30
strncpyを使った安全な文字列コピー(C言語)
コピー元の文字列の長さが不明な時用のメモリ破壊を起こさない 文字列コピーの方法について、strncpyの動作を見ながら確認したメモ 結論から言うと strncpy(dst, src, DST_BUFF_LEN); dst[DST_BUFF_LEN-1] = '\0'; すれば破壊は起きない、ただsrcをコピーしきれないことがある。 下記のソースを試したコンパイラバージョンは gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)です。
ソースコード
/* nex2t_strncpy.c */ #include <stdio.h> #include <string.h> #define EX_STR "0123456789abcdefghij" #define EX_STR2 "01234" #define BUF_LEN 16 #define DEBUG_LINE "---------------------------------------------------------\n" int main(void) { int i; char buf[BUF_LEN]; /* -------------------------------------------------------------- */ printf(DEBUG_LINE); printf("use buffer buf[BUF_LEN] BUF_LEN=%d\n", BUF_LEN); printf(DEBUG_LINE); printf("EX_STR:%s [strlen(EX_STR):%ld, sizeof(EX_STR):%ld]\n", EX_STR, strlen(EX_STR), sizeof(EX_STR)); printf(" (over buf[BUF_LEN] size!!)\n"); printf(DEBUG_LINE); printf("EX_STR2:%s [strlen(EX_STR2):%ld, sizeof(EX_STR2):%ld]\n", EX_STR2, strlen(EX_STR2), sizeof(EX_STR2)); printf(" (not over buf[BUF_LEN] size)\n"); printf(DEBUG_LINE "\n"); /* ---- Init after ----------------------------------------------- */ printf("Init after\n"); printf(DEBUG_LINE); for (i = 0; i < BUF_LEN; i++) { buf[i] = '\0'; } for (i = 0; i < BUF_LEN; i++) { printf("buf[%d] = %d\n", i, buf[i]); } printf("buf[BUF_LEN] = %d (secretly watch.)\n\n", buf[BUF_LEN]); /* ---- Normal_1 ------------------------------------------------ */ printf("Normal_1\n"); printf(DEBUG_LINE); strncpy(buf, EX_STR, 5); printf("strncpy(buf, EX_STR, 5);\n"); printf("result:string:%s [strlen(buf):%ld, sizeof(buf):%ld]\n", buf, strlen(buf), sizeof(buf)); for (i = 0; i < BUF_LEN; i++) { printf("buf[%d] = %d\n", i, buf[i]); } printf("buf[BUF_LEN] = %d (secretly watch.)\n\n", buf[BUF_LEN]); /* init */ for (i = 0; i < BUF_LEN; i++) { buf[i] = '\0'; } /* ---- Normal_2 ----------------------------------------------- */ printf("Normal_2\n"); printf(DEBUG_LINE); strncpy(buf, EX_STR, BUF_LEN); printf("strncpy(buf, EX_STR, BUF_LEN);\n"); printf("result:string:%s [strlen(buf):%ld, sizeof(buf):%ld]\n", buf, strlen(buf), sizeof(buf)); for (i = 0; i < BUF_LEN; i++) { printf("buf[%d] = %d\n", i, buf[i]); } printf("buf[BUF_LEN] = %d (secretly watch.)\n\n", buf[BUF_LEN]); printf("***Not write '\\0' automatically!! (buf[%d] = %d)\n", BUF_LEN-1, buf[BUF_LEN-1]); printf("***Not write buf[BUF_LEN] (buf[%d] = %d)\n\n", BUF_LEN, buf[BUF_LEN]); /* not init */ /* for (i = 0; i < BUF_LEN; i++) { buf[i] = '\0'; } */ /* ---- Normal_3 ----------------------------------------------- */ printf("Normal_3\n"); printf(DEBUG_LINE); strncpy(buf, EX_STR2, BUF_LEN); printf("strncpy(buf, EX_STR2, BUF_LEN);\n"); printf("result:string:%s [strlen(buf):%ld, sizeof(buf):%ld]\n", buf, strlen(buf), sizeof(buf)); for (i = 0; i < BUF_LEN; i++) { printf("buf[%d] = %d\n", i, buf[i]); } printf("buf[BUF_LEN] = %d (secretly watch.)\n\n", buf[BUF_LEN]); printf("***automatically write '\\0' to buf[15]\n"); /* ---- Extra ------------------------------------------------- */ printf("\nExtra\n"); printf(DEBUG_LINE); strncpy(buf, EX_STR, 0); printf("strncpy(buf, EX_STR, 0);\n"); printf("result:string:%s [strlen(buf):%ld, sizeof(buf):%ld]\n", buf, strlen(buf), sizeof(buf)); for (i = 0; i < BUF_LEN; i++) { printf("buf[%d] = %d\n", i, buf[i]); } printf("buf[BUF_LEN] = %d (secretly watch.)\n\n", buf[BUF_LEN]); printf("Not write any.\n\n"); /* ---- Right usage ------------------------------------------- */ printf("Right usage\n"); printf(DEBUG_LINE); strncpy(buf, EX_STR, BUF_LEN); buf[BUF_LEN-1] = '\0'; for (i = 0; i < BUF_LEN; i++) { printf("buf[%d] = %d\n", i, buf[i]); } printf("buf[BUF_LEN] = %d (secretly watch.)\n\n", buf[BUF_LEN]); printf("strncpy(buf, EX_STR, BUF_LEN); after buf[BUF_LEN-1] = '\\0';"); return 0; }
コンパイル例
gcc -W -Wall -o nex2t_strncpy nex2t_strncpy.c
実行結果
./strncpy --------------------------------------------------------- use buffer buf[BUF_LEN] BUF_LEN=16 --------------------------------------------------------- EX_STR:0123456789abcdefghij [strlen(EX_STR):20, sizeof(EX_STR):21] (over buf[BUF_LEN] size!!) --------------------------------------------------------- EX_STR2:01234 [strlen(EX_STR2):5, sizeof(EX_STR2):6] (not over buf[BUF_LEN] size) --------------------------------------------------------- Init after --------------------------------------------------------- buf[0] = 0 buf[1] = 0 buf[2] = 0 buf[3] = 0 buf[4] = 0 buf[5] = 0 buf[6] = 0 buf[7] = 0 buf[8] = 0 buf[9] = 0 buf[10] = 0 buf[11] = 0 buf[12] = 0 buf[13] = 0 buf[14] = 0 buf[15] = 0 buf[BUF_LEN] = 0 (secretly watch.) Normal_1 --------------------------------------------------------- strncpy(buf, EX_STR, 5); result:string:01234 [strlen(buf):5, sizeof(buf):16] buf[0] = 48 buf[1] = 49 buf[2] = 50 buf[3] = 51 buf[4] = 52 buf[5] = 0 buf[6] = 0 buf[7] = 0 buf[8] = 0 buf[9] = 0 buf[10] = 0 buf[11] = 0 buf[12] = 0 buf[13] = 0 buf[14] = 0 buf[15] = 0 buf[BUF_LEN] = 0 (secretly watch.) Normal_2 --------------------------------------------------------- strncpy(buf, EX_STR, BUF_LEN); result:string:0123456789abcdef [strlen(buf):16, sizeof(buf):16] buf[0] = 48 buf[1] = 49 buf[2] = 50 buf[3] = 51 buf[4] = 52 buf[5] = 53 buf[6] = 54 buf[7] = 55 buf[8] = 56 buf[9] = 57 buf[10] = 97 buf[11] = 98 buf[12] = 99 buf[13] = 100 buf[14] = 101 buf[15] = 102 buf[BUF_LEN] = 0 (secretly watch.) ***Not write '\0' automatically!! (buf[15] = 102) ***Not write buf[BUF_LEN] (buf[16] = 0) Normal_3 --------------------------------------------------------- strncpy(buf, EX_STR2, BUF_LEN); result:string:01234 [strlen(buf):5, sizeof(buf):16] buf[0] = 48 buf[1] = 49 buf[2] = 50 buf[3] = 51 buf[4] = 52 buf[5] = 0 buf[6] = 0 buf[7] = 0 buf[8] = 0 buf[9] = 0 buf[10] = 0 buf[11] = 0 buf[12] = 0 buf[13] = 0 buf[14] = 0 buf[15] = 0 buf[BUF_LEN] = 0 (secretly watch.) ***automatically write '\0' to buf[15] Extra --------------------------------------------------------- strncpy(buf, EX_STR, 0); result:string:01234 [strlen(buf):5, sizeof(buf):16] buf[0] = 48 buf[1] = 49 buf[2] = 50 buf[3] = 51 buf[4] = 52 buf[5] = 0 buf[6] = 0 buf[7] = 0 buf[8] = 0 buf[9] = 0 buf[10] = 0 buf[11] = 0 buf[12] = 0 buf[13] = 0 buf[14] = 0 buf[15] = 0 buf[BUF_LEN] = 0 (secretly watch.) Not write any. Right usage --------------------------------------------------------- buf[0] = 48 buf[1] = 49 buf[2] = 50 buf[3] = 51 buf[4] = 52 buf[5] = 53 buf[6] = 54 buf[7] = 55 buf[8] = 56 buf[9] = 57 buf[10] = 97 buf[11] = 98 buf[12] = 99 buf[13] = 100 buf[14] = 101 buf[15] = 0 buf[BUF_LEN] = 0 (secretly watch.) strncpy(buf, EX_STR, BUF_LEN); after buf[BUF_LEN-1] = '\0';
検索用タグ C言語 strncpy 安全
PR
2012/06/30 (Sat.) Comment(0) C言語
Comments