ããŒã2
ããŒã3
ã·ãªãŒãºã®ç¬¬1éšã§ã¯ãæªå®çŸ©ã®åäœãšã¯äœããCããã³C ++ã³ã³ãã€ã©ããå®å šãªãèšèªãããé«ãããã©ãŒãã³ã¹ã®ã¢ããªã±ãŒã·ã§ã³ãçæããæ¹æ³ã«ã€ããŠèª¬æããŸããã ãã®æçš¿ã§ã¯ããå®å šã§ãªããCãå®éã«äœã§ãããã«ã€ããŠèª¬æããæªå®çŸ©ã®åäœã«ãã£ãŠåŒãèµ·ããããå®å šã«äºæããªã圱é¿ã説æããŸãã 3çªç®ã®ããŒãã§ã¯ããå奜çãªãã³ã³ãã€ã©ãŒããããã®å¹æã®äžéšããããšãå¿ èŠã§ã¯ãªãå Žåã§ããã©ã®ããã«è»œæžã§ãããã«ã€ããŠèª¬æããŸãã
ç§ã¯ãããããªãäžç¢ºå®ãªè¡åãCããã°ã©ããŒãé »ç¹ã«æããããæ°é£ãã®ãããšåŒã¶ã®ã奜ãã§ãã
ã³ã³ãã€ã©ãŒã®æé©åéã®çžäºäœçšã«ãããäºæããªãçµæãçãã
ææ°ã®æé©åã³ã³ãã€ã©ã«ã¯ãç¹å®ã®é åºã§åäœããå€ãã®æé©åãå«ãŸããŠãããæã«ã¯è€æ°åç¹°ãè¿ãããŸãããã®é åºã¯ãã³ã³ãã€ã©ãéçºããããšïŒã€ãŸããæ°ãããªãªãŒã¹ããªãªãŒã¹ããããšïŒå€æŽãããå ŽåããããŸãã
ãŸããã³ã³ãã€ã©ããšã«ãªããã£ãã€ã¶ãå€§å¹ ã«ç°ãªããŸãã æé©åã¯ã³ãŒãå€æã®ããŸããŸãªæ®µéã®ããã«æ©èœãããããåã®æ®µéã§ã³ãŒããå€æŽããããšãã«ããŸããŸãªå¹æãçºçããå¯èœæ§ããããŸãã
ããå ·äœçã«ããããã«ããã®ãããªæããªäŸïŒLinuxã«ãŒãã«ã®å®éã®ãã°ã®äŸããåçŽåãããïŒãæ€èšããŠãã ããã
void contains_null_check(int *P) { int dead = *P; if (P == 0) return; *P = 4; }
ãã®äŸã§ã¯ãã³ãŒãã¯ãæ瀺çã«ããã«ãã€ã³ã¿ãŒããã§ãã¯ããŸãã ã³ã³ãã€ã©ãåé·ãªNull Check Eliminationãã¹ã®åã«ãDead Code Eliminationããã¹ãéå§ãããšã2ã€ã®ã³ãŒãå€æãå®è¡ãããããšãããããŸãã
void contains_null_check_after_DCE(int *P) { //int dead = *P; // deleted by the optimizer. if (P == 0) return; *P = 4; }
ãããŠïŒ
void contains_null_check_after_DCE_and_RNCE(int *P) { if (P == 0) // Null check not redundant, and is kept. return; *P = 4; }
ãã ãããªããã£ãã€ã¶ãŒã®æ§é ãç°ãªãå ŽåããããDCEã®åã«RNCEãå®è¡ããå ŽåããããŸãã ãã®åŸã次ã®2ã€ã®å€æãå®è¡ãããŸãã
void contains_null_check_after_RNCE(int *P) { int dead = *P; if (false) // P was dereferenced by this point, so it can't be null return; *P = 4; }
ãã®åŸãåé·ã³ãŒããåé€ãããŸãã
void contains_null_check_after_RNCE_and_DCE(int *P) { //int dead = *P; //if (false) // return; *P = 4; }
å€ãã®ããã°ã©ããŒã«ãšã£ãŠãé¢æ°ããnullãã§ãã¯ãåé€ããããšã¯éåžžã«äºæ³å€ã§ãïŒãããŠã圌ãã¯ãã°ãã³ã³ãã€ã©ã®ããã«ããŸãïŒã ãã ããcontains_null_check_after_DCE_and_RNCEãšcontains_null_check_after_RNCE_and_DCEã®äž¡æ¹ã®ãªãã·ã§ã³ã¯ãæšæºã«åŸã£ãŠcontains_null_checkã®å®å šã«æå¹ãªæé©åããã圢åŒã§ãããããŸããŸãªã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãåäžãããããã«äž¡æ¹ã®æé©åãéèŠã§ãã
ããã¯éåžžã«åçŽã§å å ¥èŠ³ã®ãªãäŸã§ãããã€ã³ã©ã€ã³é¢æ°ã§ã¯ãã®ãããªããšãåžžã«çºçããŸãã ã€ã³ã©ã€ã³é¢æ°ã¯ããã®åŸã®æé©åã®å€ãã®å¯èœæ§ãéããŸãã ããã¯ããªããã£ãã€ã¶ãŒãé¢æ°ãã€ã³ã©ã€ã³åããããšã決å®ããå Žåãã³ãŒãã®åäœãå€æŽããä»ã®ããŒã«ã«æé©åãè¡ãããããšãæå³ããŸãã ããã¯ãæšæºã®èŠ³ç¹ãããå®çšçãªèŠ³ç¹ããããçç£æ§ãé«ããããã«å®å šã«æ£ãããã®ã§ãã
äžæ確ãªæåãšå®å šæ§ãæ··åšãããªãã§ãã ãã
Cã«äŒŒãããã°ã©ãã³ã°èšèªã®ãã¡ããªã¯ãã«ãŒãã«ãsetuidããŒã¢ã³ãWebãã©ãŠã¶ãªã©ãåºç¯å²ã®éèŠãªå®å šãªã³ãŒãã«äœ¿çšãããŸãããã®ã³ãŒãã¯ããæµå¯Ÿçãªãå ¥åããŒã¿ããã³ãã®ãã°ã«å¯Ÿå¿ããããããçš®é¡ã®ã»ãã¥ãªãã£åé¡ãåŒãèµ·ããå¯èœæ§ããããŸãã Cã®æãæåãªå©ç¹ã®1ã€ã¯ãã³ãŒããèªãã ãã§äœãèµ·ãã£ãŠããããæ¯èŒçç°¡åã«ç解ã§ããããšã§ãã
ãã ããäžå®ã®åäœã¯ãã®ããããã£ã®èšèªã奪ããŸãã ããšãã°ãã»ãšãã©ã®ããã°ã©ãã¯ãäžèšã®äŸã®ãcontains_null_checkããnullããã§ãã¯ãããšæ³å®ããŸãã ãã®äŸã¯ããã»ã©æããã®ã§ã¯ãããŸãããïŒnullãæž¡ããããšããã®ã³ãŒãã¯äœããç Žå£ããå¯èœæ§ãããããããã°æã«æ¯èŒçç°¡åã«èŠã€ããããšãã§ããŸãïŒãå®éã«ã¯å®å šã«æ£ãããªãéåžžã«åççãªCã³ãŒãã®æçããããããããŸã ãã®åé¡ã¯å€ãã®ãããžã§ã¯ãïŒLinuxã«ãŒãã«ãOpenSSLãglibcãªã©ãå«ãïŒã«åœ±é¿ãåãŒããCERTã«GCCã®è匱æ§ã«é¢ããéç¥ã匷å¶çã«å ¬éããŸããïŒãã ãã GCCã ãã§ãªããåºã䜿çšãããŠããæé©åCã³ã³ãã€ã©ã¯ãã¹ãŠè匱ã§ãããšå人çã«èããŠããŸãïŒã
äŸãèããŠã¿ãŸãããã 泚ææ·±ãæžãããCã³ãŒããæ³åããŠãã ããïŒ
void process_something(int size) { // Catch integer overflow. if (size > size+1) abort(); ... // Error checking from this code elided. char *string = malloc(size+1); read(fd, string, size); string[size] = 0; do_something(string); free(string); }
ãã®ã³ãŒãã¯ãã§ãã¯ãå®è¡ããŠããã¡ã€ã«ããèªã¿åãã®ã«ååãªã¡ã¢ãªãå²ãåœãŠãããŠããããšã確èªãïŒçµç«¯ã®ãŒããè¿œå ããå¿ èŠãããããïŒããªãŒããŒãããŒå šäœãçºçããå Žåã«çµäºããŸãã ãã ãããã®äŸã§ã¯ãã³ã³ãã€ã©ã¯ïŒæšæºã«åŸã£ãŠïŒãã§ãã¯ãåé€ã§ããŸãã ããã¯ãã³ã³ãã€ã©ãŒãã³ãŒãã次ã®ããã«å€æã§ããããšãæå³ããŸãã
void process_something(int *data, int size) { char *string = malloc(size+1); read(fd, string, size); string[size] = 0; do_something(string); free(string); }
64ããããã©ãããã©ãŒã ã§ã³ã³ãã€ã«ãè¡ãããå Žåãããµã€ãºããINT_MAXïŒããããããã¯ãã£ã¹ã¯äžã®ãã¡ã€ã«ã®ãµã€ãºïŒã§ãããšãã«ãã°ãçºçããå¯èœæ§ããããŸãã ãããã©ãã»ã©ã²ã©ãã®ãèŠãŠã¿ãŸããããå€æ°ã®ãªãŒããŒãããŒããã§ãã¯ããã®ã¯åççã ããã§ãã ã³ãŒãããã¹ããããšããç¹ã«ãã®å®è¡ãã¹ããã¹ãããªãéããåé¡ã¯ãããŸããã 誰ããè匱æ§ãæªçšããããšã決å®ãããŸã§ãã³ãŒãã¯å®å šã§ãããšèããããããã§ãã ããã¯éåžžã«äºæ³å€ã®ãã²ã©ãã¯ã©ã¹ã®ãã°ã§ãã 幞ããªããšã«ãç°¡åã«ä¿®æ£ã§ããŸãããsize == INT_MAXããªã©ã䜿çšããŠãã ããã
å šäœããªãŒããŒãããŒãããããšã¯ãå€ãã®çç±ã§ã»ãã¥ãªãã£ã®åé¡ã§ããããšãããããŸããã å®å šã«å®çŸ©ãããæŽæ°æŒç®ïŒ-fwrapvã䜿çšãããã笊å·ãªãæŽæ°ã䜿çšããïŒã䜿çšããå Žåã§ããæŽæ°ã®ãªãŒããŒãããŒã«é¢é£ããå¯èœæ§ã®ãããã°ã®ã¯ã©ã¹ãæ®ããŸãã 幞ããªããšã«ããããã®ãã°ã¯ã³ãŒãã«è¡šç€ºãããã»ãã¥ãªãã£ç£æ»å¡ã«ããç¥ãããŠããŸãã
æé©åãããã³ãŒãã®ãããã°ã¯ç¡æå³ã§ã
äžéšã®äººã ïŒããšãã°ãçæããããã·ã³ã³ãŒããèŠãã®ã奜ããªäœã¬ãã«ã®çµã¿èŸŒã¿ããã°ã©ããŒïŒã¯ãåžžã«æé©åãæå¹ã«ããŠäœæ¥ããŠããŸãã éçºã®åæ段éã§ã³ãŒãã«ãã°ãããå Žåãå€ãããããããã®äººã ã¯ãããã°ã©ã ã®å®è¡æã«ãããã°ãå°é£ãªåé¡ã«ã€ãªããäžåè¡¡ãªéã®äºæããªãæé©åã芳å¯ããŠããŸãã ããšãã°ãæåã®èšäºã®äŸã®ãzero_arrayãã®äŸã§èª€ã£ãŠãi = 0ããã¹ãããããããšã«ãããã³ã³ãã€ã©ãŒãã«ãŒããå®å šã«åé€ã§ããããã«ããŸãïŒzero_arrayããreturn;ãã«å€æŽããŸãïŒã
å¥ã®èå³æ·±ãã±ãŒã¹ã¯ãã°ããŒãã«é¢æ°ãã€ã³ã¿ãŒãããå Žåã«çºçããå¯èœæ§ããããŸãã ç°¡ç¥åãããäŸã¯æ¬¡ã®ããã«ãªããŸãã
static void (*FP)() = 0; static void impl() { printf("hello\n"); } void set() { FP = impl; } void call() { FP(); }
ã©ã®clangãæé©åãããŸããïŒ
void set() {} void call() { printf("hello\n"); }
ããã¯ãnullãã€ã³ã¿ãŒã®åŒã³åºããæªå®çŸ©ã§ããããããããè¡ãããšãã§ããŸããããã¯ãåŒã³åºãïŒïŒã®åã«setïŒïŒãåŒã³åºãå¿ èŠãããããšã瀺åããŠããŸãã ãã®å Žåãéçºè ã¯setïŒïŒã®åŒã³åºããå¿ããŠãããnullãéåç §ããŠãããã°ã©ã ã¯ã¯ã©ãã·ã¥ãããä»ã®èª°ãããããã°ãã«ããè¡ããšã³ãŒããå£ããŸãã
ãã®ãããªãã°ã¯è¿œè·¡ãããŸããçããããã®ãçãããå Žåã¯ã-O0ã§ãã«ãããŠã¿ãŠãã ãããã³ã³ãã€ã©ã¯æé©åãå®è¡ããªãå¯èœæ§ãé«ããªããŸãã
æªå®çŸ©ã®åäœã䜿çšãããåäœãããã³ãŒãã¯ãã³ã³ãã€ã©ã§äœããå€æŽããããšå£ããå ŽåããããŸãã
æ°ããããŒãžã§ã³ã®LLVMãã³ã³ãã€ã«ã«äœ¿çšããããšãããŸãã¯ã¢ããªã±ãŒã·ã§ã³ãGCCããLLVMã«ç§»æ€ããããšãã«ããåäœããŠããããã«èŠãããã³ãŒããçªç¶å£ããå€ãã®ã±ãŒã¹ã調ã¹ãŸããã LLVMèªäœã«ã¯1ã€ãŸãã¯2ã€ã®ãã°ãããå ŽåããããŸãããã»ãšãã©ã®å Žåãã³ã³ãã€ã©ãåå ã§ã¢ããªã±ãŒã·ã§ã³ã«é ããããã°ãçŸããããã§ãã ããã¯å€ãã®ç°ãªãå Žåã«çºçããå¯èœæ§ããããŸãã以äžã«2ã€ã®äŸã瀺ããŸãã
1.以åã¯éå¢ã«ãã£ãŠãŒããšæ³å®ãããŠããåæåãããŠããªãå€æ°ã§ãçŸåšãŒããå«ãŸãªãå¥ã®ã¬ãžã¹ã¿ã«é 眮ãããŠããŸãã ãã®åäœã¯ãã¬ãžã¹ã¿ã¢ãã±ãŒã¿ã§å€æŽãè¡ããããšãã«æããã«ãªãããšããããããŸãã
2.ã¹ã¿ãã¯äžã®é åãªãŒããŒãããŒã¯ããããããå€æ°ã®ä»£ããã«å®éã®å€æ°ãäžæžãããŸãã ããã¯ãã³ã³ãã€ã©ãã¹ã¿ãã¯äžã®å€æ°ã䞊ã¹æ¿ããå ŽåããŸãã¯éè€ããªãæå¹æéãæã€å€æ°ãããç©æ¥µçã«ã¹ã¿ãã¯ç©ºéã«ããã¯ããå Žåã«çºçããŸãã
éèŠã§æãããããšã¯ãæªå®çŸ©ã®åäœã«åºã¥ãã»ãšãã©ãã¹ãŠã®æé©åãå°æ¥ãã€ã§ããã°ã«ã€ãªããå¯èœæ§ãããããšãèŠã€ããããšã§ãã ã€ã³ã©ã€ã³é¢æ°ãã«ãŒãã®å±éãããã³ãã®ä»ã®æé©åã¯ããé©åã«æ©èœãããããã®å€§éšåã¯äžèšã®ããã«äºæ¬¡æé©åã«ãã£ãŠè¡ãããŸãã
ããã¯ãã³ã³ãã€ã©ãã»ãšãã©å¿ ç¶çã«è²¬ä»»ãè² ãå§ãããšããäºå®ãšãèšå€§ãªéã®Cã³ãŒããççºãåŸ ã£ãŠããæéç匟ã§ãããšããããšããããéåžžã«åæºããŸãã ããã«æªãã®ã¯...
倧èŠæš¡ãªã³ãŒãããŒã¹ã«UBãå«ãŸããŠããªãããšã確èªããä¿¡é Œã§ããæ¹æ³ã¯ãããŸãã
ããã¯éåžžã«æªãç¶æ³ã§ããå®éã倧èŠæš¡ãªã¢ããªã±ãŒã·ã§ã³ã«ã¯UBããªããå°æ¥çã«å£ããªãããšãå€æããä¿¡é Œã§ããæ¹æ³ããªãããã§ãã ãã°ãèŠã€ããã®ã«åœ¹ç«ã€äŸ¿å©ãªããŒã«ã¯ãããããããŸãããå°æ¥ã³ãŒããå£ããªããšããå®å šãªèªä¿¡ãäžãããã®ã¯äœããããŸããã ããã€ãã®ãªãã·ã§ã³ããã®é·æãšçæãèŠãŠã¿ãŸãããã
1. Valgrindã¯ãããããçš®é¡ã®åæåãããŠããªãå€æ°ããã®ä»ã®ã¡ã¢ãªãã°ãèŠã€ããããã®çŽ æŽãããããŒã«ã§ãã Valgrindã¯éåžžã«é ããšããç¹ã§å¶éããããçæããããã·ã³ã³ãŒãã«æ¢ã«ååšãããã°ã®ã¿ãæ€çŽ¢ã§ãïŒãªããã£ãã€ã¶ãŒã«ãã£ãŠåé€ããããã®ãèŠã€ããããšãã§ããŸããïŒããœãŒã¹ãCã§æžãããŠããããšãç¥ããŸããïŒãããŠãããã£ãŠãå€æ°ã®ãµã€ãºãè¶ ããéã®ã·ããã笊å·ä»ãæŽæ°ã®ãªãŒããŒãããŒãªã©ã®ãã°ãèŠã€ããããšã¯ã§ããŸãã ã
2. Clangã«ã¯å®éšã¢ãŒã-fcatch-undefined-behaviorããããŸããããã¯ãã·ããç¯å²ã®å¢çãè¶ãããé åã®å¢çãè¶ãããšããåçŽãªãšã©ãŒãªã©ãéåãæ¢ãããã®ã©ã³ã¿ã€ã ãã§ãã¯ãæ¿å ¥ããŸãã ãããã®ãã§ãã¯ã¯ãã¢ããªã±ãŒã·ã§ã³ã®é床ãäœäžãããä»»æã®ãã€ã³ã¿ãŒã®éåç §ãæ¯æŽã§ããªãããïŒValgrindã¯å¯èœïŒãå¶éãããŸãããä»ã®éèŠãªãã°ãèŠã€ããããšãã§ããŸãã Clangã¯-ftrapvãã©ã°ïŒ-fwrapvãšæ··åããªãã§ãã ããïŒãå®å šã«ãµããŒãããŠããŸããããã«ãããã©ã³ã¿ã€ã ã§ç¬Šå·ä»ãæŽæ°ããªãŒããŒãããŒãããã°ããã£ããã§ããŸãïŒGCCã«ããã®ãããªãã©ã°ããããŸãããç§ã®çµéšã§ã¯éåžžã«ä¿¡é Œæ§ãäœãããã°ããããŸãïŒã 次ã«ã-fcatch-undefined-behaviorã®å°ããªãã¢ã瀺ããŸãã
$ cat tc int foo(int i) { int x[2]; x[i] = 12; return x[i]; } int main() { return foo(2); } $ clang tc $ ./a.out $ clang tc -fcatch-undefined-behavior $ ./a.out Illegal instruction
3.ã³ã³ãã€ã©ã¡ãã»ãŒãžã¯ãåæåãããŠããªãå€æ°ãåçŽãªæŽæ°ãªãŒããŒãããŒãªã©ããã°ã®ã¯ã©ã¹ãèŠã€ããã®ã«é©ããŠããŸãã äž»ã«2ã€ã®å¶éããããŸãã1ïŒã³ãŒãã®å®è¡ã«é¢ããåçãªæ å ±ããªãããšã2ïŒåæã¯ã³ã³ãã€ã«æéãå¢å ããããããåæã¯éåžžã«é«éã§ããã¹ãã§ãã
4. Clangéçã¢ãã©ã€ã¶ãŒã¯ãããæ·±ãåæãè¡ãããã«ãã€ã³ã¿ãŒã®éåç §ãªã©ãUBã®äœ¿çšãå«ããã°ãèŠã€ããããšããŸãã
éåžžã®èŠåã®ãããªæéå¶éããªããããã³ã³ãã€ã©ã®èŠåãšæ¯èŒããŠã匷åãããåæããŒã«ãšèããããšãã§ããŸãã éçã¢ãã©ã€ã¶ãŒã®äž»ãªæ¬ ç¹ã¯ã1ïŒããã°ã©ã æäœããã»ã¹ã«é¢ããåçãªæ å ±ããªãããšã2ïŒéåžžã®éçºããã»ã¹ã«çµ±åãããŠããªãããšã§ãïŒãã ããXCode 3.2ãšã®çµ±åã
5. LLVMãKleeããµããããžã§ã¯ãã¯ãèšå·åæã䜿çšããŠãã³ãŒãããšã«ãèãããããã¹ãŠã®æ¹æ³ãè©Šè¡ãããã³ãŒãå ã®ãã°ãèŠã€ããŠãã¹ããçæããŸãã ããã¯ã倧ããªã¢ããªã±ãŒã·ã§ã³ã§å®è¡ããã®ãéçŸå®çã§ãããšããäºå®ã«ãã£ãŠäž»ã«å¶éãããçŽ æŽãããå°ããªãããžã§ã¯ãã§ãã
6.è©Šããããšã¯ãããŸããããChucky EllisonãšGrigori Rosuã®C-SemanticsããŒã«ã¯ãããã€ãã®ã¯ã©ã¹ã®ãã°ïŒã·ãŒã±ã³ã¹ãã€ã³ãã®éåãªã©ïŒãæ€åºã§ãããšããç¹ã§éåžžã«èå³æ·±ããã®ã§ãã ãŸã ç 究ãããã¿ã€ãã®ç¶æ ã§ãããïŒå°èŠæš¡ããã³éå®çãªïŒããã°ã©ã ã®ãã°ãèŠã€ããã®ã«åœ¹ç«ã¡ãŸãã 詳现ã«ã€ããŠã¯ã John Regerã®æçš¿ãèªãããšããå§ãããŸãã
ãããã£ãŠããã°ãèŠã€ããããã®å€ãã®ããŒã«ããããŸãããã¢ããªã±ãŒã·ã§ã³ã«UBããªãããšã蚌æããè¯ãæ¹æ³ã¯ãããŸããã å®éã®ã¢ããªã±ãŒã·ã§ã³ã«ã¯å€§éã®ãã°ããããCã¯åºç¯å²ã®éèŠãªã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšãããŠãããšæ³åããŠãã ãããããã¯æãããããšã§ãã ååã®èšäºã§ã¯ãç¹ã«Clangã«æ³šæãæããªãããUBãåŠçããããã«Cã³ã³ãã€ã©ãæã€ããŸããŸãªãªãã·ã§ã³ãèŠãŠãããŸãã