programing tip

TR 24731 '안전'기능을 사용하십니까?

itbloger 2020. 10. 30. 07:47
반응형

TR 24731 '안전'기능을 사용하십니까?


는 ISO C위원회 ( ISO / IEC JTC1 / SC21 / WG14는 ) 발표했다 TR 24731-1 및 중이다 TR 24731-2 :

TR 24731-1 : C 라이브러리 확장 파트 I : 경계 검사 인터페이스

WG14는 더 안전한 C 라이브러리 기능에 대한 TR을 개발하고 있습니다. 이 TR은 종종 버퍼 길이와 함께 추가 매개 변수를 추가하여 기존 프로그램을 수정하도록 지향됩니다. 최신 초안은 문서 N1225에 있습니다. 근거는 문서 N1173에 있습니다. 이것은 기술 보고서 ​​유형 2가 될 것입니다.

TR 24731-2 : C 라이브러리 확장-파트 II : 동적 할당 기능

WG14는 더 안전한 C 라이브러리 기능에 대한 TR을 개발하고 있습니다. 이 TR은 버퍼 길이에 대한 추가 매개 변수 대신 동적 할당을 사용하는 새 프로그램을 지향합니다. 최신 초안은 문서 N1337에 있습니다. 이것은 기술 보고서 ​​유형 2가 될 것입니다.

질문

  • TR24731-1 기능을 지원하는 라이브러리 또는 컴파일러를 사용하십니까?
  • 그렇다면 어떤 컴파일러 또는 라이브러리와 어떤 플랫폼에 있습니까?
  • 이러한 기능을 사용하도록 코드를 수정 한 결과 버그를 발견 했습니까?
  • 어떤 기능이 가장 가치를 제공합니까?
  • 가치가 없거나 부정적인 가치를 제공하는 것이 있습니까?
  • 나중에 도서관을 사용할 계획입니까?
  • TR24731-2 작업을 추적하고 있습니까?

저는이 TR이 처음 (단일 TR이었을 때)부터이 TR에 대해 보컬 비평가를 해왔으며 내 소프트웨어에서 사용하지 않을 것입니다. 그들은 원인을 해결하는 대신 증상을 가리고, 동일한 목표를 훨씬 더 효과적으로 달성 할 수있는 기존 관행을 홍보하는 대신 잘못된 보안 감각을 제공하기 때문에 소프트웨어 설계에 부정적인 영향을 미칠 것이라고 생각합니다. 저는 혼자가 아닙니다. 사실 저는 이러한 TR을 개발하는위원회 외부의 주요 지지자 한 명도 알지 못합니다.

나는 glibc를 사용하고 있으므로 glibc의 수석 관리자 인 Ulrich Drepper 가 주제에 대해 다음 과 같이 말했듯 이이 말도 안되는 일을 처리하지 않아도 될 것임을 알고 있습니다 .

제안 된 safe (r) ISO C 라이브러리는 문제를 완전히 해결하지 못했습니다. ... 프로그래머의 삶을 더 힘들게 만들겠다고 제안하는 것은 도움이되지 않습니다. 그러나 이것은 정확히 제안 된 것입니다. ... 그들은 모두 더 많은 일을해야하거나 그냥 어리석은 일입니다.

그는 제안 된 여러 기능에 대한 자세한 문제를 계속 설명하고 다른 곳에서는 glibc가이를 지원하지 않을 것이라고 지적했습니다.

오스틴 그룹 (POSIX 유지 담당)은 TR에 대한 매우 비판적인 검토, 그들의 의견 및 여기에서 사용할 수있는위원회 응답을 제공 했습니다 . Austin Group 리뷰는 TR의 많은 문제를 자세히 설명하는 매우 훌륭한 작업을 수행하므로 여기서 개별 세부 사항을 다루지 않겠습니다.

따라서 결론은 다음과 같습니다. 저는 이것을 지원하거나 지원할 구현을 사용하지 않으며 이러한 기능을 사용할 계획이 없으며 TR에서 긍정적 인 가치를 볼 수 없습니다. 저는 개인적으로 TR이 어떤 형태로든 여전히 살아있는 유일한 이유는 광범위한 반대에도 불구하고 표준위원회를 통해 일을 당할 수있는 능력을 최근에 입증 한 Microsoft에 의해 강력하게 추진되고 있기 때문이라고 생각합니다. 이러한 기능이 표준화 된 경우 제안이 몇 년 동안 존재하고 실제 커뮤니티 지원을 얻지 못했기 때문에 널리 사용되지 않을 것이라고 생각합니다.


