424 정보과학회논문지 : 컴퓨팅의실제및레터제 19 권제 8 호 (2013.8) 사례연구를통한정적프로그램분석기법을사용하는도구의비교 (A Comparative Case Study on Static Program Analysis Tools) 김윤호 박용배 (Yunho Kim) 김문주 (Moonzoo Kim) (Yongbae Park) 요약프로그램신뢰성향상을위해서정적프로그램분석도구가많이사용되고있다. 하지만, 정적분석결과에서거짓경보를걸러내기위한추가적인분석이필요하고실제오류를찾지못할수있는문제점이있다. 본논문에서는상용정적프로그램분석도구인 Coverity 와 Sparrow 및오픈소스도구인 Clang analyzer 를 buffer overflow 벤치마크와 libexif 0.6.20 소스코드에적용하여실험대상도구가오류를찾아내는데얼마나효과적인지사례연구를수행하였다. 실험결과 buffer overflow 벤치마크에서는 Coverity, Sparrow, Clang analyzer 각각 6.02%, 3.61%, 0% 의버그탐지율과 2.41%, 1.20%, 0% 의오탐율을보였다. libexif 0.6.20 적용에서 Coverity, Sparrow, Clang analyzer 는총 745 개의오류를찾아내었으나알려진 7 개의오류중 6 개를 본연구는미래부가지원한 2013년정보통신 방송 (ICT) 연구개발사업, 지식경제부 / 한국산업기술평가관리원 IT R&D 프로그램 [10041752, 초소형 고신뢰 OS와고성능멀티코어 OS를동시실행하는듀얼운영체제원천기술개발 ], 그리고미래부 / 한국연구재단의중견연구자지원사업-핵심연구 (2012046172) 의연구비지원으로수행되었음 이논문은제39회추계학술발표회에서 정적프로그램분석기법을사용하는도구의비교 :Coverity 와 Sparrow 를사용한 libexif 사례연구 의제목으로발표된논문을확장한것임 학생회원 : KAIST 전산학과 kimyunho@kaist.ac.kr yongbae2@gmail.com 종신회원 : KAIST 전산학과교수 moonzoo@cs.kaist.ac.kr (Corresponding author임 ) 논문접수 : 2013년 1월 21일심사완료 : 2013년 5월 10일 CopyrightC2013 한국정보과학회 ː개인목적이나교육목적인경우, 이저작물의전체또는일부에대한복사본혹은디지털사본의제작을허가합니다. 이때, 사본은상업적수단으로사용할수없으며첫페이지에본문구와출처를반드시명시해야합니다. 이외의목적으로복제, 배포, 출판, 전송등모든유형의사용행위를하는경우에대하여는사전에허가를얻고비용을지불해야합니다. 정보과학회논문지 : 컴퓨팅의실제및레터제19권제8호 (2013.8) 찾아내지못하였다. 이와같이정적분석도구가놓칠수있는오류가많으므로높은소프트웨어신뢰성보장을위해다른기법과병행하여적용하는것이필요하다. 키워드 : 정적분석, 사례연구, Coverity, Sparrow, Clang analyzer Abstract Static analysis tools have been widely used to improve software reliability. However, static analysis tools have limitations that can generate false alarms and can miss real bugs. This paper presents a comparative study of three static analysis tools, Coverity, Sparrow, and Clang analyzer, through a case study on a set of buffer overflow benchmark programs and libexif 0.6.20 to evaluate the effectiveness of the three static analysis tools in terms of a bug finding capability. Experiment results on buffer overflow benchmark show that bug detection capabilities of Coverity, Sparrow, and Clang analyzer are 6.02%, 3.61%, and 0%, respectively and false alarm ratios of Coverity, Sparrow, and Clang analyzer are 2.41%, 1.20% and 0%, respectively. Experiment results on libexif 0.6.20 show that Coverity, Sparrow, and Clang analyzer detect 745 bugs and miss 6 out of 7 real bugs. Thus, it is necessary to use other bug finding techniques with static analysis techniques for achieving high software reliability, because static analysis tools can miss real bugs in target programs. Keywords: static analysis, case study, coverity, sparrow, clang analyzer 1. 서론 소프트웨어의활용범위가넓어짐에따라소프트웨어의신뢰성이더욱중요해지고있다. 특히의료장비, 우주탐사장비등의다양한종류의기기가소프트웨어로구동되면서소프트웨어의오류로심각한사회, 경제적피해및인명피해가발생한다. 예를들어아리안 5호로켓은 64bit 부동소수점을 16bit 정수형으로변환하던중발생한오류로폭발하여 5억달러의피해를남겼다 [1]. 또다른예로 Therac-25라는방사선의료기기의소프트웨어오류로인해환자가필요이상의많은방사선에노출되어사망하는사고가있었다 [2]. 이러한피해를막기위해서소프트웨어의신뢰성을높이기위한노력이필요하다. 소프트웨어신뢰성을효율적으로높이기위한방법으로정적프로그램분석기법이주목받고있다. 기존에소프트웨어의신뢰성향상을위해표준적으로사용되는소프트웨어테스트는개발자가테스트케이스를수동으로생성하고그결과를분석해야하기때문에비효율적이다. 정적프로그램분석기법은자동화된방식으로프로그램을분석하여프로그램이비정상적으로종료되는오류와 overflow오류등을찾을수있다.
사례연구를통한정적프로그램분석기법을사용하는도구의비교 425 본논문에서는상용정적분석도구 Coverity[3] 와 Sparrow[4] 및오픈소스도구 Clang analyzer[5] 를사용하여사례연구를통해버그찾는능력및오탐율을비교하였다. 사례연구는크게두가지로진행하였다. 먼저기존프로그램의 buffer overflow 버그를기반으로생성된소규모 (100~1000LOC) 벤치마크프로그램을대상으로버그찾는능력과오탐율을비교하고규모있는 (9KLOC) 오픈소스라이브러리인 libexif 0.6.20을대상으로적용하여발생한경보및발견한오류를비교하였다. 실험결과 buffer overflow 벤치마크에서는 Coverity, Sparrow, Clang analyzer 각각 6.02%, 3.61%, 0% 의버그탐지율과 2.41%, 1.20%, 0% 의오탐율을보였다. libexif 0.6.20 적용에서 Coverity, Sparrow, Clang analyzer는총 745개의오류를찾아내었으나알려진 7개의오류중 6개를찾아내지못했다. 2. 정적프로그램분석정적프로그램분석 [6,7] 은프로그램을실제로실행시키지않고분석하여프로그램소스코드를실행하였을때나타나는오류를찾아내는방법이다. 분석방법은프로그램이실행가능한경로, 프로그램의변수가가질수있는값의범위등을추상화하여분석하고가능한실행경로나값의범위가프로그램오류가발생하는조건을만족하는지검사하여오류가발생하는부분을찾아내는것이다. 정적프로그램분석방법을사용하여동적으로할당한메모리자원, 0으로나누는연산, 잘못된메모리접근과같은오류를효과적으로찾아낼수있다. 정적프로그램분석은프로그램을실행시키지않고분석하기때문에실제프로그램이수행될만큼개발이진행되지않아도개발도중에적용할수있고, 프로그램을실제실행하여분석하는방법인동적프로그램분석에비해서짧은시간에넓은범위를분석할수있는장점이있다. 또한분석과정이자동화되어있어서개발자가큰노력없이적용할수있다. 이와같은장점에힘입어 Coverity, Sparrow, Clang analyzer와같은다양한도구들이개발되어사용되고있다. 하지만, 정적프로그램분석기법은프로그램이가질수있는무한한크기의실행경로와프로그램상태를추상화하여유한한크기내에서분석하기때문에이과정에서정확도가떨어져거짓경보를발생할수있다. 거짓경보가발생할경우개발자가직접경보를분석하여실제버그인지아닌지판별해야하기때문에거짓경보가많이발생할경우정적분석을통한개발비용절감보다거짓경보분석에따르는개발비용증가가더커질수있다. 따라서거짓경보를줄이기위한다양한관련연구가진행되고있다 [8]. 또한, 여러정적프로그램분석도구가효율적으로 buffer overflow 오류를찾아내는지를비교하는연구도있다 [9]. 본논문에서는 buffer overflow 오류외에도두도구가찾아낼수있는모든오류를분석하여분류하였다. 3. 실험환경 3.1 도구설정 Coverity 5.4와 Sparrow 4.7 도구는경보가발생하는수준을조절할수있으며 Coverity의경우 3단계가, Sparrow에는 5단계가있다. 낮은단계에서는거짓경보를줄이기위해최소의경보를발생시키고, 높은단계에서는오류를놓치지않기위해최대한많은경보를발생한다. 하지만두도구에서검사할수있는오류의종류와분석강도가서로다르기때문에완전히동일한설정에서의비교는어렵다. 따라서본논문에서는경보분석을위한시간을고려하여두도구가수백개수준의경보를발생할수있는경보발생단계를적용하여비교하였다. Clang analyzer 3.3 도구는경보발생수준을조절하는옵션이없어기본설정으로수행하였다. 각도구는 Intel Core i7 3.4GHz 프로세서와 8GB의메모리가장착된 Debian 서버에서실행하였으며모든분석은 5분내에종료되었다. 1) 3.2 Buffer overflow 벤치마크실험설정각도구의오류찾는능력과오탐율을비교하기위해 buffer overflow 벤치마크 [9] 를대상으로적용하여결과를비교하였다. buffer overflow는 C 프로그램에서자주발생하는버그로발생시프로그램비정상종료및심각한보안버그를야기할수있는치명적인버그이다. 벤치마크프로그램은오픈소스프로그램 BIND, Sendmail, wuftpd에서기존에발견된버그를재현하기위한코드로작성되어있으며크기는 90~800LOC이다. 총 14쌍의테스트케이스로구성되어있으며각테스트케이스는 buffer overflow 버그가있는 BAD 버전과해당버그를수정한 OK 버전한쌍으로구성되어있다. 각 BAD 버전은최소 1개에서최대 28개, 평균 5.9개의 buffer overflow 버그를발생시킬수있는소스코드라인을포함하고있다. Buffer overflow 벤치마크실험에서는미리지정된테스트케이스의오류와관련되지않은경보는무시하였다. 3.3 libexif 0.6.20 실험설정분석대상인 libexif는 Exchangeable Image File Format(EXIF)[10] 형식의이미지파일에포함된정보를읽고쓰기위해사용한다. libexif 0.6.20은 C 언어소스코드파일 24개와 30개의헤더파일로구성되어있 1) 본논문은 2012 한국컴퓨터종합학술대회추계학술발표회에발표된 정적프로그램분석기법을사용하는도구의비교 : Coverity와 Sparrow 를사용한 libexif 사례연구 논문을확장한것으로기존논문에서적용한 Sparrow의성능을개선한새버전의 Sparrow 를사용하여실험을수행하고결과를분석하였다.
426 정보과학회논문지 : 컴퓨팅의실제및레터제 19 권제 8 호 (2013.8) 표 1 Buffer overflow 벤치마크실험결과 Table 1 Experiment results of buffer overflow benchmark Bug detection capability False alarm ratio Coverity 6.02% 2.41% Sparrow 3.61% 1.20% Clang analyzer 0.00% 0.00% 표 2 libexif 0.6.20 에서발생한경보 Table 2 The number of generated alarms for libexif 0.6.20 Coverity Sparrow Clang -analyzer Real bugs 147 (84%) 599 (95%) 3 (100%) False alarms 28 (16%) 33 (5%) 0 (0%) Total alarms 175 (100%) 632 (100%) 3 (100%) 으며, 8,922줄이들어있으며함수의개수는 229개이다. libexif를사용한이유는실제널리사용되고있는규모있는오픈소스라이브러리이며알려진오류와찾지못한오류가모두있어서각정적분석도구가얼마나효과적으로오류를찾아내는지확인할수있기때문이다. 공개된버그리포트를확인하고 libexif의최신버전인 0.6.21 버전에서오류를고친부분과비교하면 0.6.20에서오류가발생하는부분을찾을수있다. 4. 실험결과 4.1 Buffer overflow 벤치마크실험결과표 1은 buffer overflow 벤치마크실험결과를보여준다. Bug detection capability는 BAD 버전의전체 83개의 buffer overflow를야기할수있는소스코드라인중에서각도구가실제오류로찾아낸비율을나타내고 false alarm ratio는 OK 버전에서수정된 83개의소스코드라인중에서오류가있다고경보가발생한수의비율을나타낸다. Coverity의경우 6.02% (=5/83) 의 bug detection capability와 2.41% 의 false alarm ratio(=2/83) 을보였으며 Sparrow의경우 bug detection capability는 3.61%(=3/83) 로 Coverity보다낮았으나 false alarm ratio가 1.20%(=1/83) 로 Coverity보다낮아오탐이적게발생하였다. Clang analyer의경우모든테스트케이스에서경보를발생시키지않았다. Buffer overflow 벤치마크실험결과 Coverity와 Sparrow 의 buffer overflow bug detection capability 는 7% 미만으로낮은것으로나타났다. 상용정적분석도구들은수십만~수백만줄규모의프로그램을분석하면서유용한결과를주기위해오탐율을낮추는다양한휴리스틱알고리즘을적용한다. 이과정에서실제오류인지확실하지않은것으로보일경우오류가아닌것으로간주하여 bug detection capability를낮추더라 도오탐을줄이기위해최대한노력한다. 따라서정적분석도구는프로그램이올바르게작성된것을증명하는도구가아니기때문에정적분석도구가경보를발생시키지않더라도숨어있는버그가있을수있으며높은신뢰성을달성하기위해정적분석도구에만의존하지말고 concolic testing과같은동적분석기법과상호보완하여적용해야한다. 4.2 libexif 0.6.20 실험결과표 2는 Coverity, Sparrow, Clang analyzer로 libexif를분석하여발생한경보의수를나타낸다. Coverity, Sparrow, Clang analyzer는각각 175, 632, 3개의경보를발생시켰고세도구가모두공통적으로발견한경보가 1개있었다. Coverity와 Sparrow는세도구가모두찾은경보외에도 2개의동일한경보를발생시켰으며 Coverity와 Clang analyzer 역시모두찾은경보외에 2개의동일한경보를발생시켰다. Sparrow와 Clang analyzer는모두찾은경보외에동일한경보를발생시키지않았다. 그림 1은경보의종류별로각도구별각각발생시킨경보및공통적으로발생시킨경보를나누어비교한결과이다. 경보는원인에따라서 8가지분류의 17종류로구분하였다. 그림 2, 3, 4는각각 Coverity, Sparrow, Clang analyzer 가찾은실제오류와거짓경보를비교한것이다. 각도구가찾아낸오류와찾지못한오류가있고경보의종류에따른실제오류와거짓경보비율을알수있다. 4.2.1 찾아낸실제오류세도구는총 745개의실제오류를찾아내었으며, 그중세도구가공통적으로찾은오류는 1개이다. 찾아낸오류중 0.6.21에서고친오류도존재하며고쳐지지않은오류도존재한다. 그림 5는 Coverity, Sparrow, Clang analyzer가공통으로발견한 null pointer dereference 오류이다. exif-loader.c 파일의 exif_loader_get_buf() 함수 413 번째줄에서포인터 loader가 NULL일경우조건이참이되어 414 번째줄을실행한다. 하지만 414번째줄에서 exif_log() 함수의첫번째인자에서 loader를참조하므로 null pointer dereference 오류가발생한다. 해당오류는 0.6.21 버전에서아직수정되지않았다. 이처럼정적프로그램분석기법을사용하면개발자가찾기힘든오류까지찾을수있으므로정적프로그램분석으로소프트웨어의신뢰성을향상시킬수있다. 4.2.2 발견한경보종류의비교그림 1을봤을때 Coverity의경우 null pointer dereference를포함하여총 12종류의경보를발생시켰으며그중 null pointer dereference를제외한 11종류의경보는 Sparrow가발생시키지않은경보이다. 반면 Sparrow 의경우 null pointer dereference, bad integer constant
사례연구를통한정적프로그램분석기법을사용하는도구의비교 427 그림 1 각도구가생성한경보비교 Fig. 1 Alarms generated by Coverity, Sparrow, and Clang analyzer 그림 2 Coverity 가찾은실제오류와발생된거짓경보 Fig. 2 Real bugs and false alarms generated by Coverity 그림 3 Sparrow 가찾은실제오류와발생된거짓경보 Fig. 3 Real bugs and false alarms generated by Sparrow 그림 4 Clang analyzer 가찾은실제오류와발생된거짓경보 Fig. 4 Real bugs and false alarms generated by Clang analyzer
428 정보과학회논문지 : 컴퓨팅의실제및레터제 19 권제 8 호 (2013.8) 그림 5 exif-loader.c 에서발생하는 null pointer dereference 오류 Fig. 5 Null pointer dereference error in exif-data.c definition 등총 6종류의경보를발생시켰으며그중 null pointer dereference를제외한 5종류의경보는 Coverity 가발견하지못한경보이다. Clang analyzer는 null pointer dereference와 unused local variable 두종류의경보를발생시켰다. 이와같이각도구는오류를찾기위한경보를발생시키는방식이달라서한도구가찾아낸오류를다른도구에서찾아내지못할수있으며, 최대한많은오류를찾아야한다면여러가지도구를함께사용하는것이효과적이다. 4.2.3 찾아내지못한오류 0.6.21에서수정된 7개오류중 1개를찾아내었으나나머지 6개는찾지못하였다. 그중하나는 libexif 내부의동작과관련된오류로, 정적프로그램분석으로찾을수없으며, 나머지오류는배열범위를벗어난접근오류 3개, buffer overflow 오류 1개, 0으로나누는오류 1개이다. Coverity와 Sparrow는 0으로나누는오류를찾아내는기능이있지만 libexif에있는오류는찾아내지못하였다. 그림 6은 0으로나누는오류가존재하는 0.6.20과그오류가수정된 0.6.21을비교한것이다. vr.denominator라는변수는 exif_get_rational에서파일의특정부분의값이대입되며 0이대입될가능성이존재한다. 따라서변수가 0인지확인해야하며, 0.6.21 버전의 80 번줄에 vr.denominator가 0인지확인한후에 vr.denominator로나누는매크로가추가되어 378번줄에서이를사용하도록소스코드가변경되었다. 이오류는 concolic execution 기법을사용하는도구인 CREST-BV는찾아내는오류이며 0.6.21에서수정된 7개오류가운데 2개오류를 CREST-BV를사용해서발견하였다 [11]. 이처럼정적프로그램분석기법만으로는모든오류를찾아낼수없으므로, concolic execution과같은다른기법을함께사용하는것이필요하다. 5. 결론및향후연구사례연구를통해정적프로그램분석도구를비교하였다. 각도구모두 libexif 0.6.20의실제오류를발견하 그림 6 mnote-olympus-entry.c에서 0.6.20( 위 ) 과 0.6.21 ( 아래 ) 의차이점 Fig. 6 Difference of mnote-olympus-entry.c between 0.6.20(above) and 0.6.21(below) 였으며따라서정적프로그램분석도구는소프트웨어신뢰성을향상시키는데유용하다. 하지만 buffer overflow 벤치마크결과가보여주듯이오탐율을줄이기위해낮은버그탐지율을보일수있고각도구가찾을수있는오류종류가서로다를수있기때문에소프트웨어신뢰성을높이기위해서는여러정적분석도구를같이활용하고 concolic execution과같은다른분석기법을사용하여오류를찾아내는것도필요하다. References [1] J. Jézéquel, B. Meyer, "Design by contract: The lessons of ariane," IEEE Computer, vol.30, no.1, pp.129-130, 1997. [2] N. Leveson, C. Turner, "An investigation of the therac-25 accidents," IEEE Computer, vol.26, no.7, pp.18-41, 1993. [3] Coverity [Online]. Available: http://www.coverity.com (downloaded 2013, Jul. 28) [4] Sparrow [Online]. Available: http://www.fasoo.com/ product/sparrow_overview.asp (downloaded 2013, Jul. 28) [5] Clang analyzer [Online]. Available: http://clang-analyzer.llvm.org (downloaded 2013, Jul. 28) [6] P. Emanuelsson, U. Nilsson, "A comparative study of industrial static analysis tools," Proc. of the 3rd International Workshop on Systems Software Verification (SSV 2008), 2008. [7] A. Bessey, K. Block, B. Chelf, A. Chou, B. Fulton, S. Hallem, C. Henri-Gros, A. Kamsky, S. McPeak, D. Engler, "A few billion lines of code later: Using static analysis to find bugs in the real world," CACM, vol.53, no.2, pp.66-75, 2010. [8] K. Yi, J. Kim, Y. Jung, "Design and Implementation of Static Program Analyzer Finding All Buffer Overrun Errors in C Programs," Journal of KIISE : Software and Applications, vol.33, no.5, pp.508-524, 2006. [9] M. Zitser, R. Lippmann, T. Leek, "Testing static analysis tools using exploitable buffer overflows from open source code," Proc. of the SIGSOFT '04/FSE-12, 2004. [10] JEITA. Exif.org [Online]. Available: http://www. exif.org/ (downloaded 2013, Jul. 28) [11] Y. Kim, M. Kim, Y. Kim, Y. Jang, "Industrial application of concolic testing approach: A case study on libexif by using CREST-BV and KLEE," Proc. of the Software Engineering (ICSE), 2012 34th International Conference, SEIP track, 2012.