Coccinelle으로 Malloc 후 누락 된 널 검사 추가
-
19-09-2019 - |
문제
나는 의미 론적 패치를 쓰고 싶다 Coccinelle, 추가 할 수 있도록 if (ptr == NULL) ...
Malloc으로 전화를 한 후 누락 된 곳에서 확인합니다.
다음 입력 소스 코드가 있다고 가정 해 봅시다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// memory leaks ignored
static void OK_simple(void)
{
char *ptr;
ptr = malloc(100);
if (ptr == NULL) {
return;
}
strcpy(ptr, "abcd");
}
static void NOT_OK_missing_NULL_check(void)
{
char *ptr;
ptr = malloc(100);
strcpy(ptr, "abcd");
}
static void NOT_OK_NULL_check_too_late(void)
{
char *ptr;
ptr = malloc(100);
strcpy(ptr, "abcd");
if (ptr == NULL) {
return;
}
}
static void OK_code_between_allocation_and_NULL_check(void)
{
char *ptr;
ptr = malloc(100);
printf("The NULL test does not have to be put immediately after\n");
if (ptr == NULL) {
return;
}
strcpy(ptr, "abcd");
}
static void OK_two_allocations(void)
{
char *ptr1, *ptr2;
ptr1 = malloc(100);
ptr2 = malloc(100);
if (ptr1 == NULL) {
return;
}
if (ptr2 == NULL) {
return;
}
strcpy(ptr1, "abcd");
strcpy(ptr2, "abcd");
}
static void NOT_OK_two_allocations_with_one_missing_NULL_check(void)
{
char *ptr1, *ptr2;
ptr1 = malloc(100);
ptr2 = malloc(100);
if (ptr1 == NULL) {
return;
}
strcpy(ptr1, "abcd");
strcpy(ptr2, "abcd");
}
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
OK_simple();
NOT_OK_missing_NULL_check();
NOT_OK_NULL_check_too_late();
OK_code_between_allocation_and_NULL_check();
OK_two_allocations();
NOT_OK_two_allocations_with_one_missing_NULL_check();
return 0;
}
나는 이것을하는 의미 론적 패치를 만들려고 노력했지만, 내가 원하는 것을하는 데 어려움이 있습니다. 무조건 테스트를 무조건 추가하는 것은 문제가되지 않습니다. 문제는 필요하지 않은 경우에 문제가되지 않는 것입니다. 다음은 내가 현재 가지고있는 것입니다.
// this rule matches code that already have a NULL test
@already_have_proper_check@
statement S;
type T;
T* ptr;
expression E;
@@
ptr = malloc(E);
... when != ptr
if (ptr == NULL) S
//+dummy_change_just_to_verify_that_this_rule_matches();
// this rule adds NULL tests where missing
//@add_NULL_check depends on !already_have_proper_check@
@add_NULL_check@
type T;
//T* ptr != already_have_proper_check.ptr;
T* ptr;
expression E;
@@
ptr = malloc(E);
+if (ptr == NULL) {
+ insert_error_handling_here();
+}
이것의 문제는 그것이 OK 사례를 배제하지 않으며 두 규칙을 연결하는 방법을 이해하지 못한다는 것입니다. 누구든지 나를 도와 줄 수 있습니까?
Coccinelle을 실행 한 후 원하는 출력은 100% 명확 해지려면 다음과 같습니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// memory leaks ignored
static void OK_simple(void)
{
char *ptr;
ptr = malloc(100);
if (ptr == NULL) {
return;
}
strcpy(ptr, "abcd");
}
static void NOT_OK_missing_NULL_check(void)
{
char *ptr;
ptr = malloc(100);
if (ptr == NULL) {
insert_error_handling_here();
}
strcpy(ptr, "abcd");
}
static void NOT_OK_NULL_check_too_late(void)
{
char *ptr;
ptr = malloc(100);
if (ptr == NULL) {
insert_error_handling_here();
}
strcpy(ptr, "abcd");
if (ptr == NULL) {
return;
}
}
static void OK_code_between_allocation_and_NULL_check(void)
{
char *ptr;
ptr = malloc(100);
printf("The NULL test does not have to be put immediately after\n");
if (ptr == NULL) {
return;
}
strcpy(ptr, "abcd");
}
static void OK_two_allocations(void)
{
char *ptr1, *ptr2;
ptr1 = malloc(100);
ptr2 = malloc(100);
if (ptr1 == NULL) {
return;
}
if (ptr2 == NULL) {
return;
}
strcpy(ptr1, "abcd");
strcpy(ptr2, "abcd");
}
static void NOT_OK_two_allocations_with_one_missing_NULL_check(void)
{
char *ptr1, *ptr2;
ptr1 = malloc(100);
ptr2 = malloc(100);
if (ptr2 == NULL) {
insert_error_handling_here();
}
if (ptr1 == NULL) {
return;
}
strcpy(ptr1, "abcd");
strcpy(ptr2, "abcd");
}
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
OK_simple();
NOT_OK_missing_NULL_check();
NOT_OK_NULL_check_too_late();
OK_code_between_allocation_and_NULL_check();
OK_two_allocations();
NOT_OK_two_allocations_with_one_missing_NULL_check();
return 0;
}
해결책
// find calls to malloc @call@ expression ptr; position p; @@ ptr@p = malloc(...); // find ok calls to malloc @ok@ expression ptr; position call.p; @@ ptr@p = malloc(...); ... when != ptr ( (ptr == NULL || ...) | (ptr != NULL || ...) ) // fix bad calls to malloc @depends on !ok@ expression ptr; position call.p; @@ ptr@p = malloc(...); + if (ptr == NULL) return;
제휴하지 않습니다 StackOverflow