프로그램 오류를 자동으로 고쳐주는 기술
✔ SW 개발에 소요되는 시간 중 디버깅은 거의 절반이 소요된다.
특히 상업적 소프트웨어의 경우 Bug-fixing time이 200일 정도 된다는 결과가 있다.
✔ 소프트웨어 버그의 수는 매년 증가한다.
✔ manual하게 오류를 고치는 과정은 시간이 소요되며, 오류 발생이 쉽다(=error-prone)
즉 원래 없던 오류를 만들어낼 수도 있다. 또 실제 버그가 고쳐졌는지를 확신하기 어렵다.
patch를 validate하기 위해 testcase에 의존한다.
1) patch synthesizer는 이미 정해진 patch의 후보군들이 존재한다.
2) 프로그램이 주어지면,free()를 더한다, 옮긴다
등의 후보군 중 하나를 골라서 candidate patch를 만들어 본다.
3) Candidate patch에 대해 patch validator가 평가한다. patch validator을 이용하여 테스트케이스를 통해서 다 통과하는지 확인한다.
4) 만약 통과하지 못한다면, 다른 후보를 선택하는 방식으로 loop을 돈다.
5) 모든 테스트 케이스를 통과하면 patched program이 된다.
📌 단점
테스트케이스에 의존하는 이 접근의 단점은 테스트케이스는 통과했을지 모르지만 실제 오류는 고치지 못한 plausible patch를 만들어낼 수 있다.
📌 Plausible Patch
테스트 케이스는 다 통과했는데 원본 코드의 오류는 고쳐지지 않은 경우
Memory deallocation errors: MemFix1, SAVER2, LeakFix3
Null dereferences: Vfix4, SapFix5
Buffer/integer overflows: IntPTI6, IntRepair7
Concurrency errors: Pfix8
-> 우리는 메모리 해제오류를 중점적으로 살펴보자.
malloc
p = malloc(i)
free (p)
프로그램이 끝난 후에는 매모리 해제를 해주어야 하는데 그러지 않아서 발생하는 오류가 3가지이다.
1) Memory-leak (CWE-401): Free memory too late.
해제 없이 끝났으니, return문 전에 free(p)를 해 주면 된다.
2) Use-after-free (CWE-416): Free memory too quickly.
메모리 사용이 안 끝났는데 free를 너무 빨리 해서 발생하는 오류
use(p) 뒤에 free(p)를 넣는다.3) Double-free (CWE-415): Free the memory multiple times.
p를 여러번 free한 것이다. free를 이미 했는데 또 한 것!
p = malloc(1);
if (...) {
q = malloc(2);
free(p); // 밑에서 q만 이용하고 있으므로
}
else
q = p;
// use q;
free(q);
혹은, if문으로 p와 q 주소값을 비교 후 해제
if (p == q)
free(p)
Nullification Code를 넣어서 해결한다. 물론 다른 방법들도 있을 수 있음!
그러나 전체 코드가 너무 길어서 개발자는 이 해결법에 대해서 확신하지 못했다고 한다.(과연 버그가 고쳐졌는지)
개발자의 실수로 free(out)을 4->12번으로 옮겨서, memory leak이 발생하게 되었다.
9번에서 out을 해제하지 않고 NULL을 할당하니까 memory leak
안전하게 고치기 위해서 개발자가 free(out)은 그대로 두고 6번에 out = NULL을 한다.
코드가 완벽히 깔끔하지는 않지만 이것도 옳은 patch이다!