2025
05
10
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)です。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | /* 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; } |
コンパイル例
1 | gcc -W -Wall -o nex2t_strncpy nex2t_strncpy.c |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | . /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 安全
2012/06/30 (Sat.) Comment(0) C言語
Comments