질문에 대한 직접적인 답변

나는 Robert의 대답을 좋아하지만 내가 제기 한 질문에 대한 견해도 있습니다.

  • TR24731-1 기능을 지원하는 라이브러리 또는 컴파일러를 사용하십니까?

    아뇨.

  • 그렇다면 어떤 컴파일러 또는 라이브러리와 어떤 플랫폼에 있습니까?

    이 기능은 MS Visual Studio (예 : MS VC ++ 2008 Edition)에서 제공한다고 믿으며 사용을 권장하는 경고가 있습니다.

  • 이러한 기능을 사용하도록 코드를 수정 한 결과 버그를 발견 했습니까?

    아직. 그리고 내 코드에서 많은 것을 발견 할 것으로 기대하지 않습니다. 내가 작업하는 다른 코드 중 일부-아마도. 그러나 나는 아직 확신하지 못했습니다.

  • 어떤 기능이 가장 가치를 제공합니까?

    printf_s () 함수 계열이 ' %n'형식 지정자를 받아들이지 않는다는 사실이 마음에 듭니다 .

  • 가치가 없거나 부정적인 가치를 제공하는 것이 있습니까?

    tmpfile_s()tmpnam_s()기능 끔찍한 실망입니다. 그들은 mkstemp()TOCTOU (time-of-check, time-of-use) 취약점이 없는지 확인하기 위해 파일을 생성하고 여는 방식으로 작업해야했습니다. 이 두 가지는 거의 가치를 제공하지 않습니다.

    나는 또한 그것이 strerrorlen_s()매우 작은 가치 제공 한다고 생각합니다 .

  • 나중에 도서관을 사용할 계획입니까?

    나는 그것에 대해 두 가지 생각을 가지고 있습니다. 표준 C 라이브러리를 통해 TR 24731의 기능을 구현하는 라이브러리 작업을 시작했지만 제대로 작동하는지 입증하는 데 필요한 단위 테스트의 양에 사로 잡혔습니다. 계속해야할지 모르겠습니다. Windows로 이식하고 싶은 코드가 있습니다 (주로 모든 플랫폼에서 지원을 제공하려는 비뚤어진 욕망에서-현재 수십 년 동안 Unix 파생 제품에서 작업하고 있습니다). 안타깝게도 MSVC 컴파일러의 경고없이 컴파일하려면 완벽하게 신뢰할 수있는 표준 C 라이브러리 함수를 사용하여 MSVC가 저를 괴롭히는 것을 방지하기 위해 코드를 석고로 만들어야합니다. 그리고 그것은 식욕을 돋 우지 않습니다. 그 기간에 걸쳐 개발 된 20 년 동안의 대부분의 시스템을 다루어야 할만큼 나쁘다. 누군가의 재미에 대한 생각을 처리해야하는 것은 (사람들이 필요하지 않을 때 TR 24731을 채택하게 만드는 것) 성가신 일입니다. 그래서 Unix와 Windows에서 동일한 인터페이스를 사용할 수 있도록 라이브러리 개발을 시작했습니다. 하지만 여기서 무엇을할지 모르겠습니다.

  • TR24731-2 작업을 추적하고 있습니까?

    질문에 대한 데이터를 수집하는 동안 표준 사이트에 갈 때까지 추적하지 않았습니다. asprintf()vasprintf()기능은 아마 가치가있다; 나는 그것들을 사용할 것입니다. 메모리 스트림 I / O 기능에 대해 잘 모르겠습니다. strdup()는 C 수준에서 표준화하는 것은 앞으로 큰 단계가 될 것입니다. 이것은 파트 1 (경계 확인) 인터페이스보다 덜 논쟁의 여지가있는 것 같습니다.

전반적으로 저는 1 부 '경계 검사 인터페이스'에 확신이 없습니다. 2 부 '동적 할당 함수'초안의 자료가 더 좋습니다.

