C 언어 시큐어 코딩 - Preprocessor-2
안전하지 않은 매크로 인자로 인한 부작용 발생을 피한다.
인자 중 하나를 두 번 이상 평가하거나 전혀 평가하지 않는 함수 형태 매크로는 안전하지 않다. 또한 할당, 증가, 감
소, 휘발성 액세스, 입출력 등의 부작용을 유발할 수 있는 함수 호출을 포함하는 매크로는 호출하지 않는다.
함수 형태 매크로 사용 시 전달 인자로 인한 부작용은 사용 방법에 대한 위험 요소이므로 그 책임은 매크로를 사용
한 프로그래머에게 있다. 하지만 이를 해결하기 위한 좋은 방법은 안전하지 않은 함수 형태의 매크로 작성을 하지
않는 것이다.
잘못된 코드 예제 - 1
매크로 인자로 인한 부작용을 보여주는 잘못된 코드 예제:
#define ABS(x) (((x) < 0) ? -(x) : (x))
void func(int n) {
/* Validate that n is within the desired range */
int m = ABS(++n);
/* ... */
}
이 예제에서 ABS() 매크로를 호출하면 다음과 같이 확장된다.
m = (((++n) < 0) ? -(++n) : (++n));
n을 두 번 증가시키는 것을 확인할 수 있다.
올바른 코드 예제 - 1.1
n의 증가 연산을 매크로 호출 전 수행하는 올바른 코드 예제:
#define ABS(x) (((x) < 0) ? -(x) : (x)) /* UNSAFE */
void func(int n) {
/* Validate that n is within the desired range */
++n;
int m = ABS(n);
/* ... */
}
추가로 ABS_UNSAFE()로 매크로 이름을 변경하여 매크로가 안전하지 않다는 것을 명확히하여 매크로를 사용하는
다른 프로그래머들의 안전한 사용을 도울 수 있으며, 부호 있는 정수에 대한 연산이 오버 플로우를 발생하지 않도록
한다.
올바른 코드 예제 - 1.2
ABS() 매크로를 대체하는 인라인 함수 iabs()를 정의한다. 모든 유형의 피연산자가 동작하는 매크로와는 달리 함수
는 데이터 형의 범위를 벗어난 인자를 자른다.
#include <complex.h>
#include <math.h>
static inline int iabs(int x) {
return (((x) < 0) ? -(x) : (x));
}
void func(int n) {
/* Validate that n is within the desired range */
int m = iabs(++n);
/* ... */
}
올바른 코드 예제 - 1.3
보다 유연한 해결책은 _Generic을 사용하여 ABS() 매크로를 선언하는 것이다. 아래 코드는 인라인 함수를 사용하여
모든 산술 데이터 형식을 지원하도록 작성되었다.
#include <complex.h>
#include <math.h>
static inline long long llabs(long long v) {
return v < 0 ? -v : v;
}
static inline long labs(long v) {
return v < 0 ? -v : v;
}
static inline int iabs(int v) {
return v < 0 ? -v : v;
}
static inline int sabs(short v) {
return v < 0 ? -v : v;
}
static inline int scabs(signed char v) {
return v < 0 ? -v : v;
}
#define ABS(v) _Generic(v, signed char : scabs, 
short : sabs, 
int : iabs, 
long : labs, 
long long : llabs, 
float : fabsf, 
double : fabs, 
long double : fabsl, 
double complex : cabs, 
float complex : cabsf, 
long double complex : cabsl)(v)
void func(int n) {
/* Validate that n is within the desired range */
int m = ABS(++n);
/* ... */
}
올바른 코드 예제(GCC) - 1.4
GCC의 __typeof를 사용하면 매크로 피연산자 값을 선언하고 동일한 유형을 임시 할당할 수 있다. 임시 할당하여
계산을 수행하므로 피연산자는 한번만 평가된다.
#define ABS(x) __extension__ ({ __typeof (x) tmp = x; 
tmp < 0 ? -tmp : tmp; })
잘못된 코드 예제(assert()) - 2
assert() 매크로는 편리한 코드 테스트 메커니즘을 제공한다. assert() 매크로의 동작은 NDEBUG 매크로 정의를 따
른다. NDEBUG 매크로가 정의되지 않은 경우 assert() 매크로는 인자를 평가 하기 위해 정의되며 결과가 0과 비교
되면 abort() 함수를 호출한다. NDEBUG가 정의되면 assert는 ((void) 0)으로 확장되도록 정의된다.
아래 코드는 부작용이 있는 표현식(index++)이 포함된 assert() 매크로의 예이다.
#include <assert.h>
#include <stddef.h>
void process(size_t index) {
assert(index++ > 0); /* Side effect */
/* ... */
}
올바른 코드 예제(assert()) - 2.1
부작용을 포함하는 표현식을 assert() 매크로 외부로 이동시켜 부작용을 방지한다.
#include <assert.h>
#include <stddef.h>
void process(size_t index) {
assert(index > 0); /* No side effect */
++index;
/* ... */
}
출처 PRE31-C. Avoid side effects in arguments to unsafe macros

