![éçããã³åçåæã®åæ](https://habrastorage.org/getpro/habr/post_images/44d/90d/38e/44d90d38efc7e0a9333e5af93663ea95.png)
åçããã³éçã³ãŒãåæã®æ¹æ³è«
ããã°ã©ã ã®ãœãŒã¹ã³ãŒãã«ã¯ããšã©ãŒã®ç¹å®ã«åœ¹ç«ã€ãã³ããå«ãŸããŠããŸãã ç°¡åãªäŸãèããŠã¿ãŸãããã
char *str = foo(); if (str == '\0')
ãã€ã³ã¿ãŒãnullptr ã NULLããŸãã¯å°ãªããšã0 ãã€ãŸãæåãªãã©ã«'\ 0'ãšæ¯èŒããªãã®ã¯å¥åŠã§ãã ãã®å¥åŠãªããšã«åºã¥ããŠãéçã³ãŒãã¢ãã©ã€ã¶ãŒã¯ããã€ã³ã¿ãŒã0ã§ããã®ã§ã¯ãªããæååã空ã§ããããšãæ¬åœã«ç¢ºèªããããšèããŠããå¯èœæ§ããããŸãã ã€ãŸã è¡ã®å é ã«çµç«¯ãŒããããããšã確èªãããã£ãã®ã§ããã誀ã£ãŠãã€ã³ã¿ãŒãéåç §ããã®ãå¿ããŠããŸããã ã»ãšãã©ã®å Žåãããã¯æ¬åœã«ééãã§ãããæ£ããã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
char *str = foo(); if (*str == '\0')
ã³ã³ãã€ã«äžã«ããã®ãããªæ å ±ã¯å€±ãããåçã¢ãã©ã€ã¶ãŒã¯ãã®ãšã©ãŒãæ€åºã§ããŸããã åçã¢ãã©ã€ã¶ãŒã®èŠ³ç¹ããã¯ããã€ã³ã¿ãŒã®NULLããã§ãã¯ãããŸã ãå¿é ããå¿ èŠã¯ãããŸããã
åçã¢ãã©ã€ã¶ãŒã®ãã1ã€ã®åŒ±ç¹ã¯ããšã©ãŒãå«ãã³ãŒããå®è¡ããå¿ èŠãããããšã§ãã ãŸããã³ãŒãã®å€ãã®ã»ã¯ã·ã§ã³ã§ã¯ããããè¡ãã®ã¯éåžžã«å°é£ã§ãã å®éã®ã¢ããªã±ãŒã·ã§ã³ããååŸããã³ãŒãã®äŸã䜿çšããŠèª¬æããŸãã
ADOConnection* piTmpConnection = NULL; hr = CoCreateInstance( CLSID_DataLinks, NULL, CLSCTX_INPROC_SERVER, IID_IDataSourceLocator, (void**)&dlPrompt ); if( FAILED( hr ) ) { piTmpConnection->Release(); dlPrompt->Release( ); return connstr; }
CoCreateInstanceé¢æ°ã倱æããå Žåã piTmpConnection nullãã€ã³ã¿ãŒã¯éåç §ãããŸãã å®éã piTmpConnection-> ReleaseïŒïŒãšããè¡ããããŸãã æ¥ç¶ããŸã äœæãããŠããªããããåã«äžèŠã§ãã
CoCreateInstanceé¢æ°ããšã©ãŒã¹ããŒã¿ã¹ãè¿ãå Žåãç¶æ³ããšãã¥ã¬ãŒãããå¿ èŠããããããåçã¢ãã©ã€ã¶ãŒã䜿çšããŠãã®ãããªç¶æ³ãèå¥ããããšã¯åé¡ã§ãã ããã¯ç°¡åã§ã¯ãããŸããã
çŽç²ã«çè«çã«ã¯ãéçã¢ãã©ã€ã¶ãŒã¯ã³ãŒãã«é¢ããæ å ±ãæã£ãŠãããããåçã¢ãã©ã€ã¶ãŒãããå€ãã®ãšã©ãŒãæ€åºã§ããŸãã å®éã«ã¯ãéçã¢ãã©ã€ã¶ãŒã®æ©èœã¯ã䜿çšå¯èœãªã¡ã¢ãªãŒã®éãšèš±å®¹å¯èœãªã©ã³ã¿ã€ã ã«ãã£ãŠå¶éãããŸãã ã€ãŸããéçã¢ãã©ã€ã¶ãŒã¯ãèãããããã¹ãŠã®å ¥åããŒã¿ã§ã³ãŒããã©ã®ããã«æ©èœããããèæ ®ããããšãã§ããŸãã ãããã圌ã¯ã¯ã©ã¹ã¿ãŒã§150幎éãããã«èšå€§ãªéã®ã¡ã¢ãªãã€ã³ã¹ããŒã«ãããŸãã
ãã®çµæãå®éã«ã¯ãéçã¢ãã©ã€ã¶ãŒã¯å€ãã®ã¿ã€ãã®ãšã©ãŒãæ€åºã§ããŸããã ããšãã°ãå€ãã®é¢æ°éã§ãã€ã³ã¿ãŒãæž¡ãããå ŽåããªãŒã¯ã«æ°ä»ããªãã åçã¢ãã©ã€ã¶ãŒã¯ãã³ãŒãã®è€éãã«é¢ä¿ãªãããã®ãããªã¿ã¹ã¯ã®åªããä»äºãããŸãã
æ€èšŒçµæ
éçã³ãŒãåæã®æ¹æ³è«ãæ®åãããããã«ãããŸããŸãªãããžã§ã¯ããå®æçã«ãã§ãã¯ããŠããŸãããValgrindã®ãããªãããžã§ã¯ããæž¡ãããšã¯ã§ããŸããã§ããã ééããèŠã€ããããšã¯äžçš®ã®ææŠã§ãã ããã¯é«å質ã®ãã¹ãæžã¿ãããžã§ã¯ãã§ãããCoverityã¢ãã©ã€ã¶ãŒã«ãã£ãŠããã§ãã¯ãããŸãã ãšã«ããããã®ã³ãŒãã¯ããŸããŸãªããŒã«ã䜿çšããæ奜家ã«ãã£ãŠãã¹ãããããšç¢ºä¿¡ããŠããŸãã ãã®ãããããã€ãã®ééããèŠã€ããããšã§ããã倧æåã§ãã
PVS-Studioã¢ãã©ã€ã¶ãŒãValgrindãããžã§ã¯ãã³ãŒãã§èŠã€ãããã®ãèŠãŠã¿ãŸãããã
static void lk_fini(Int exitcode) { .... VG_(umsg)(" taken: %'llu (%.0f%%)\n", taken_Jccs, taken_Jccs * 100.0 / total_Jccs ?: 1); .... }
èŠåPVS-StudioïŒV502ãïŒïŒãæŒç®åã¯ãäºæ³ãšã¯ç°ãªãæ¹æ³ã§åäœããå¯èœæ§ããããŸãã ãïŒïŒãæŒç®åã®åªå é äœã¯ãã/ãæŒç®åãããäœããªã£ãŠããŸãã lk_main.c 1014
ãªãã¬ãŒã¿ãŒïŒïŒéåžžã«é°æ¹¿ã§ãããéåžžã«æ éã«äœ¿çšããå¿ èŠããããŸãã ãã®ãããã¯ã«ã€ããŠã¯ã å°ããªæ¬ã®ç¬¬4ç« ã§è©³ãã説æããŸããã ãã®ã³ãŒããçãããçç±ãèããŠã¿ãŸãããã
ããã°ã©ããŒã¯ãŒãé€ç®ãã身ãå®ããããšæã£ãããã§ãã ãããã£ãŠãå€æ°total_Jccsã0ã«çããå Žåã é€ç®ã¯1ã§å®è¡ããå¿ èŠããããŸãã ã³ãŒãã¯æ¬¡ã®ããã«æ©èœããããšãèšç»ãããŠããŸããã
taken_Jccs * 100.0 / (total_Jccs ?: 1)
ãã ããïŒïŒæŒç®åã®åªå é äœã¯ãä¹ç®ããã³é€ç®æŒç®åã®åªå é äœãããäœããªã£ãŠããŸãã ãããã£ãŠãåŒã¯æ¬¡ã®ããã«è©äŸ¡ãããŸãã
(taken_Jccs * 100.0 / total_Jccs) ?: 1
ãã ããããããã³ãŒãã¯æå³ãããšããã«æ©èœããŸãã ãšã«ããããããåœãŠã¯ãŸãå Žåã¯ãæ¬åŒ§ãè¿œå ããŠãä»ã®ããã°ã©ããŒãå°æ¥ãšã©ãŒããããã©ããçåã«æããªãããã«ããããšããå§ãããŸãã
static Bool doHelperCall (....) { .... UInt nVECRETs = 0; .... vassert(nVECRETs == (retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0); .... }
èŠåPVS-StudioïŒV502ãïŒïŒãæŒç®åã¯ãäºæ³ãšã¯ç°ãªãæ¹æ³ã§åäœããå¯èœæ§ããããŸãã ãïŒïŒãæŒç®åã®åªå é äœã¯ãã==ãæŒç®åãããäœããªã£ãŠããŸãã host_arm_isel.c 795
èå³æ·±ãã±ãŒã¹ã The ?:æŒç®åã¯èª€ã£ãŠäœ¿çšãããŠããŸãããã³ãŒãã¯æ£ããã§ãã
ãã§ãã¯ã¯æ¬¡ã®ããã«æ©èœããã¯ãã ãšèããããŠããŸããã
nVECRETs == ((retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0)
ãã ãã次ã®ããã«æ©èœããŸãã
(nVECRETs == (retTy == Ity_V128 || retTy == Ity_V256)) ? 1 : 0
ãããããããšã«ãããèŠããšããããã®ãã§ãã¯ãåçã§ããããšãããããŸãã çµæã¯åãã«ãªããŸãã
åæ§ã®ãã§ãã¯ã¯ãã¡ãã§ãïŒ
- V502ãããããã?:ãæŒç®åã¯äºæ³ãšã¯ç°ãªãæ¹æ³ã§åäœããŸãã ãïŒïŒãæŒç®åã®åªå é äœã¯ãã==ãæŒç®åãããäœããªã£ãŠããŸãã host_arm64_isel.c 737
- V502ãããããã?:ãæŒç®åã¯äºæ³ãšã¯ç°ãªãæ¹æ³ã§åäœããŸãã ãïŒïŒãæŒç®åã®åªå é äœã¯ãã==ãæŒç®åãããäœããªã£ãŠããŸãã host_mips_isel.c 611
typedef ULong DiOffT; typedef struct { Bool fromC; DiOffT off; SizeT size; SizeT used; UChar data[]; } CEnt; static Bool is_sane_CEnt (....) { .... CEnt* ce = img->ces[i]; .... if (!(ce->size == CACHE_ENTRY_SIZE)) goto fail; if (!(ce->off >= 0)) goto fail; // <= if (!(ce->off + ce->used <= img->real_size)) goto fail; .... }
PVS-StudioèŠåïŒV547åŒ 'ce-> off> = 0'ã¯åžžã«trueã§ãã 笊å·ãªãã®åã®å€ã¯åžžã«> = 0ã§ããimage.c 147
offã¡ã³ããŒã¯ç¬Šå·ãªãã®åã®å€æ°ã§ããã€ãŸããåžžã«ãŒã以äžã§ãã ãããã£ãŠãæ¡ä»¶ïŒïŒïŒCe-> off> = 0ïŒïŒã¯åžžã«falseã§ãã
static void sdel_Counts ( Counts* cts ) { memset(cts, 0, sizeof(Counts)); free(cts); }
PVS-StudioèŠåïŒV597ã³ã³ãã€ã©ãŒã¯ã 'cts'ãªããžã§ã¯ãã®ãã©ãã·ã¥ã«äœ¿çšããã 'memset'é¢æ°åŒã³åºããåé€ã§ããŸããã ãã©ã€ããŒãããŒã¿ãæ¶å»ããã«ã¯ãmemset_sïŒïŒé¢æ°ã䜿çšããå¿ èŠããããŸãã cg_merge.c 324
ã©ããããValgrindèªäœã®ãšã©ãŒã®æ€çŽ¢ãç°¡çŽ åããããã«ãã¡ã¢ãªã¯è§£æŸãããåã«ãŒãã§åããããŸãã ãã ãããªãªãŒã¹ããŒãžã§ã³ã§ã¯ãã³ã³ãã€ã©ã¯memseté¢æ°åŒã³åºããåé€ããå¯èœæ§ããããŸããããã¯ã freeé¢æ°ãåŒã³åºããããŸã§ãããã¡ãŒã䜿çšãããªããªãããã§ãã
ã¡ã¢ãªããªã»ãããããªãå¯èœæ§ãããåæ§ã®å ŽæïŒ
- V597ã³ã³ãã€ã©ãŒã¯ããffnããªããžã§ã¯ãã®ãã©ãã·ã¥ã«äœ¿çšããããmemsetãé¢æ°åŒã³åºããåé€ã§ããŸããã ãã©ã€ããŒãããŒã¿ãæ¶å»ããã«ã¯ãmemset_sïŒïŒé¢æ°ã䜿çšããå¿ èŠããããŸãã cg_merge.c 263
- V597ã³ã³ãã€ã©ãŒã¯ããctsããªããžã§ã¯ãã®ãã©ãã·ã¥ã«äœ¿çšããããmemsetãé¢æ°åŒã³åºããåé€ã§ããŸããã ãã©ã€ããŒãããŒã¿ãæ¶å»ããã«ã¯ãmemset_sïŒïŒé¢æ°ã䜿çšããå¿ èŠããããŸãã cg_merge.c 332
- V597ã³ã³ãã€ã©ãŒã¯ããcpfããªããžã§ã¯ãã®ãã©ãã·ã¥ã«äœ¿çšããããmemsetãé¢æ°åŒã³åºããåé€ã§ããŸããã ãã©ã€ããŒãããŒã¿ãæ¶å»ããã«ã¯ãmemset_sïŒïŒé¢æ°ã䜿çšããå¿ èŠããããŸãã cg_merge.c 394
static Bool dis_AdvSIMD_scalar_shift_by_imm(DisResult* dres, UInt insn) { .... ULong nmask = (ULong)(((Long)0x8000000000000000ULL) >> (sh-1)); .... }
PVS-StudioèŠåïŒV610äžç¹å®ã®åäœã ã·ããæŒç®åã>>ãã確èªããŠãã ããã å·Šã®ãªãã©ã³ã 'ïŒïŒLongïŒ0x8000000000000000ULLïŒ'ã¯è² ã§ãã guest_arm64_toIR.c 9428
å³ã«ã·ããããããªãã©ã³ãã®å€ãè² ã®å Žåãçµæã®å€ã¯å®è£ ã«äŸåããŸãïŒå®è£ å®çŸ©ïŒã ãããã£ãŠãç§ãã¡ã¯å±éºãªã³ãŒããæ±ã£ãŠããŸãã
ããã§ã NULLããã§ãã¯ãããåã«ãã€ã³ã¿ãŒã®éåç §ãè¡ãããç¶æ³ãèããŸã ã
PRE(xsm_op) { struct vki_xen_flask_op *op = (struct vki_xen_flask_op *)ARG1; PRINT("__HYPERVISOR_xsm_op ( %u )", op->cmd); // <= PRE_MEM_READ("__HYPERVISOR_xsm_op", ARG1, sizeof(vki_uint32_t) + sizeof(vki_uint32_t)); if (!op) // <= return; .... }
PVS-StudioèŠåïŒV595 nullptrã«å¯ŸããŠæ€èšŒãããåã«ããopããã€ã³ã¿ãŒã䜿çšãããŸããã è¡ã確èªããŠãã ããïŒ350ã360ãsyswrap-xen.c 350
åæ§ã®ã±ãŒã¹ïŒ
- V595 nullsysrã«å¯ŸããŠæ€èšŒãããåã«ããsysctlããã€ã³ã¿ãŒã䜿çšãããŸããã è¡ã確èªããŠãã ããïŒ568ã578ãsyswrap-xen.c 568
- V595 nullptrã«å¯ŸããŠæ€èšŒãããåã«ããdomctlããã€ã³ã¿ãŒã䜿çšãããŸããã è¡ã確èªããŠãã ããïŒ710ã722ãsyswrap-xen.c 710
Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) { .... if (inrw && sdynbss_present) { vg_assert(di->sbss_present); sdynbss_present = False; vg_assert(di->sbss_svma + di->sbss_size == svma); di->sbss_size += size; .... } else // <= if (inrw && !di->sbss_present) { di->sbss_present = True; di->sbss_svma = svma; di->sbss_avma = svma + inrw->bias; .... }
PVS-StudioèŠåïŒV705ãelseããããã¯ãå¿ããããŠãããã³ã¡ã³ãã¢ãŠããããŠããå¯èœæ§ãããããã®ããããã°ã©ã ã®æäœããžãã¯ãå€æŽãããŠããŸãã readelf.c 2231
elseããŒã¯ãŒãã¯ããã®ã³ãŒãã§ã¯éåžžã«çãããèŠããŸãã ã³ãŒãã¯ããã®äœæ¥ã®ããžãã¯ã«åŸã£ãŠèª¿æŽãããŠããŸããã ããã«ã elseè¡ã®åŸã«ç©ºã®è¡ãç¶ããŸãã ããã¯ã倱æããã³ãŒãã®ãªãã¡ã¯ã¿ãªã³ã°ã®çµæã«çŽé¢ããŠãããšä»®å®ãã ãã以å€ã¯äžèŠã§ãã
static Bool doHelperCallWithArgsOnStack (....) { .... if (guard) { if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1 && guard->Iex.Const.con->Ico.U1 == True) { /* unconditional -- do nothing */ } else { goto no_match; //ATC cc = iselCondCode( env, guard ); } } .... }
PVS-StudioèŠåïŒV779å°éäžèœã³ãŒããæ€åºãããŸããã ãšã©ãŒãååšããå¯èœæ§ããããŸãã host_arm_isel.c 461
ã³ãŒãã®è¡ïŒ
cc = iselCondCode( env, guard );
å®è¡ãããªãã£ãïŒ
void reset_valgrind_sink(const char *info) { if (VG_(log_output_sink).fd != initial_valgrind_sink.fd && initial_valgrind_sink_saved) { VG_(log_output_sink).fd = initial_valgrind_sink.fd; VG_(umsg) ("Reset valgrind output to log (%s)\n", (info = NULL ? "" : info)); } }
PVS-StudioèŠåïŒV547åŒ 'ïŒïŒvoid *ïŒ0ïŒ'ã¯åžžã«falseã§ãã server.c 110
ã¢ãã©ã€ã¶ãŒã®èŠåã¯å¥åŠã«èŠãã説æãå¿ èŠã§ãã
次ã®åŒã«èå³ããããŸãã
(info = NULL ? "" : info))
NULLãã¯ãã¯ïŒïŒvoid *ïŒ0ïŒã«å±éãã ã次ã®ããã«ãªããŸãã
(info = ((void *) 0) ? "" : info))
ïŒïŒæŒç®åã®åªå 床ã¯=æŒç®åã®åªå 床ãããé«ããããèšç®ã¯æ¬¡ã®ããã«ãªããŸãã
(info = (((void *) 0) ? "" : info)))
ïŒïŒæŒç®åã®æ¡ä»¶ïŒïŒvoid *ïŒ0ïŒãå¥åŠã«èŠããããšã«åæããŸããããã¯PVS-Studioã¢ãã©ã€ã¶ãŒãèŠåãããã®ã§ãã ã©ããããç§ãã¡ã¯ã¿ã€ããã¹ãæ±ã£ãŠãããã³ãŒãã¯æ¬¡ã®ããã«ãªã£ãŠããã¯ãã§ãã
(info == NULL ? "" : info))
ãããŠä»æ¥ã®æåŸã®ã³ãŒãïŒ
void genReload_TILEGX ( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg, Int offsetB ) { TILEGXAMode *am; vassert(!hregIsVirtual(rreg)); am = TILEGXAMode_IR(offsetB, TILEGXGuestStatePointer()); switch (hregClass(rreg)) { case HRcInt64: *i1 = TILEGXInstr_Load(8, rreg, am); break; case HRcInt32: *i1 = TILEGXInstr_Load(4, rreg, am); break; default: ppHRegClass(hregClass(rreg)); vpanic("genReload_TILEGX: unimplemented regclass"); break; } }
PVS-StudioèŠåïŒV751ãã©ã¡ãŒã¿ãŒãi2ãã¯é¢æ°æ¬äœå ã§ã¯äœ¿çšãããŸããã host_tilegx_defs.c 1223
ããã§ã¯ãä»ã®åæ§ã®é¢æ°ã§è¡ãããããã«ã i2ã§NULLãæžã蟌ãã®ãå¿ããŠãããšæããŸãã
*i1 = *i2 = NULL;
åæ§ã®ãšã©ãŒã¯ãã¡ãã§ãïŒ
V751ãã©ã¡ãŒã¿ãŒ 'i2'ã¯é¢æ°æ¬äœå ã§ã¯äœ¿çšãããŸããã host_mips_defs.c 2000
ãããã«
ãæž èŽããããšãããããŸããã Linuxçšã®PVS-Studioéçã³ãŒãã¢ãã©ã€ã¶ãŒããè©Šããã ããã
- ããŠã³ããŒãïŒ PVS-Studio for Linux
- äžæçãªã©ã€ã»ã³ã¹ããŒãååŸããŸãã
- æé ïŒ Linuxã§PVS-Studioãå®è¡ããæ¹æ³ ã
Windowséçºè ãç§ã¯ããã«æåŸ ããŸãïŒ PVS-Studio for Windows ã 圌ãã«ãšã£ãŠ-ãã¹ãŠãå°ãç°¡åã§ãã Visual Studioã®ãã©ã°ã€ã³ãã€ã³ã¹ããŒã«ãããã¢ããŒãžã§ã³ã§CãC ++ãCïŒãããžã§ã¯ãã確èªããã ãã§ãã
ãã®èšäºãè±èªåã®èŽè¡ãšå ±æãããå Žåã¯ã翻蚳ãžã®ãªã³ã¯ã䜿çšããŠãã ããïŒAndrey Karpovã éçã¢ãã©ã€ã¶ãŒã«ããValgrindåçã¢ãã©ã€ã¶ãŒã®ã³ãŒãã®ç¢ºèª
èšäºãèªãã§è³ªåããããŸããïŒ
å€ãã®å Žåãèšäºã«ã¯åã質åãå¯ããããŸãã ããã§åçãåéããŸããïŒ PVS-StudioããŒãžã§ã³2015ã«é¢ããèšäºã®èªè
ããã®è³ªåãžã®åç ã ãªã¹ããã芧ãã ããã