나에게 달려 있다면 파트 1의 줄을 따라 다소 이동 하겠지만 C99 표준 C 라이브러리에서 a char *를 문자열의 시작 부분 (예 : strcpy()and strcat())으로 반환하는 인터페이스를 수정하여 시작에 대한 포인터를 반환하면 새 문자열의 끝에서 널 바이트에 대한 포인터를 반환합니다. 이것은 반복적으로 사용하는 코드에 의해 나타나는 2 차 동작을 피하는 것이 사소하기 때문에 일부 일반적인 관용구 (예 : 문자열을 다른 끝에 반복적으로 연결하는 것과 같은)를 더 효율적으로 만듭니다 strcat(). 교체는 모두 TR24731 버전처럼 출력 문자열의 null 종료를 보장합니다. 나는 검사 인터페이스 나 예외 처리 기능에 대해 전적으로 싫어하는 것이 아니다. 까다로운 사업입니다.


Microsoft의 구현은 표준 사양과 동일하지 않습니다.

업데이트 (2011-05-08)

질문을 참조하십시오 . 안타깝게도 TR24731 기능의 유용성에 치명적이지만 일부 기능의 정의는 Microsoft 구현과 표준간에 차이가있어 (나에게) 쓸모 없게 만듭니다. 내 대답은 인용합니다 vsnprintf_s().

예를 들어 TR 24731-1은 인터페이스 vsnprintf_s()가 다음과 같다고 말합니다 .

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdarg.h>
#include <stdio.h>
int vsnprintf_s(char * restrict s, rsize_t n,
                const char * restrict format, va_list arg);

불행히도 MSDN 은 인터페이스 vsnprintf_s()가 다음 같다고 말합니다 .

int vsnprintf_s(
   char *buffer,
   size_t sizeOfBuffer,
   size_t count,
   const char *format,
   va_list argptr 
);

매개 변수

  • buffer-출력을위한 저장 위치.
  • sizeOfBuffer-출력을위한 버퍼의 크기.
  • count-쓸 최대 문자 수 (종료 널 제외) 또는 _TRUNCATE.
  • format-형식 사양.
  • argptr-인수 목록에 대한 포인터.

이것은 단순히 유형 매핑의 문제가 아닙니다. 고정 인수의 수가 다르기 때문에 조정 불가능합니다. 또한 'sizeOfBuffer'와 'count'를 모두 갖는 것이 어떤 이점이 있는지 나에게 (그리고 아마도 표준위원회에서도) 명확하지 않습니다. 동일한 정보가 두 번 나타납니다 (또는 일반적으로 두 매개 변수에 대해 동일한 값으로 코드가 작성됩니다).

Similarly, there are also problems with scanf_s() and its relatives. Microsoft says that the type of the buffer length parameter is unsigned (explicitly stating 'The size parameter is of type unsigned, not size_t'). In contrast, in Annex K, the size parameter is of type rsize_t, which is the restricted variant of size_t (rsize_t is another name for size_t, but RSIZE_MAX is smaller than SIZE_MAX). So, again, the code calling scanf_s() would have to be written differently for Microsoft C and Standard C.

Originally, I was planning to use the 'safe' functions as a way of getting some code to compile cleanly on Windows as well as Unix, without needing to write conditional code. Since this is defeated because the Microsoft and ISO functions are not always the same, it is pretty much time to give up.


Changes in Microsoft's vsnprintf() in Visual Studio 2015

In the Visual Studio 2015 documentation for vsnprintf(), it notes that the interface has changed:

Beginning with the UCRT in Visual Studio 2015 and Windows 10, vsnprintf is no longer identical to _vsnprintf. The vsnprintf function complies with the C99 standard; _vnsprintf is retained for backward compatibility.

However, the Microsoft interface for vsnprintf_s() has not changed.


Other examples of differences between Microsoft and Annex K

The C11 standard variant of localtime_s() is defined in ISO/IEC 9899:2011 Annex K.3.8.2.4 as:

struct tm *localtime_s(const time_t * restrict timer,
                       struct tm * restrict result);

compared with the MSDN variant of localtime_s() defined as:

errno_t localtime_s(struct tm* _tm, const time_t *time);

and the POSIX variant localtime_r() defined as:

struct tm *localtime_r(const time_t *restrict timer,
                       struct tm *restrict result);

The C11 standard and POSIX functions are equivalent apart from name. The Microsoft function is different in interface even though it shares a name with the C11 standard.

Another example of differences is Microsoft's strtok_s() and Annex K's strtok_s():

char *strtok_s(char *strToken, const char *strDelimit, char **context); 

vs:

