Почему в gcc (или glibc) не реализованы функции _s?

_s функции, такие как scanf_s, printf_s, кажется необязательным стандартом. MSVC реализовал эти функции, а gcc - нет.

Есть ли конкретная причина не реализовывать безопасные функции? Достаточно ли безопасен scanf glibc?


person suhdonghwi    schedule 06.06.2018    source источник
comment
Это может пролить свет на ситуацию с Приложением K: open -std.org/jtc1/sc22/wg14/www/docs/n1967.htm   -  person Christian Gibbons    schedule 06.06.2018
comment
Их вывод: Дизайн интерфейсов проверки границ, хотя и сделан из лучших побуждений, страдает от слишком большого количества проблем, которые нельзя исправить. Было замечено, что использование API-интерфейсов приводит к ухудшению качества и безопасности программного обеспечения, чем использование установленных подходов или современных технологий. Более эффективные и менее навязчивые подходы стали обычным явлением, и им часто отдают предпочтение как пользователи, так и эксперты по безопасности. Поэтому мы предлагаем либо удалить Приложение K из следующей версии стандарта C, либо исключить его из употребления, а затем удалить.   -  person Christian Gibbons    schedule 06.06.2018
comment
Разве функции приложения K не были с самого начала инициативой Microsoft? Или, по крайней мере, тот, в который М.С. был глубоко вовлечен?   -  person John Bollinger    schedule 06.06.2018
comment
Какую версию gcc вы используете? У меня версия 4.7.2, и она знает о _s безопасных версиях.   -  person lurker    schedule 06.06.2018
comment
@lurker: Где вы используете GCC? Проблема на самом деле в библиотеке C. Если вы используете GCC в Windows и он настроен так, чтобы знать о функциях в Microsoft C RunTime (CRT), вы сможете их использовать. Если вы не в Windows, функции обычно недоступны в локальной библиотеке C. Вы можете найти несколько реализаций надстроек, но они не обязательно полные. См. Статью N1967 для получения более подробной информации о том, что (недоступно) доступно.   -  person Jonathan Leffler    schedule 06.06.2018
comment
@JonathanLeffler под MINGW64, мне было интересно, может ли он предоставлять какие-то дополнительные услуги? Так что да, должно быть, Windows предоставляет дополнительные товары.   -  person lurker    schedule 06.06.2018
comment
@JohnBollinger: Более-менее. Функции Приложения K *_s() тесно связаны с *_s() функциями, которые Microsoft добавила в MSVC, но существенно отличаются от них. Да, я считаю, что Microsoft сыграла важную роль в создании отчета TR 24731-1, но результат отличался по ключевым аспектам от того, что MS уже выпустила в дебрях, и обратная совместимость тогда стала проблемой. MS не могла легко соответствовать стандарту, потому что это нарушило бы их обещания обратной совместимости.   -  person Jonathan Leffler    schedule 06.06.2018
comment
@lurker: В этом есть смысл. Насколько я понимаю, MinGW состоит в том, что в нем GCC работает под Windows, максимально используя службы и библиотеки Windows. Таким образом, он обеспечивает доступ к функциям MS CRT, включая функции *_s() - полезно знать. Однако он подчеркивает разницу между «компилятором» и «библиотеками», а также не переносится в большинство других сред. Функции *_s() по существу недоступны, кроме как на платформе MS.   -  person Jonathan Leffler    schedule 06.06.2018
comment
@JonathanLeffler Я понимаю разницу между библиотекой и компилятором, и это стоит здесь подчеркнуть. Сначала я предположил, что вместе с данной версией gcc он поставляется с соответствующим набором конкретных библиотек (что все это часть пакета), что, очевидно, не так.   -  person lurker    schedule 06.06.2018
comment
Также обратите внимание, что реализация scanf в glibc действительно включает модификатор выделения памяти Posix / TR-24731-2 (m), который во многих отношениях является превосходным интерфейсом.   -  person rici    schedule 06.06.2018


Ответы (1)


_s функции не являются обязательными (Приложение K стандарта C11). Многие считают их «не очень полезными».

В ответах на мой вопрос Используете ли вы безопасные функции TR-24731? вы можете найти информацию о том, где возникают проблемы. со стандартной спецификацией - например, важные различия между стандартом и реализацией Microsoft. TR 24731-1 был техническим отчетом комитета по стандартизации C. Отчет был включен почти дословно - с дополнительной, ранее опущенной функцией IIRC - в стандарт C11 как (необязательное, но «нормативное») Приложение K. Также есть TR 24731-2 для другого набора функций - без суффикса _s. . Он столкнулся с сопротивлением по другому набору причин.

