일반적으로 우리가 사용하는 assert()는 runtime에서 사용할 수 있다.
UPX 소스를 분석하던 중 독특한 define이 눈에 들어왔는데 그것은..
COMPILE_TIME_ASSERT(sizeof(pe_header_t) == 248)
와 같은 구문이었다.
딱 봤을때 신기하다는 생각이 들지 않는가?
compile하는 시점에서 assertion을 수행한다는 것 자체가 신기할 따름이었다.
그래서 그 define부분을 보고 분석 한 결과..
#define COMPILE_ASSERT(x) switch(0) case 1: case !(x): break; #define COMPILE_ASSERT2(x) typedef int __acc_cta_t[1-!(x)];
와 같은 define문을 간추려 내었다.
(UPX에서는 각 컴파일러의 버전에 맞게 되어 있지만 여기서는 생략한다)
즉, x를 조건식으로 본 뒤 switch에서 동일한 값의 case가 있을때 오류나는 원리를 이용하여 조건을 검사하는 것이다.
두번째는, 배열의 첨자는 0이 될 수 없다는 오류 메시지를 출력하는 컴파일러를 위해 있는 구문이며, 배열의 크기가 1-!(x), 즉 참일 경우에는 1-0 이 되지만 거짓일 경우에는 1-1이 되서, 결국 배열의 첨자가 0이라는 오류를 출력하게 하는 구문이다.
참고로 typedef는 여러번 겹쳐도 되기 때문에 문제가 되질 않는다.



Attribution/Share Alike 2.0 license






