Функции вызова с правильным номером и типом аргументов
Функции вызова с правильным номером и типом аргументов.[1]
Эта проверка проверяет на наличие следующих проблем:
Неправильный режим доступа к файлам или состояние.
Ненадежное приведение указателя на функцию.
Стандартный вызов функции с неправильными аргументами.
Несоответствие объявления функции
Плохой режим доступа к файлам или состояние происходит, когда вы используете функции в fopen
или open
группа с недопустимыми или несовместимыми режимами доступа к файлам, флагами создания файлов или флагами состояния файлов в качестве аргументов. Для образца, для open
функция, примеры действительных:
Режимы доступа включают O_RDONLY
, O_WRONLY
, и O_RDWR
Флаги создания файлов включают O_CREAT
, O_EXCL
, O_NOCTTY
, и O_TRUNC
.
Флаги состояния файлов включают O_APPEND
, O_ASYNC
, O_CLOEXEC
, O_DIRECT
, O_DIRECTORY
, O_LARGEFILE
, O_NOATIME
, O_NOFOLLOW
, O_NONBLOCK
, O_NDELAY
, O_SHLOCK
, O_EXLOCK
, O_FSYNC
, O_SYNC
и так далее.
Дефект может возникнуть в следующих ситуациях.
Ситуация | Риск | Зафиксировать |
---|---|---|
Вы передаете пустой или недопустимый режим доступа к Согласно ANSI® Стандарт C, допустимые режимы доступа для
|
Некоторые реализации допускают расширение режима доступа, такого как:
Однако строка режима доступа должна начинаться с одной из допустимых последовательностей. | Передайте допустимый режим доступа к fopen . |
Вы передаете флаг состояния O_APPEND на open функция, не объединяя ее ни с одним из O_WRONLY или O_RDWR . |
The | Пройдите или O_APPEND|O_WRONLY или O_APPEND|O_RDWR как режим доступа. |
Вы передаете флаги состояния O_APPEND и O_TRUNC вместе с open функция. |
The | В зависимости от того, что вы намерены сделать, передайте один из двух режимов. |
Вы передаете флаг состояния O_ASYNC на open функция. | В некоторых реализациях режим O_ASYNC не включает операции ввода-вывода, управляемые сигналом. | Используйте fcntl(pathname, F_SETFL, O_ASYNC); вместо этого. |
Исправление зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Вы можете реализовать исправление на любом событии в последовательности. Если сведения о результате не отображают историю событий, можно отследить их с помощью опций правого щелчка в исходном коде и просмотреть предыдущие связанные события. Смотрите также Результаты интерпретации Bug Finder в интерфейсе пользователя Polyspace Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к своему результату или коду, чтобы избежать другой проверки. Смотрите Адрес Результаты Polyspace через исправления ошибок или обоснования.
fopen
#include <stdio.h>
void func(void) {
FILE *file = fopen("data.txt", "rw");
if(file!=NULL) {
fputs("new data",file);
fclose(file);
}
}
В этом примере режим доступа rw
недопустимо. Потому что r
указывает, что вы открываете файл для чтения и w
указывает, что вы создаете новый файл для записи, два режима доступа несовместимы.
r
или w
как режим доступаОдной из возможных коррекций является использование режима доступа, соответствующего тому, что вы намереваетесь сделать.
#include <stdio.h> void func(void) { FILE *file = fopen("data.txt", "w"); if(file!=NULL) { fputs("new data",file); fclose(file); } }
Ненадежное приведение указателя на функцию происходит, когда указатель на функцию приведен к другому указателю на функцию, который имеет другой аргумент или возвращаемый тип.
Этот дефект применяется только в том случае, если языком кода для проекта является C.
Если вы приведете указатель на функцию к другому указателю на функцию с другим аргументом или возвращаемым типом, а затем используете последний указатель на функцию для вызова функции, поведение не определено.
Избегайте приведения между двумя указателями на функцию с несовпадением аргументов или возвращаемых типов.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к своему результату или коду, чтобы избежать другой проверки. Смотрите Адрес Результаты Polyspace через исправления ошибок или обоснования.
#include <stdio.h>
#include <math.h>
#include <stdio.h>
#define PI 3.142
double Calculate_Sum(int (*fptr)(double))
{
double sum = 0.0;
double y;
for (int i = 0; i <= 100; i++)
{
y = (*fptr)(i*PI/100);
sum += y;
}
return sum / 100;
}
int main(void)
{
double (*fp)(double);
double sum;
fp = sin;
sum = Calculate_Sum(fp);
/* Defect: fp implicitly cast to int(*) (double) */
printf("sum(sin): %f\n", sum);
return 0;
}
Указатель на функцию fp
объявлен как double (*)(double)
. Однако, проходя его, чтобы функционировать Calculate_Sum
, fp
неявно приведено к int (*)(double)
.
Одной из возможных коррекций является проверка того, что указатель на функцию в определении Calculate_Sum
имеет тот же аргумент и тип возврата, что и fp
. Этот шаг гарантирует, что fp
неявно приведен к другому аргументу или возвращаемому типу.
#include <stdio.h> #include <math.h> #include <stdio.h> # define PI 3.142 /*Fix: fptr has same argument and return type everywhere*/ double Calculate_Sum(double (*fptr)(double)) { double sum = 0.0; double y; for (int i = 0; i <= 100; i++) { y = (*fptr)(i*PI/100); sum += y; } return sum / 100; } int main(void) { double (*fp)(double); double sum; fp = sin; sum = Calculate_Sum(fp); printf("sum(sin): %f\n", sum); return 0; }
Стандартный вызов функции с неправильными аргументами происходит, когда аргументы к определенным стандартным функциям не соответствуют требованиям к их использованию в функциях.
Например, аргументы в эти функции могут быть недопустимыми следующими способами.
Тип функции | Ситуация | Риск | Зафиксировать |
---|---|---|---|
Функции манипуляции строками, такие как strlen и strcpy | Аргументы указателя не указывают на NULL -terminated string. | Поведение функции не определено. | Передайте NULL -terminated string to string mandipulation functions. |
Функции обработки файлов в stdio.h такие как fputc и fread | The FILE* аргумент указателя может иметь значение NULL . | Поведение функции не определено. | Протестируйте FILE* указатель на NULL перед использованием в качестве аргумента функции. |
Функции обработки файлов в unistd.h такие как lseek и read | Аргумент дескриптора файла может быть -1. | Поведение функции не определено. Большинство реализаций | Проверьте возвращаемое значение Если возврат значение -1, проверьте значение |
Аргумент дескриптора файла представляет дескриптор закрытого файла. | Поведение функции не определено. | Закройте дескриптор файла только после того, как вы полностью закончите его использование. Кроме того, повторно откройте дескриптор файла перед использованием его в качестве аргумента функции. | |
Функции генерации имен директорий, такие как mkdtemp и mkstemps | Последние шесть символов шаблона строки не XXXXXX . | Функция заменяет последние шесть символов строкой, которая делает имя файла уникальным. Если последние шесть символов не XXXXXX функция не может сгенерировать достаточно уникальное имя директории. | Проверяйте, XXXXXX ли последние шесть символов строки перед использованием строки в качестве аргумента функции. |
Функции, связанные с переменными окружения, такими как getenv и setenv | Строковый аргумент "" . | Поведение определяется реализацией. | Протестируйте строковый аргумент для "" прежде чем использовать его как getenv или setenv аргумент. |
Строковый аргумент заканчивается знаком равенства, = . Для образца, "C=" вместо "C" . | Поведение определяется реализацией. | Не завершайте строковый аргумент = . | |
Функции обработки строк, такие как strtok и strstr |
| Некоторые реализации не обрабатывают эти краевые случаи. | Проверьте строку на "" перед использованием в качестве аргумента функции. |
Исправление зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Вы можете реализовать исправление на любом событии в последовательности. Если сведения о результате не отображают историю событий, можно отследить их с помощью опций правого щелчка в исходном коде и просмотреть предыдущие связанные события. Смотрите также Результаты интерпретации Bug Finder в интерфейсе пользователя Polyspace Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к своему результату или коду, чтобы избежать другой проверки. Смотрите Адрес Результаты Polyspace через исправления ошибок или обоснования.
NULL
Указатель прошел как strnlen
Аргумент#include <string.h>
#include <stdlib.h>
enum {
SIZE10 = 10,
SIZE20 = 20
};
int func() {
char* s = NULL;
return strnlen(s, SIZE20);
}
В этом примере a NULL
указатель передается следующим strnlen
аргумент вместо NULL
-terminated string.
Перед выполнением анализа кода укажите компилятор GNU. См. Compiler (-compiler)
.
NULL
-терминатная строкаПередайте NULL
-терминатная строка как первый аргумент strnlen
.
#include <string.h> #include <stdlib.h> enum { SIZE10 = 10, SIZE20 = 20 }; int func() { char* s = ""; return strnlen(s, SIZE20); }
Примечание
В коде С++ эта проверка применяется к функциям, которые заданы как extern "C"
.
Несоответствие объявления функции происходит, когда прототип extern "C"
функция не соответствует ее определению. Несоответствие типов аргументов определения функции и прототипа функции может зависеть от вашего окружения. Polyspace® рассматривает два типа как совместимые, если они имеют одинаковый размер и сигнальность в окружении, которую вы используете. Например, если вы задаете -target
как i386, Polyspace рассматривает long
и int
как совместимые типы.
В C++, если функция не задана как extern "C"
и его прототип не соответствует никакому определению функции, компилятор обрабатывает прототип как образец неопределенной перегрузки функции. Polyspace не помечает вызовы таких неопределенных функций.
Чекер не помечает эту проблему в Polyspace по умолчанию во время анализа You Code. Смотрите Checkers Deactivated in Polyspace как You Code Default Analysis (Polyspace Bug Finder Access).
Несоответствие объявления функции может привести к неопределенному поведению. Когда объявления функций заданы как extern "C"
несоответствия между определением и объявлением функции могут вызывать только предупреждения во время компиляции, в результате чего код компилируется, но ведет себя неожиданным образом.
Прежде чем вы вызовете функцию, предоставьте ее полный прототип, даже если вы задаете функцию позже в том же файле.
Избегайте любого несоответствия между числовыми аргументами в объявлении прототипа функции и определении функции.
Избегайте любого несоответствия между типами аргументов объявления прототипа функции и определением функции.
// file1.c extern "C" void foo(int iVar){ //... } extern "C" void bar(int iVar){ //... } extern "C" void fubar(int A, ...){ //... } |
//prototype.h extern "C" void foo(void); extern "C" void fubar(int A, ...); extern "C" void bar(long iVar); |
//file2.c //file2.c #include"prototype.h" void call_funcs(){ int iTemp; float fTemp; long lTemp; foo(); //Noncompliant bar(lTemp);//Noncompliant in x86_64 fubar(iTemp,fTemp);//Compliant } |
В этом примере функции foo
, bar
, и fubar
определяются в файле file1.c
. Их прототипы заявлены в prototype.h
. Затем эти функции вызываются в файле file2.c
.
Функция foo
определяется как int
аргумент, но его прототип объявлен без какого-либо аргумента. Из-за этого несоответствия Polyspace помечает вызов функции.
Функция bar
определяется как int
аргумент, но его прототип объявлен с long
аргумент. Эти два типа несовместимы с x86_64
окружение. Когда вы задаете -target
как x86_64
, Polyspace помечает вызов функции.
Вызов вариадной функции fubar
является совместимым, поскольку его сигнатура вызова, прототип и определение совпадают.
Исправление этого дефекта состоит в том, чтобы объявить полные и точные прототипы для вызываемых функций. В этом случае исправьте возникшие проблемы, разрешив несоответствия между определением функции и объявлением прототипа. Обновите вызовы функций так, чтобы они совпадали с обновленными прототипами.
// file1.c extern "C" void foo(int iVar){ //... } extern "C" void bar(int iVar){ //... } extern "C" void fubar(int A, ...){ //... } |
//prototype.h extern "C" void foo(int); extern "C" void fubar(int A, ...); extern "C" void bar(int iVar); |
//file2.c //file2.c #include"prototype.h" void call_funcs(){ int iTemp; float fTemp; long lTemp; foo(iTemp); //Compliant bar(iTemp);//Compliant in x86_64 fubar(iTemp,fTemp);//Compliant } |
Группа: 02. Выражения (EXP) |
[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.
ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.
Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.