본문 바로가기

CERT C/선언과 초기화

[CERT C/선언과 초기화] (1) 코드의 가독성을 높이기 위해 타입 정의를 사용하라

의미

C 언어 같은 경우, 함수 포인터를 이용한 함수들은 타입을 읽을 때 가독성이 떨어지는 경우가 많다. 아래 signal 함수로 예를 들어본다.

void(*signal(int signum, void (*handler)(int)))(int)

 

signal 함수를 반환하는 부분과 매개변수 부분으로 나누어보면
    
(1) signal 함수는 두 개의 파라미터를 가진다.
    
    signal(int signum, void (*handler)(int))
    
(2) signal 함수가 반환하는 값은
   
    void (*)(int);
    -> 함수 포인터 형이며 반환 값이 없고 int 매개변수를 받는 함수를 가르리키는 포인터이다.

문제 코드 1. 함수의 선언이 읽기도 어렵고 이해하기 힘들다.

#include <stdio.h>

int (*getFunction(int))(void);

int getFruits();
int getGrains();

int main()
{
    int (*func)(void);
    func = getFunction(1);
    func();
    func = getFunction(2);
    func();
    return 0;
}

int (*getFunction(int type))(void)
{
    int (*func)(void);

    switch(type)
    {
    case 1:
        func = getFruits;
        break;
    case 2:
        func = getGrains;
        break;
    }

    return func;
}

int getFruits()
{
    printf("getFruits() 함수가 선택되었습니다.\n");
    return 1;
}

int getGrains()
{
    printf("getGrains() 함수가 선택되었습니다.\n");
    return 1;
}

 

취약점 분석 및 해결 코드 1

해결 방법 : int (*)(void) 타입을 따로 정의해서 사용한다.

#include <stdio.h>

//int (*getFunction(int))(void);
typedef int(*Func)(void);
Func getFunction(int);

int getFruits();
int getGrains();
int res;

int main()
{
    Func func;
    func = getFunction(1);
    res = func();
    if(res != 1) printf("문제 발생\n");

    func = getFunction(2);
    res = func();
    if(res != 1) printf("문제 발생\n");

    return 0;
}

Func getFunction(int type)
{
    Func func;

    switch(type)
    {
    case 1:
        func = getFruits;
        break;
    case 2:
        func = getGrains;
        break;
    }

    return func;
}

int getFruits()
{
    printf("getFruits() 함수가 선택되었습니다.\n");
    return 1;
}

int getGrains()
{
    printf("getGrains() 함수가 선택되었습니다.\n");
    return 1;
}

 

POINT

  • 가독성이 떨어지는 타입(함수형 포인터 등)은 상황에 적절한 타입으로 재정의해서 사용한다.

참조


DCL01-C. Do not reuse variable names in subscopes

 

wiki.sei.cmu.edu/confluence/display/c/PRE00-C.+Prefer+inline+or+static+functions+to+function-like+macroswiki.sei.cmu.edu/confluence/display/c/PRE06-C.+Enclose+header+files+in+an+include+guardwiki.sei.cmu.edu/confluence/display/c/PRE10-C.+Wrap+multistatement+macros+in+a+do-while+loopwiki.sei.cmu.edu/confluence/display/c/DCL01-C.+Do+not+reuse+variable+names+in+subscopes