More Related Content

PDF
코딩인카페 C&JAVA 기초과정 C프로그래밍(1)
PDF
코딩인카페 C&JAVA 기초과정 C프로그래밍(3)
PDF
코딩인카페 C&JAVA 기초과정 C프로그래밍(2)
PDF
Secure coding-c-preprocessor-3
PDF
CNN for sentence classification
PPTX
Refelction의 개념과 RTTR 라이브러리
PPTX
Chapter 17 monte carlo methods
PPTX
자바스크립트.
코딩인카페 C&JAVA 기초과정 C프로그래밍(1)
코딩인카페 C&JAVA 기초과정 C프로그래밍(3)
코딩인카페 C&JAVA 기초과정 C프로그래밍(2)
Secure coding-c-preprocessor-3
CNN for sentence classification
Refelction의 개념과 RTTR 라이브러리
Chapter 17 monte carlo methods
자바스크립트.

What's hot (17)

PPTX
Effective c++(chapter 5,6)
PDF
프로그래밍 대회: C++11 이야기
PPTX
가능한 C++ 스타일의 캐스트를 즐겨 쓰자
PPTX
C++11
PDF
Effective modern cpp item14
PPTX
이펙티브 C++ 789 공부
PDF
Effective c++ chapter7_8_9_dcshin
PPTX
Hoons 닷넷 정기세미나
PDF
Secure coding-c-preprocessor-1
PDF
알고리즘 연합캠프 세미나 3-C (C++11 and ETC)
PPTX
What’s new in c++11
PDF
Api design for c++ 6장
PPTX
C# 세미나 12회차
PPTX
Effective c++ Chapter6
PPTX
[아꿈사] The C++ Programming Language 13장 템플릿
PPTX
Windosw via c 스터디2장
PPTX
C#을 사용한 빠른 툴 개발
Effective c++(chapter 5,6)
프로그래밍 대회: C++11 이야기
가능한 C++ 스타일의 캐스트를 즐겨 쓰자
C++11
Effective modern cpp item14
이펙티브 C++ 789 공부
Effective c++ chapter7_8_9_dcshin
Hoons 닷넷 정기세미나
Secure coding-c-preprocessor-1
알고리즘 연합캠프 세미나 3-C (C++11 and ETC)
What’s new in c++11
Api design for c++ 6장
C# 세미나 12회차
Effective c++ Chapter6
[아꿈사] The C++ Programming Language 13장 템플릿
Windosw via c 스터디2장
C#을 사용한 빠른 툴 개발
Ad

Similar to Secure coding-c-preprocessor-2 (20)

PPTX
7장매크로
PPTX
파이썬 스터디 2주차
PDF
일단 시작하는 코틀린
PPTX
[Gpg2권 조진현] 1.2 인라인 함수 대 매크로
PDF
Lambda 란 무엇인가
PPTX
ECMAScript 6의 새로운 것들!
PDF
technical report
PDF
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
PPTX
0.javascript기본(~3일차내)
PDF
C++ api design 품질
PDF
Itcookbook Asp Chapter2
PDF
Modern C++ 프로그래머를 위한 CPP11/14 핵심
PDF
C++ 프로그래밍 2014-2018년 기말시험 기출문제
PDF
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
PDF
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
PDF
NDC11_슈퍼클래스
PPTX
Macro & compilation
PPT
카사 공개세미나1회 W.E.L.C.
PPT
8.다중메서드
PPTX
7장매크로
파이썬 스터디 2주차
일단 시작하는 코틀린
[Gpg2권 조진현] 1.2 인라인 함수 대 매크로
Lambda 란 무엇인가
ECMAScript 6의 새로운 것들!
technical report
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
0.javascript기본(~3일차내)
C++ api design 품질
Itcookbook Asp Chapter2
Modern C++ 프로그래머를 위한 CPP11/14 핵심
C++ 프로그래밍 2014-2018년 기말시험 기출문제
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
NDC11_슈퍼클래스
Macro & compilation
카사 공개세미나1회 W.E.L.C.
8.다중메서드
Ad

More from Seungyong Lee (11)

PDF
Secure coding-c-dcl-1
PDF
Linux blue borne-vulnerabilities
PDF
Sha 2017-teaser-round website attack writeup
PDF
윈도우 커널 익스플로잇
PDF
화이트 박스 암호기법
PDF
Dll 하이재킹
PDF
Frida tutorial 1
PDF
C 프로그램 메모리 구조
PDF
리눅스 커널 기초 태스크관리
PDF
암호 기법의 소개
PDF
문자열이란 무엇인가
Secure coding-c-dcl-1
Linux blue borne-vulnerabilities
Sha 2017-teaser-round website attack writeup
윈도우 커널 익스플로잇
화이트 박스 암호기법
Dll 하이재킹
Frida tutorial 1
C 프로그램 메모리 구조
리눅스 커널 기초 태스크관리
암호 기법의 소개
문자열이란 무엇인가

