Secure Coding in C - const, enum, 변수재활용, 선언 룰

markyang92·2021년 6월 14일
0

Secure Coding in C

목록 보기
2/7

고정적인 값 = symbolic const

  • 코드 상에서 literal 을 사용할 경우, 가독성이 떨어질 수 있다.
    • 가급적 literal 을 직접 사용하기 보다는 symbolic 상수을 사용해 적절한 이름을 붙여 코드의 의도를 명확히 해야한다.
    1. const 객체
    2. enum
    3. 객체형 매크로
방식평가 시점메모리 소비 유무디버깅 시 심볼타입 체크컴파일 타임 상수 표현식
const 지정런타임OOOX
열거형컴파일 타임XOOO
매크로전처리XXXO

const 객체

  • 장점
    • const로 지정된 객체는 특정 스코프 내에서 사용가능
    • 컴파일러가 타입 체크 제공
    • 디버깅 도구 사용 시, 객체의 이름을 나타낼 수 있음
  • 단점
    • 각 객체는 메모리 사용하며 런타임에 약간의 오버헤드 유발
    • 컴파일 타임에서 정수형 상수가 필요한 곳에서는 사용할 수 없음
      • struct 내부 bit 단위 로 정의된 멤버
      • 배열의 크기(가변 배열 예외)
      • 열거형 상수 값
      • case 상수 값

enum

  • 장점
    • 열거형 상수는 정수로 나타낼 수 있는 정수형 상수 표현식(int)를 나타낼 때 사용
    • const와 달리 메모리 사용 XX
  • 단점
    • 값의 타입을 정의할 수 없음
    • 항상 int
  • 열거형열거자정수형으로 매핑된다.
  • 열거자의 값이 중복되면 모호성으로 인한 에러 발생

열거형 선언 법

  1. 명시적 선언하지 않는다.
  2. 첫 번째 열거자에 대해서만 값을 지정
  3. 모든 열거자에 대해 명시적으로 값 지정

객체형 매크로

  • 전처리 단계에서 사용되는 객체형 매크로(object-like macro)
#define identifier replacement-list
  • 객체형 매크로는 전처리기에 의해 치환되는 구조, 컴파일 과정에서는 매크로 심볼 볼 수 없음
    • 그래서 대부분의 컴파일러들은 매크로 이름을 따로 저장하고 디버거에 전달
  • 매크로는 다음 이름으로 적용될 수 있는 스코프 규칙들을 고려하지 않았기 때문에 의도하지 않는 방식으로 치환되어 unexpected behaviour 유발 가능
  • 객체형 매크로는 메모리 소비X, 포인터로 가리킬 수 없음
  • C 프로그래머들은 심볼릭 상수로 객체형 매크로를 사용하는 편이다.

const

DCL-00. immutable object는 const!

  • immutable 객체const 로 보장해야한다.

1. 부적절한 코드

  • 다음 코드의 객체의 값의도치 않게 변경되고 있다.

1 해결방법

  • const 붙이자!

scope 內 변수 재사용 금지

DCL-01. 내부 스코프에서 변수 이름을 재사용하지 말 것

  • 변수의 이름을 재사용할 경우, 코드 상에서 혼란을 가중
  1. global 변수가 사용되는 범위에서 어떤 변수든 중복해서 전역 변수 이름을 사용하면 안된다.
  2. 어떤 블록 안에서 이미 사용되고 있는 변수동일한 이름으로 다른 블록에서 선언하면 안된다.
  3. 여튼 수명 다한 객체 참조는 매우 위험하다!!

1. 부적절한 코드

  • local 변수global 변수를 가린다!!!!

변수 재활용

1. 부적절한 코드

  • 수명을 다한 local 객체global 변수가 참조하여 임의의 코드를 수행할 수 있는 위험성 존재



1. 해결 방법

  • 전역 포인터유효 객체(메모리 할당)하여 가리키게한다.



지역변수 포인터

2. 부적절한 코드

  • 다음 코드는 지역 객체의 주소를 반환하고 있다.

    arr의 주소를 받고 싶었는데, main함수의 pArr의 주소를 얻는다.
    지역변수는 함수를 나가면, 없어지기 때문
    진짜 할당하려면 malloc으로 힙 할당 해야함

2. 해결 방법

  1. main에서 미리 할당하고 넘겨준다.

  2. 함수에서 malloc으로 힙할당


선언

함수 선언은 앞에 반드시

  • 함수 선언 시 반드시 함수의 선언 정보가 존재해야한다.
    • 컴파일러가 타입 정보를 정확하게 체크할 수 있도록!!
    • 함수의 선언 정보가 없는 상태로 함수를 호출할 경우, 컴파일러는 경고를 내지만 에러는 발생하지 않음

함수 선언은 미리

#include <stdio.h>

int func(int a, int b, int c); // 전처리문이나 미리 선언해 함수의 선언 정보를 컴파일러에게 알려주자!

Function Pointer Variable

#include <stdio.h>

int add(int a, int b){  // 컴파일러 단에서 Error 방지!
    return a + b;
}

int main(){
    int(*fp)(int); // Error !!
    ...
}

추상 데이터 타입(ADT) 사용

  • 추상 데이터 타입(ADT, Abstract Data Type)은 프로그램의 대상이 되는 사물이나 현상을 추상화하여 정의한 것
    • 추상 데이터 타입을 사용하면 그 타입의 세부적인 구현을 감출 수 있기 때문에, 정보 은닉(information hiding)을 할 수 있다.
  1. 헤더 파일에 함수 선언
  2. 각 파일에서 구현
    (e.g. stack.h stack.c main.c)

1. 부적절한 코드

  • 아래의 코드는 스택 자료구조의 내부 구조가 노출되어 외부로부터 내부 데이터를 보호 할 수 없다.


1. 해결 방법

  • 불완전한 타입으로 선언한 후, 포인터를 사용하라!
profile
pllpokko@alumni.kaist.ac.kr

0개의 댓글