85.23 Secure 함수 사용하기
C 언어의 기본 함수들은 입력 값의 길이나 버퍼의 크기(문자 개수)를 설정할 수 없어 보안에 취약한 경우가 많습니다. 따라서 Visual Studio에서는 보안이 향상된 함수를 제공하며 기본 함수에 _s가 붙어 있습니다.
secure_function.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <wchar.h> int main() { int num1; char s1[20]; // 문자열은 버퍼의 크기를 넣어줌 scanf_s("%d %s", &num1, s1, _countof(s1)); printf("%d %s\n", num1, s1); wchar_t ws1[20]; // wchar_t 문자열은 문자열의 개수를 넣어줌 wscanf_s(L"%d %s", &num1, ws1, _countof(ws1)); wprintf(L"%d %s\n", num1, ws1); sprintf_s(s1, _countof(s1), "%s", "Hello, world!"); printf("%s\n", s1); swprintf_s(ws1, _countof(ws1), L"%s", L"Hello, world!"); wprintf(L"%s\n", ws1); strcat_s(s1, _countof(s1), "123"); printf("%s\n", s1); wcscat_s(ws1, _countof(ws1), L"123"); wprintf(L"%s\n", ws1); char s2[20]; wchar_t ws2[20]; strcpy_s(s2, _countof(s2), s1); printf("%s\n", s2); wcscpy_s(ws2, _countof(ws2), ws1); wprintf(L"%s\n", ws2); char s3[20] = "The Little Prince"; char *ptr1; char *next1; ptr1 = strtok_s(s3, " ", &next1); // next1에는 다음번에 자를 문자열의 포인터가 들어감 while (ptr1 != NULL) { printf("%s\n", ptr1); ptr1 = strtok_s(NULL, " ", &next1); } wchar_t ws3[20] = L"The Little Prince"; wchar_t *ptr2; wchar_t *next2; ptr2 = wcstok_s(ws3, L" ", &next2); // next2에는 다음번에 자를 문자열의 포인터가 들어감 while (ptr2 != NULL) { wprintf(L"%s\n", ptr2); ptr2 = wcstok_s(NULL, L" ", &next2); } return 0; }
실행 결과
10 Hello (입력) 10 Hello 20 world (입력) 20 world Hello, world! Hello, world! Hello, world!123 Hello, world!123 Hello, world!123 Hello, world!123 The Little Prince The Little Prince
먼저 scanf_s, wscanf_s 함수는 문자열을 입력받을 때 문자열 버퍼의 문자 개수(count)를 지정해야 합니다(버퍼 크기(size)가 아님). 숫자나 문자일 때는 문자 개수를 지정하지 않아도 됩니다.
scanf_s("%d %s", &num1, s1, _countof(s1)); wscanf_s(L"%d %s", &num1, ws1, _countof(ws1));
Visual Studio에서는 문자열 버퍼의 문자 개수를 구하는 _countof 매크로를 제공하는데 sizeof(s1) / sizeof(char)와 또는 sizeof(ws1) / sizeof(wchar_t)와 결과가 같습니다.
#define _countof __crt_countof #define __crt_countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
나머지 _s가 붙은 함수들도 문자열을 생성하거나 복사할 때 목적지 포인터의 문자 개수를 지정해서 사용하면 됩니다.
다음은 파일 처리 함수입니다.
secure_function_file.c
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *fp; fopen_s(&fp, "hello.txt", "w+"); // 파일 포인터의 주소를 넣음 fputs("Hello 100", fp); rewind(fp); char buffer[100] = { 0, }; int num1; fscanf_s(fp, "%s %d", buffer, _countof(buffer), &num1); printf("%s %d\n", buffer, num1); rewind(fp); memset(buffer, 0, sizeof(buffer)); // 버퍼 크기, 읽기 크기, 읽기 횟수를 지정 fread_s(buffer, sizeof(buffer), 20, 5, fp); printf("%s\n", buffer); rewind(fp); memset(buffer, 0, sizeof(buffer)); // 버퍼 크기와 읽기 크기를 같게. 읽기 크기는 1로 지정 fread_s(buffer, sizeof(buffer), sizeof(buffer), 1, fp); printf("%s\n", buffer); fclose(fp); return 0; }
실행 결과
Hello 100 Hello 100 Hello 100
fread_s 함수는 fread_s(buffer, sizeof(buffer), 20, 5, fp);와 같이 총 버퍼 크기 sizeof(buffer)를 먼저 지정해주고 읽기 크기, 읽기 횟수를 지정하면 됩니다.
Secure 함수에 대한 자세한 내용은 MSDN을 참조하세요.
- 보안이 강화된 CRT 함수 버전:
https://msdn.microsoft.com/ko-kr/library/wd3wzwts.aspx