#dokydoky

[C++] Double free example 본문

Secure Coding

[C++] Double free example

dokydoky 2017. 4. 7. 12:38

Double free 취약코드

struct P {};

class C {
	P *p;
public:
	C(P *p) : p(p) {}
	~C() { delete p; }
	void f() {}
};

void g(C c) {
	c.f();
}

void main() {
	P *p = new P;
	C c(p);
	g(c);
}


g()의 매개변수 타입을 reference로 변경해주면 되지만, 근본적으로 이런 실수가 발생하지 않게 복사 생성자와 대입 연산자를 삭제한다. 이 경우 g()함수의 매개변수가 reference 타입이 아니면 컴파일 에러가 발생하여 컴파일 타임에 오류를 확인할 수 있다.

struct P {};
class C {
	P *p;
public:
	C(P *p) : p(p) {}
	C(const C&) = delete;
	~C() { delete p; }
	void operator=(const C&) = delete;
	void f() {}
};
void g(C &c) {
	c.f();
}
void main() {
	P *p = new P;
	C c(p);
	g(c);
}


추가적으로, Smart pointer를 사용하여 해결할 수도 있지 않을까? unique_ptr와 shared_ptr 순서대로 알아보자.

<unique_ptr>

#include <iostream>
#include <memory>
using namespace std;

struct P {
public:
	P() { cout << "constructor" << endl; }
	~P() { cout << "destructor" << endl; }
};

class C {
//	P *p;
	unique_ptr<P> uniq_p;
public:
	C(P *p) {
		uniq_p.reset(p);
	}
	void f() {}
};

void g(C &c) {
	c.f();
}

void main() {
	P *p = new P;
	cout << "-----------" << endl;
	C c(p);
	cout << "-----------" << endl;
	g(c);
}

output>>

constructor
-----------
-----------
destructor

 위 처럼 unique_ptr을 사용할 경우 정상적으로 메모리 할당/해제가 이뤄지며, g() 함수의 매개변수가 reference가 아닐 경우, 복사 생성자를 delete 한 경우와(첫 번째 예제와 같이)와 동일한 에러가 발생한다.


<shared_ptr>

#include <iostream>
#include <memory>
using namespace std;

struct P {
public:
	P() { cout << "constructor" << endl; }
	~P() { cout << "destructor" << endl; }
};

class C {
//	P *p;
	shared_ptr<P> shared_p;
public:
	C(P *p) {
		shared_p.reset(p);
	}
	void f() {}
};

void g(C &c) {
	c.f();
}

void main() {
	P *p = new P;
	cout << "-----------" << endl;
	C c(p);
	cout << "-----------" << endl;
	g(c);
}

output>>

constructor
-----------
-----------
destructor

shared_ptr의 경우는 참조 카운트를 사용해 여러번 참조될 수 있기 때문에, g()함수의 매개변수가 reference이던, call by value 타입이든 상관없이 잘 동작한다.

하지만 불필요한 복사생성자의 호출을 자제하기 위해서는 reference 타입의 매개변수를 사용하는 것이 좋다.



Reference

CERT C++ coding standard 2016, MEM51-CPP.

'Secure Coding' 카테고리의 다른 글

[C++] Smart pointer noncompliant code cases  (0) 2017.08.09
[*NIX] Privilege Model  (0) 2017.08.09
Comments