Функции вызова с правильным количеством и типом аргументов
Функции вызова с правильным количеством и типом аргументов. [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. |
| Пройти либо O_APPEND|O_WRONLY или O_APPEND|O_RDWR в качестве режима доступа. |
Вы передаете флаги состояния O_APPEND и O_TRUNC вместе с open функция. |
| В зависимости от того, что вы намерены сделать, передайте один из двух режимов. |
Вы передаете флаг состояния O_ASYNC в open функция. | В определенных реализациях режим O_ASYNC не включает операции ввода-вывода, управляемые сигналом. | Используйте fcntl(pathname, F_SETFL, O_ASYNC); вместо этого. |
Исправление зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Исправление может быть реализовано для любого события в последовательности. Если сведения о результатах не отображают историю событий, можно выполнить обратную трассировку, щелкнув правой кнопкой мыши параметры в исходном коде и просмотреть предыдущие связанные события. См. также раздел Интерпретация результатов поиска ошибок в интерфейсе пользователя Polyspace Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.
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.
Если поместить указатель функции на другой указатель функции с другим аргументом или возвращаемым типом, а затем использовать последний указатель функции для вызова функции, поведение не будет определено.
Избегайте приведения между двумя указателями функций с несоответствием в аргументах или возвращаемых типах.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.
#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- завершенная строка. | Поведение функции не определено. | Пройти а NULL- завершенная строка для функций манипуляции строками. |
Функции обработки файлов в stdio.h такие как fputc и fread | FILE* аргумент указателя может иметь значение NULL. | Поведение функции не определено. | Протестируйте FILE* указатель для NULL перед использованием в качестве аргумента функции. |
Функции обработки файлов в unistd.h такие как lseek и read | Аргумент дескриптора файла может иметь значение -1. | Поведение функции не определено. Большинство реализаций | Проверьте возвращаемое значение Если возвращаемое значение равно -1, проверьте значение |
| Аргумент дескриптора файла представляет собой закрытый дескриптор файла. | Поведение функции не определено. | Закройте дескриптор файла только после завершения его использования. Либо повторно откройте дескриптор файла, прежде чем использовать его в качестве аргумента функции. | |
Функции создания имен каталогов, такие как mkdtemp и mkstemps | Последние шесть символов шаблона строки не являются XXXXXX. | Функция заменяет последние шесть символов строкой, делающей имя файла уникальным. Если последние шесть символов не являются XXXXXX, функция не может создать достаточно уникальное имя каталога. | Проверка, являются ли последние шесть символов строки XXXXXX перед использованием строки в качестве аргумента функции. |
Функции, связанные с переменными среды, такими как getenv и setenv | Строковый аргумент: "". | Поведение определяется реализацией. | Проверка строкового аргумента для "" перед использованием в качестве getenv или setenv аргумент. |
Строковый аргумент заканчивается знаком равенства, =. Например, "C=" вместо "C". | Поведение определяется реализацией. | Не завершайте строковый аргумент =. | |
Функции обработки строк, такие как strtok и strstr |
| В некоторых реализациях эти краевые случаи не обрабатываются. | Проверить строку для "" перед использованием в качестве аргумента функции. |
Исправление зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Исправление может быть реализовано для любого события в последовательности. Если сведения о результатах не отображают историю событий, можно выполнить обратную трассировку, щелкнув правой кнопкой мыши параметры в исходном коде и просмотреть предыдущие связанные события. См. также раздел Интерпретация результатов поиска ошибок в интерфейсе пользователя Polyspace Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.
NULL Указатель передан как strnlen Аргумент#include <string.h>
#include <stdlib.h>
enum {
SIZE10 = 10,
SIZE20 = 20
};
int func() {
char* s = NULL;
return strnlen(s, SIZE20);
}
В этом примере NULL указатель передается как strnlen аргумент вместо NULL- завершенная строка.
Перед выполнением анализа кода укажите компилятор 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);
}
Примечание
В коде C++ эта проверка применяется к функциям, указанным как extern "C".
Несоответствие объявления функции возникает, когда прототип extern "C" функция не соответствует ее определению. Несоответствие типов аргументов определения функции и прототипа функции может зависеть от среды. Polyspace ® считает два типа совместимыми, если они имеют одинаковый размер и соответствие в используемой среде. Например, если указано-target как i386, Полиспейс считает long и int как совместимые типы.
В C++, если функция не указана как extern "C" и его прототип не соответствует какому-либо определению функции, компилятор рассматривает прототип как прототип неопределенной перегрузки функции. Polyspace не помечает вызовы таких неопределенных функций.
Средство проверки не помечает эту проблему в анализе Polyspace по умолчанию в качестве кода. См. раздел Шашки, деактивированные в Polyspace как анализ кода по умолчанию (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. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.