2009-11-11 3 views
4

Я хочу написать семантический патч для coccinelle, чтобы он добавил if (ptr == NULL) ... чеки после звонков в malloc там, где они отсутствуют.Добавление отсутствующих проверок NULL после malloc с 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); 
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 

@[email protected] 
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 [email protected] 
@[email protected] 
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; 
} 

ответ

6
 
// find calls to malloc 
@[email protected] 
expression ptr; 
position p; 
@@ 

[email protected] = malloc(...); 

// find ok calls to malloc 
@[email protected] 
expression ptr; 
position call.p; 
@@ 

[email protected] = malloc(...); 
... when != ptr 
(
(ptr == NULL || ...) 
| 
(ptr != NULL || ...) 
) 

// fix bad calls to malloc 
@depends on [email protected] 
expression ptr; 
position call.p; 
@@ 

[email protected] = malloc(...); 
+ if (ptr == NULL) return; 
+0

Этот патч не будет обрабатывать переменные, которые назначены в операторе объявления (например, «символ * PTR = malloc (100); "). См. Http://lists.diku.dk/pipermail/cocci/2009-November/000479.html для подсказок о том, как добавить. – hlovdal

+0

Этот список рассылки больше не доступен – estebarb

 Смежные вопросы

  • Нет связанных вопросов^_^