我想写 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;
}

我一直在试图拿出一个语义补丁,它这样做,但我有麻烦它做我想做的。只需添加NULL测试无条件地是没有问题的,麻烦的是不这样做时,没有必要。以下是我目前有:

// 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();
+}

这个麻烦的是,它并不排除确定的情况下,我不知道如何将两个规则连接。谁能帮我这个?

只要为100%清楚,我跑COCCINELLE后要输出的是以下内容:

#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;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top