본문 바로가기

CERT C/표현식

[CERT C/표현식] (1) 연산자 우선순위의 중요성

의미

연산자 우선순위란, C 언어에서 사용되는 수 많은 연산자들의 연산 순서를 의미한다.

보통 +, -보다 *, / 가 우선이고 비트 연산자 우선순위 정도까지 생각을 하는 분이 많을 것이라고 생각하는데 우리가 코드에서 보는 모든 기호에 우선순위가 부여되어있고 그 우선순위를 이해하다보면 포인터, 배열 등의 개념의 이해에 큰 도움이 될 것이다.

동작 방식

순위 명칭 연산자 결합방향
1차 연산자 () [] . -> ->
2 단항 연산자 + - ! ~ (type) sizeof ++ -- & * <-
3 승법 연산자 * / % ->
4 가법 연산자 + -
5 Shift 연산자 << >> 
6 관계 연산자 < > <= >=
7 등가 연산자 == !=
8 bit 곱 연산자 &
9 bit 차 연산자 ^
10 bit 합 연산자 |
11 논리곱 연산자 &&
12 논리합 연산자 ||
13 조건 연산자 ?: ->
14 대입 연산자 = += -= *= /= %= <<= 
>>= &= |=
<-
15 순차 연산자 , ->

문제 코드 1. 연산자 우선순위를 나타내려면 괄호를 사용하는 것이 좋다.

출력을 예상해보기

#include <stdio.h>
typedef int bool;
enum { false, true };


int main()
{
    int x = 3;
    // x 변수의 최하위 비트를 검사하는 경우
    x & 1 == 0;

    int *p;
    int num = 3;
    p = &num;

    // p가 가리키는 것을 증가하려는 경우
    *p++;

    int num = 10;

    // num이 10과 같지 않은가를 테스트하는 경우
    bool res  = !num == 10;
    return 0;
}

출력 :

물론, print하는 경우가 없으므로 출력이 되지 않지만 문제가 되는 부분은 3 부분이 있다.

 

취약점 분석 및 해결 코드 1

분석 

 

(1) x & 1== 0 에서 == 연산자가 우선이다.

(2) *p++ 에서 ++이 *보다 우선이다.

(3) == 보다 !이 우선순위이므로 비교한 결과의 부정을 나타낼 수가 없다.

 

해결 방법 : 연산자 우선순위를 나타내려면 괄호를 이용하자. 

               *** 모든 연산자의 우선순위를 외울 수 없으므로 괄호를 통해서 원하는 연산 순위대로 수정하는 것이 좋다.

#include <stdio.h>
typedef int bool;
enum { false, true };


int main()
{
    int x = 3;
    // x 변수의 최하위 비트를 검사하는 경우
    (x & 1) == 0;

    int *p;
    int num = 3;
    p = &num;

    // p가 가리키는 것을 증가하려는 경우
    (*p)++;

    // num이 10과 같지 않은가를 테스트하는 경우
    bool res  = !(num == 10);
    return 0;
}

POINT

  • 연산자 우선순위 표를 참고하고 자주 사용하는 부분은 기억하고 나머지는 자주 참조하자.
  • 연산자 우선순위를 좀 알더라도 정확히 괄호를 통해서 확실히 프로그램이 동작하게 하자

참조


EXP00-C. Use parentheses for precedence of operation

 

 

wiki.sei.cmu.edu/confluence/display/c/EXP00-C.+Use+parentheses+for+precedence+of+operation