char *strtok_s(char * restrict s1, rsize_t * restrict s1max, const char * restrict s2, char ** restrict ptr);

Note that the Microsoft variant has 3 arguments whereas the Annex K variant has 4. This means that the argument list to Microsoft's strtok_s() is compatible with POSIX's strtok_r() — so calls to these are effectively interchangeable if you change the function name (e.g. by a macro) — but the Standard C (Annex K) version is different from both with the extra argument.

The question Different declarations of qsort_r() on Mac and Linux has an answer that also discusses qsort_s() as defined by Microsoft and qsort_s() as defined by TR24731-1 — again, the interfaces are different.


ISO/IEC 9899:2011 — C11 Standard

The C11 standard (December 2010 Draft; you could at one time obtain a PDF copy of the definitive standard, ISO/IEC 9899:2011, from the ANSI web store for 30 USD) does have the TR24731-1 functions in it as an optional part of the standard. They are defined in Annex K (Bounds-checking Interfaces), which is 'normative' rather than 'informational', but it is optional.

The C11 standard does not have the TR24731-2 functions in it — which is sad because the vasprintf() function and its relatives could be really useful.

Quick summary:

  • C11 contains TR24731-1
  • C11 does not contain TR24731-2
  • C18 is the same as C11 w.r.t TR24731.

Proposal to remove Annex K from the successor to C11

Deduplicator pointed out in a comment to another question that there is a proposal before the ISO C standard committee (ISO/IEC JTC1/SC22/WG14)

It contains references to some of the extant implementations of the Annex K functions — none of them widely used (but you can find them via the document if you are interested).

The document ends with the recommendation:

Therefore, we propose that Annex K be either removed from the next revision of the C standard, or deprecated and then removed.

I support that recommendation.

The C18 standard did not alter the status of Annex K. There is a paper N2336 advocating for making some changes to Annex K, repairing its defects rather than removing it altogether.


Ok, now a stand for TR24731-2:

Yes, I've used asprintf()/vasprintf() ever since I've seen them in glibc, and yes I am a very strong advocate of them.

Why?
Because they deliver precisely what I need over and over again: A powerful, flexible, safe and (relatively) easy to use way to format any text into a freshly allocated string.

I am also much in favor of the memstream functions: Like asprintf(), open_memstream() (not fmemopen()!!!) allocates a sufficiently large buffer for you and gives you a FILE* to do your printing, so your printing functions can be entirely ignorant of whether they are printing into a string or a file, and you can simply forget about how much space you will need.


Do you use a library or compiler with support for the TR24731-1 functions? If so, which compiler or library and on which platform(s)?

Yes, Visual Studio 2005 & 2008 (for Win32 development obviously).

Did you uncover any bugs as a result of fixing your code to use these functions?

Sort of.... I wrote my own library of safe functions (only about 15 that we use frequently) that would be used on multiple platforms -- Linux, Windows, VxWorks, INtime, RTX, and uItron. The reason for creating the safe functions were:

  • We had encountered a large number of bugs due to improper use of the standard C functions.
  • I was not satisfied with the information passed into or returned from the TR functions, or in some cases, their POSIX alternatives.

Once the functions were written, more bugs were discovered. So yes, there was value in using the functions.

Which functions provide the most value?

Safer versions of vsnprintf, strncpy, strncat.

Are there any that provide no value or negative value?

fopen_s and similar functions add very little value for me personally. I'm OK if fopen returns NULL. You should always check the return value of the function. If someone ignores the return value of fopen, what is going to make them check the return value of fopen_s? I understand that fopen_s will return more specific error information which can be useful in some contexts. But for what I'm working on, this doesn't matter.

Are you planning to use the library in the future?

We are using it now -- inside our own "safe" library.

Are you tracking the TR24731-2 work at all?

No.


No, these functions are absolutely useless and serve no purpose other than to encourage code to be written so it only compiles on Windows.

snprintf is perfectly safe (when implemented correctly) so snprintf_s is pointless. strcat_s will destroy data if the buffer is overflowed (by clearing the concatenated-to string). There are many many other examples of complete ignorance of how things work.

The real useful functions are the BSD strlcpy and strlcat. But both Microsoft and Drepper have rejected these for their own selfish reasons, to the annoyance of C programmers everywhere.

참고URL : https://stackoverflow.com/questions/372980/do-you-use-the-tr-24731-safe-functions

반응형