Кроме того, перед комитетом по стандартизации C есть предложение удалить эти функции из следующей редакции стандарта:

Этот документ является прямым и убедительным прочтением причин, по которым функции TR-24731 (*_s()) не получили широкого распространения.

Основные причины включают:

  • Проблема обнаруживается только один раз, затем устраняется, и тогда функция *_s() не нужна.
  • Это очень затрудняет тестирование *_s() функций или кода, который их использует.
  • Нелегко интегрировать новые функции в старый код (что принесет наибольшую пользу).
  • Эти функции по своей сути замедляют работу программного обеспечения из-за обширных, но избыточных проверок.

См. Статью для более подробной информации. Статья заканчивается разделом:

Предлагаемое техническое исправление

Несмотря на то, что прошло более десяти лет с момента первоначального предложения и почти десять лет с момента ратификации ISO / IEC TR 24731-1: 2007, а также почти пять лет с момента введения интерфейсов проверки границ в стандарт C, жизнеспособных соответствующих реализаций не появилось. . API-интерфейсы по-прежнему вызывают споры, и разработчики продолжают отклонять запросы на реализацию.

Дизайн интерфейсов проверки границ, хотя и сделан из лучших побуждений, страдает от слишком большого количества проблем, которые необходимо исправить. Было замечено, что использование API-интерфейсов приводит к ухудшению качества и безопасности программного обеспечения, чем использование установленных подходов или современных технологий. Более эффективные и менее навязчивые подходы стали обычным явлением, и им часто отдают предпочтение как пользователи, так и эксперты по безопасности.

Поэтому мы предлагаем либо исключить Приложение K из следующей версии стандарта C, либо исключить его из употребления, а затем удалить.

person Jonathan Leffler    schedule 06.06.2018
comment
Честно говоря, единственная часть Приложения K, которая всегда должна быть реализована, - это memset_s и только для поддержки кода, чувствительного к безопасности. Тем не менее, было бы неплохо иметь strtok замену, тоже кроссплатформенную. - person Mgetz; 27.06.2018
comment
@Mgetz: используйте strtok_r() в Unix и strtok_s() в Windows; в остальном они совместимы. Или, если хотите, всегда вызывайте strtok_s() и используйте static inline char *strtok_s(char **ptr, const char *delim) { return strtok_r(ptr, delim); } в Unix. - person Jonathan Leffler; 27.06.2018
comment
О, я сделал это, потому что strtok было бы просто хорошо, если бы это было частью стандарта, а не счастливой случайностью. Я действительно поддерживаю потребность в memset_s, который нельзя оптимизировать. - person Mgetz; 27.06.2018
comment
@Mgetz: Я пошел и посмотрел на C11 §7.24.6.1 The memset функция и §K.3.7.4.1 memset_s функция, и полезное различие действительно является требованием: В отличие от memset, любой вызов функции memset_s должен оцениваться строго в соответствии с правилами абстрактной машины, как описано в (5.1.2.3). То есть любой вызов функции memset_s должен предполагать, что память, обозначенная s и n, может быть доступна в будущем и, следовательно, должна содержать значения, указанные c. - person Jonathan Leffler; 27.06.2018
comment
Это требование означает, что вызовы memset_s() нельзя оптимизировать, даже если на задаваемую переменную больше не ссылаются. Это, в свою очередь, позволяет программисту гарантировать, что пароли обнуляются, когда они больше не нужны, и выполнять другие подобные операции. Дополнительный аргумент на самом деле не нужен; дополнительная семантика, связанная с (не) оптимизацией, безусловно, полезна в небольшом, но значительном наборе вариантов использования. - person Jonathan Leffler; 27.06.2018
comment
@JonathanLeffler: Я думаю, более важным, чем конкретная функция memset_s, было бы общее средство, заставляющее компилятор синхронизировать состояния объектов абстрактной машины и состояние памяти, видимое ЦП. Использование обычного memset с последующей принудительной синхронизацией было бы эквивалентно memset_s, но код, заботящийся о безопасности, также нуждается в синхронизации для других целей. Например, что-то вроде unsigned u = *p; if (u < ARRAY_SIZE) array[u]++; может привести к уязвимости системы безопасности, если *p загружается один раз для сравнения и еще раз на этапе индексации. - person supercat; 28.06.2018