Secure coding-c-preprocessor-2

  • 1. C 언어 시큐어 코딩 - Preprocessor-2 안전하지 않은 매크로 인자로 인한 부작용 발생을 피한다. 인자 중 하나를 두 번 이상 평가하거나 전혀 평가하지 않는 함수 형태 매크로는 안전하지 않다. 또한 할당, 증가, 감 소, 휘발성 액세스, 입출력 등의 부작용을 유발할 수 있는 함수 호출을 포함하는 매크로는 호출하지 않는다. 함수 형태 매크로 사용 시 전달 인자로 인한 부작용은 사용 방법에 대한 위험 요소이므로 그 책임은 매크로를 사용 한 프로그래머에게 있다. 하지만 이를 해결하기 위한 좋은 방법은 안전하지 않은 함수 형태의 매크로 작성을 하지 않는 것이다. 잘못된 코드 예제 - 1 매크로 인자로 인한 부작용을 보여주는 잘못된 코드 예제: #define ABS(x) (((x) < 0) ? -(x) : (x)) void func(int n) { /* Validate that n is within the desired range */ int m = ABS(++n); /* ... */ } 이 예제에서 ABS() 매크로를 호출하면 다음과 같이 확장된다. m = (((++n) < 0) ? -(++n) : (++n)); n을 두 번 증가시키는 것을 확인할 수 있다. 올바른 코드 예제 - 1.1 n의 증가 연산을 매크로 호출 전 수행하는 올바른 코드 예제: #define ABS(x) (((x) < 0) ? -(x) : (x)) /* UNSAFE */ void func(int n) { /* Validate that n is within the desired range */ ++n; int m = ABS(n); /* ... */ }
  • 2. 추가로 ABS_UNSAFE()로 매크로 이름을 변경하여 매크로가 안전하지 않다는 것을 명확히하여 매크로를 사용하는 다른 프로그래머들의 안전한 사용을 도울 수 있으며, 부호 있는 정수에 대한 연산이 오버 플로우를 발생하지 않도록 한다. 올바른 코드 예제 - 1.2 ABS() 매크로를 대체하는 인라인 함수 iabs()를 정의한다. 모든 유형의 피연산자가 동작하는 매크로와는 달리 함수 는 데이터 형의 범위를 벗어난 인자를 자른다. #include <complex.h> #include <math.h> static inline int iabs(int x) { return (((x) < 0) ? -(x) : (x)); } void func(int n) { /* Validate that n is within the desired range */ int m = iabs(++n); /* ... */ } 올바른 코드 예제 - 1.3 보다 유연한 해결책은 _Generic을 사용하여 ABS() 매크로를 선언하는 것이다. 아래 코드는 인라인 함수를 사용하여 모든 산술 데이터 형식을 지원하도록 작성되었다. #include <complex.h> #include <math.h> static inline long long llabs(long long v) { return v < 0 ? -v : v; } static inline long labs(long v) { return v < 0 ? -v : v; } static inline int iabs(int v) { return v < 0 ? -v : v; } static inline int sabs(short v) { return v < 0 ? -v : v; } static inline int scabs(signed char v) { return v < 0 ? -v : v; }
  • 3. #define ABS(v) _Generic(v, signed char : scabs, short : sabs, int : iabs, long : labs, long long : llabs, float : fabsf, double : fabs, long double : fabsl, double complex : cabs, float complex : cabsf, long double complex : cabsl)(v) void func(int n) { /* Validate that n is within the desired range */ int m = ABS(++n); /* ... */ } 올바른 코드 예제(GCC) - 1.4 GCC의 __typeof를 사용하면 매크로 피연산자 값을 선언하고 동일한 유형을 임시 할당할 수 있다. 임시 할당하여 계산을 수행하므로 피연산자는 한번만 평가된다. #define ABS(x) __extension__ ({ __typeof (x) tmp = x; tmp < 0 ? -tmp : tmp; }) 잘못된 코드 예제(assert()) - 2 assert() 매크로는 편리한 코드 테스트 메커니즘을 제공한다. assert() 매크로의 동작은 NDEBUG 매크로 정의를 따 른다. NDEBUG 매크로가 정의되지 않은 경우 assert() 매크로는 인자를 평가 하기 위해 정의되며 결과가 0과 비교 되면 abort() 함수를 호출한다. NDEBUG가 정의되면 assert는 ((void) 0)으로 확장되도록 정의된다. 아래 코드는 부작용이 있는 표현식(index++)이 포함된 assert() 매크로의 예이다. #include <assert.h> #include <stddef.h> void process(size_t index) { assert(index++ > 0); /* Side effect */ /* ... */ } 올바른 코드 예제(assert()) - 2.1 부작용을 포함하는 표현식을 assert() 매크로 외부로 이동시켜 부작용을 방지한다.
  • 4. #include <assert.h> #include <stddef.h> void process(size_t index) { assert(index > 0); /* No side effect */ ++index; /* ... */ } 출처 PRE31-C. Avoid side effects in arguments to unsafe macros