#dokydoky
[C++] Double free example 본문
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