> 백엔드 개발 > C++ > 본문

TIL CANnex K가 존재하지만 사용하면 안 됩니다.

DDD
풀어 주다: 2024-11-03 13:58:03
원래의
343명이 탐색했습니다.

TIL CAnnex K exists but you shouldn

Annex K는 기술명입니다. 다른 일반적인 키워드는 __STDC_LIB_EXT1__ 및 __STDC_WANT_LIB_EXT1__입니다. 부록 K는 sprintf_s() 및 scanf_s()와 같은 "보안" _s 접미사 항목을 정의합니다.

또한 Annex K(2015)에 대한 현장 경험 및 경계 확인 - cppreference.com 기술 문서를 확인하세요.

목표

_s() 함수의 요점은 무엇인가요? 그들은 "스트림이 null이거나, 문자열이 null이거나, bufsz가 0이거나, 버퍼가 지정된 길이를 초과하는 범위를 벗어나는 경우 제약 조건 처리기를 호출합니다."와 같은 더 많은 불변성에 대한 인수를 확인합니다. 좋은 생각인 것 같죠? 응! 그렇습니다!

요점은 다음과 같이 할 수 있다는 것입니다.

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>

int main() {
  printf_s("Hello %s!\n", "Alan Turing");
  return 0;
}
로그인 후 복사
로그인 후 복사

__STDC_WANT_LIB_EXT1__ 없이 작업을 수행하는 일반적인 방법과 비교하면 어떤가요?

행복한 길

FILE *file = fopen("hello.txt", "r");
// file is OK.
로그인 후 복사
FILE *file;
errno_t err = fopen_s(&file, "hello.txt", "r");
// file is OK
로그인 후 복사

슬픈 길

FILE *file = fopen("notexist.txt", "r");
// file is NULL, errno is set.
로그인 후 복사
FILE *file;
errno_t err = fopen_s(&file, "notexist.txt", "r");
// file is NULL, err is set.
로그인 후 복사

잘못된 경로

FILE *file = fopen(NULL, NULL);
// idk.
로그인 후 복사
FILE *file;
errno_t err = fopen_s(&file, NULL, NULL);
// Constraint violated. Abort with message.
로그인 후 복사

예. 파일에 로그인하고 아무 일도 일어나지 않은 것처럼 계속 진행하도록 제약 조건 처리기를 사용자 정의할 수 있습니다.

set_constraint_handler_s(ignore_handler_s);
set_constraint_handler_s(abort_handler_s);
set_constraint_handler_s(my_awesome_handler);
로그인 후 복사

일반적인 fopen()이 어떻게 동일한 반환 값(아마도 다른 errno)을 가지고 있는지 확인하여 다양한 수준의 오류를 나타냅니다. 이것이 바로 fopen_s()가 개선하려고 했던 것입니다. 적어도 그것은 내가 읽은 것입니다. 내 생각엔 Rust의 패닉!()과 반환된 Result가 비슷하다고 생각합니다. 또한 strcpy_s() 및 gets_s()와 같은 대상 버퍼 오버플로를 방지하기 위해 size_of_dest 인수를 제공하여 일부 버퍼 오버플로 공격을 중지하는 데 도움이 될 수 있습니다.

char* gets( char* str ); // (removed in C11)
char* gets_s( char* str, rsize_t n ); // (since C11, annex K)
로그인 후 복사

개행 문자가 발견되거나 파일 끝이 발생할 때까지 str이 가리키는 문자 배열로 stdin을 읽어옵니다. null 문자는 배열에 읽혀진 마지막 문자 바로 뒤에 기록됩니다. 개행 문자는 삭제되지만 버퍼에 저장되지는 ​​않습니다.

gets() 함수는 경계 검사를 수행하지 않으므로 이 함수는 버퍼 오버플로 공격에 매우 취약합니다. 안전하게 사용할 수 없습니다(프로그램이 stdin에 나타날 수 있는 것을 제한하는 환경에서 실행되지 않는 한). 이러한 이유로 이 기능은 C99 표준의 세 번째 정오표에서 더 이상 사용되지 않으며 C11 표준에서는 완전히 제거되었습니다. fgets() 및 gets_s()는 권장되는 대체 방법입니다.

경고: gets()를 사용하지 마십시오.

// BAD
char buffer[1000];
gets(buffer);
// ⚠️ Could write >1000 chars to `buffer`!
로그인 후 복사
// GOOD
char buffer[1000];
gets_s(buffer, sizeof(buffer));
// This will stop at 1000 chars.
로그인 후 복사

_s() 함수는 버퍼 오버플로가 발생할 수 있는 일반적인 장소를 중지하는 데 꽤 유용해 보입니다.

문제

모든 곳에서 구현되지는 않습니다. _s() 함수는 GNU의 glibc와 같은 libc 구현에서 사용할 수 없는 확장입니다. 멀티스레딩에 인체공학적이지 않고 strcpy_s()와 같은 작업에 sizeof(dest) 대신 sizeof(src)를 수행하는 일반적인 실수와 같은 다른 사소한 문제도 있지만 가용성 문제에 비하면 이 모든 것이 무색합니다.

내가 찾을 수 있는 대부분의 온라인 정보는 MSVC가 Annex K를 구현한 유일한 주요 컴파일러/libc임을 나타내는 것 같습니다.

이 멋진 _s() 함수가 코드를 컴파일해야 하는 모든 곳에 있지 않다면 다음과 같이 코드를 작성해야 합니다.

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>

int main() {
  printf_s("Hello %s!\n", "Alan Turing");
  return 0;
}
로그인 후 복사
로그인 후 복사

...strlen_s(), fopen_s() 또는 strcpy_s()를 수행하려는 모든 인스턴스에 대해. 미치게 만드는 좋은 방법이군요.

그래서 플랫폼에 종속적인 코드를 작성하지는 않을 것이 분명합니다단지 기본 printf() 및 strcpy()를 수행하기 위해

하지만 모든 #ifdef __STDC_LIB_EXT1__ #else 항목을 라이브러리에 래핑하는 것은 어떻습니까?

빠른 Google 검색을 통해 찾은 유망해 보이는 두 개의 라이브러리가 있습니다.
  • safec: Safe C Library 웹사이트 GitHub 페이지 ⭐335
  • sbaresearch/slibc: C11 Annex K "경계 검사 인터페이스" 구현 ISO/IEC 9899:2011 ⭐14

그래서... _s() 함수를 사용하고 싶지만(또는 보안 관련 요구 사항이 있는 경우) MSVC로만 제한하고 싶지 않다면 해당 ☝ 라이브러리 중 하나를 사용할 수 있습니다.

? 자세한 내용은 Annex K(2015) 및 경계 확인 - cppreference.com 기술 문서를 사용한 현장 경험을 확인하세요.

위 내용은 TIL CANnex K가 존재하지만 사용하면 안 됩니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