Используя объект, перезаписанный getenv, localeconv, setlocale, и strerror
Неправильное употребление возвращаемого значения от неповторно используемой стандартной функции происходит, когда эти события происходят в этой последовательности:
Вы указываете на буфер, возвращенный в неповторно используемую стандартную функцию, такую как getenv или setlocale.
user = getenv("USER");Вы вызываете ту неповторно используемую стандартную функцию снова.
user2 = getenv("USER2");Вы используете или разыменовываете указатель от первого шага, ожидая, что буфер останется немодифицированными начиная с того шага. Тем временем вызов на втором шаге изменил буфер.
Например:
var=*user;
В некоторых случаях, дефектная сила появляются, даже если вы не вызываете getenv функционируйте во второй раз, но просто возвратите указатель. Например:
char* func() {
user=getenv("USER");
.
.
return user;
}Для получения информации о котором функции покрыты этим дефектом, видят документацию относительно неповторно используемых стандартных функций.
Стандарт C позволяет неповторно используемые функции, такие как getenv возвратить указатель на статический буфер. Поскольку буфер является статическим, второй вызов getenv изменяет буфер. Если вы продолжаете использовать указатель, возвращенный в первый вызов мимо второго вызова, вы видите неожиданные результаты. Буфер, на который это не указывает больше, имеет значения от первого вызова.
Дефект появляется, даже если вы не вызываете getenv во второй раз, но просто возвращают указатель. Причина состоит в том, что кто-то вызывающий вашу функцию может использовать возвращенный указатель после второго вызова getenv. Путем возврата указателя от вызова до getenv, вы делаете свою функцию небезопасной использовать.
То же объяснение верно для других неповторно используемых функций, покрытых этим дефектом.
После первого вызова getenv, сделайте копию буфера, на который указывает возвращенный указатель. После второго вызова getenv, используйте эту копию. Даже если второй вызов изменяет буфер, ваша копия является нетронутой.
getenv Используемый после второго вызова getenv#include <stdlib.h>
#include <string.h>
int func()
{
int result = 0;
char *home = getenv("HOME"); /* First call */
if (home != NULL) {
char *user = NULL;
char *user_name_from_home = strrchr(home, '/');
if (user_name_from_home != NULL) {
user = getenv("USER"); /* Second call */
if ((user != NULL) &&
(strcmp(user, user_name_from_home) == 0))
{
result = 1;
}
}
}
return result;
}В этом примере, указатель user_name_from_home выведен из указателя homeдомой точки к буферу, возвращенному от первого вызова до getenv. Поэтому user_name_from_home точки к местоположению в том же буфере.
После второго вызова getenv, буфер изменяется. Если вы продолжаете использовать user_name_from_home, можно получить неожиданные результаты.
Если вы хотите получить доступ к буферу от первого вызова до getenv мимо второго вызова сделайте копию буфера после первого вызова. Одна возможная коррекция должна использовать strdup функция, чтобы сделать копию.
#include <stdlib.h>
#include <string.h>
int func()
{
int result = 0;
char *home = getenv("HOME");
if (home != NULL) {
char *user = NULL;
char *user_name_from_home = strrchr(home, '/');
if (user_name_from_home != NULL) {
/* Make copy before second call */
char *saved_user_name_from_home = strdup(user_name_from_home);
if (saved_user_name_from_home != NULL) {
user = getenv("USER");
if ((user != NULL) &&
(strcmp(user, saved_user_name_from_home) == 0))
{
result = 1;
}
free(saved_user_name_from_home);
}
}
}
return result;
}
| Разрешимость: неразрешимый |
[1] Выписки из стандарта "Техническая характеристика ISO/IEC TS 17961 - 2013-11-15" воспроизводятся с соглашением о AFNOR. Только исходный и полный текст стандарта, как опубликовано Выпусками AFNOR - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.