I checked the Firefox project using the PVS-Studio static code analyzer. I just glanced through the code but managed to find a few obviously odd fragments. Below I will cite the analyzer-generated messages I have studied and the corresponding code fragments. I hope this will help to improve the project a bit. -- Andrey Karpov, MVP Cand. Sc. (Physics and Mathematics), CTO Program Verification Systems Co., Ltd. URL: www.viva64.com E-Mail: karpov@viva64.com ============================================================================= V501 There are identical sub-expressions 'unit [0] == eCSSUnit_Null' to the left and to the right of the '||' operator. nsstyleanimation.cpp 1767 PRBool nsStyleAnimation::AddWeighted(...) { ... if (unit[0] == eCSSUnit_Null || unit[1] == eCSSUnit_Null || unit[0] == eCSSUnit_Null || unit[0] == eCSSUnit_URL) { return PR_FALSE; } ... } I think there could be written like this. if (unit[0] == eCSSUnit_Null || unit[1] == eCSSUnit_Null || unit[0] == eCSSUnit_URL || unit[1] == eCSSUnit_URL) { ----------------------------------------------------------------------------- V501 There are identical sub-expressions to the left and to the right of the '||' operator. nsdisplaylist.cpp 767 static PRBool IsZPositionLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2, void* aClosure) { if (!aItem1->GetUnderlyingFrame()->Preserves3D() || !aItem1->GetUnderlyingFrame()->Preserves3D()) { return IsContentLEQ(aItem1, aItem2, aClosure); } ... } I think there could be written like this. if (!aItem1->GetUnderlyingFrame()->Preserves3D() || !aItem2->GetUnderlyingFrame()->Preserves3D()) { ----------------------------------------------------------------------------- V501 There are identical sub-expressions to the left and to the right of the '&&' operator: aXResolution > 0.0 && aXResolution > 0.0 nspresshell.cpp 5114 nsresult PresShell::SetResolution(float aXResolution, float aYResolution) { if (!(aXResolution > 0.0 && aXResolution > 0.0)) { return NS_ERROR_ILLEGAL_VALUE; } ... } I think there could be written like this. (aXResolution > 0.0 && aYResolution > 0.0) ----------------------------------------------------------------------------- V501 There are identical sub-expressions 'protocol.EqualsIgnoreCase ("ftp")' to the left and to the right of the '||' operator. mozinlinespellwordutil.cpp 1034 Not a error. But one "protocol.EqualsIgnoreCase("ftp")" can be removed. if (protocol.EqualsIgnoreCase("http") || protocol.EqualsIgnoreCase("https") || protocol.EqualsIgnoreCase("news") || protocol.EqualsIgnoreCase("ftp") || protocol.EqualsIgnoreCase("file") || protocol.EqualsIgnoreCase("javascript") || protocol.EqualsIgnoreCase("ftp")) { ----------------------------------------------------------------------------- V502 Perhaps the '?:' operator works in a different way than it was expected. The '?:' operator has a lower priority than the '+' operator. gdef.cc 291 bool ots_gdef_parse(...) { ... const unsigned gdef_header_end = static_cast(8) + gdef->version_2 ? static_cast(2) : static_cast(0); ... } I think there could be written like this. const unsigned gdef_header_end = static_cast(8) + (gdef->version_2 ? static_cast(2) : static_cast(0)); ----------------------------------------------------------------------------- V512 A call of the 'memset' function will lead to underflow of the buffer '(exploded)'. time_win.cc 198 void Time::Explode(bool is_local, Exploded* exploded) const { ... ZeroMemory(exploded, sizeof(exploded)); ... } I think there could be written like this. ZeroMemory(exploded, sizeof(*exploded)); ----------------------------------------------------------------------------- V528 It is odd that pointer to 'char' type is compared with the '\0' value. Probably meant: *token == '\0'. svgnumberlist.cpp 96 nsresult SVGNumberList::SetValueFromString(const nsAString& aValue) { ... const char *token = str.get(); if (token == '\0') { return NS_ERROR_DOM_SYNTAX_ERR; // nothing between commas } ... } I think there could be written like this. if (*token == '\0') { or if (token[0] == '\0') { ----------------------------------------------------------------------------- V501 There are identical sub-expressions to the left and to the right of the '||' operator. svgorientsmiltype.cpp 161 nsresult SVGOrientSMILType::Interpolate(...) { ... if (aStartVal.mU.mOrient.mOrientType != nsIDOMSVGMarkerElement::SVG_MARKER_ORIENT_ANGLE || aStartVal.mU.mOrient.mOrientType != nsIDOMSVGMarkerElement::SVG_MARKER_ORIENT_ANGLE) { // TODO: it would be nice to be able to handle auto angles too. return NS_ERROR_FAILURE; } ... } ----------------------------------------------------------------------------- V547 Expression 'c < 0' is always false. Unsigned type value is never < 0. updater.cpp 1179 int PatchFile::LoadSourceFile(FILE* ofile) { ... size_t c = fread(rb, 1, r, ofile); if (c < 0) { LOG(("LoadSourceFile: error reading destination file: " LOG_S "\n", mFile)); return READ_ERROR; } ... } And here: V547 Expression 'c < 0' is always false. Unsigned type value is never < 0. updater.cpp 2373 V547 Expression 'c < 0' is always false. Unsigned type value is never < 0. bspatch.cpp 107 ----------------------------------------------------------------------------- V547 Expression is always true. Unsigned type value is always >= 0. exception_handler.cc 846 bool ExceptionHandler::WriteMinidumpForChild(...) { ... DWORD last_suspend_cnt = -1; ... // this thread may have died already, so not opening the handle is a // non-fatal error if (NULL != child_thread_handle) { if (0 <= (last_suspend_cnt = SuspendThread(child_thread_handle))) { ... } I think there could be written like this. if ( ((DWORD) -1) != (last_suspend_cnt = SuspendThread(child_thread_handle))) { And here: V547 Expression '0 <= last_suspend_cnt' is always true. Unsigned type value is always >= 0. exception_handler.cc 869 ----------------------------------------------------------------------------- V541 It is dangerous to print the string 'newhost' into itself. ssltunnel.cpp 531 bool AdjustWebSocketHost(relayBuffer& buffer, connection_info_t *ci) { ... sprintf(newhost, "%s:%d", newhost, PR_ntohs(inet_addr.inet.port)); ... } I think there could be used new buffer. ----------------------------------------------------------------------------- V547 Expression 'index < 0' is always false. Unsigned type value is never < 0. nsieprofilemigrator.cpp 622 PRBool nsIEProfileMigrator::TestForIE7() { ... PRUint32 index = ieVersion.FindChar('.', 0); if (index < 0) return PR_FALSE; ... } I think there could be written like this. _SIGNED_TYPE_ index = ieVersion.FindChar('.', 0); ----------------------------------------------------------------------------- V575 The 'memcmp' function processes '0' elements. Inspect the third argument. pixman-image.c 520 pixman_bool_t pixman_image_set_transform (...) { memcmp (common->transform, transform, sizeof (pixman_transform_t) == 0)) } I think there could be written like this. memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0) ----------------------------------------------------------------------------- V576 Incorrect format. Consider checking the third actual argument of the 'fwprintf' function. The pointer to string of wchar_t type symbols is expected. cairo-win32-surface.c 129 cairo_status_t _cairo_win32_print_gdi_error (const char *context) { ... fwprintf (stderr, L"%s: %S", context, (wchar_t *)lpMsgBuf); ... } I think there could be written like this. fwprintf (stderr, L"%S: %S", context, (wchar_t *)lpMsgBuf); ----------------------------------------------------------------------------- V579 The strncmp function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. affixmgr.cpp 3708 int AffixMgr::parse_convtable(..., const char * keyword) { ... if (strncmp(piece, keyword, sizeof(keyword)) != 0) { HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); delete *rl; *rl = NULL; return 1; } ... } I think there could be written like this. if (strncmp(piece, keyword, strlen(keyword)) != 0) { ----------------------------------------------------------------------------- V579 The InternetSetOptionW function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the fourth argument. http_upload.cc 152 bool HTTPUpload::SendRequest(..., int *timeout, ...) { if (timeout) { if (!InternetSetOption(request.get(), INTERNET_OPTION_SEND_TIMEOUT, timeout, sizeof(timeout))) { fwprintf(stderr, L"Could not unset send timeout, continuing...\n"); } ... } And here: V579 The InternetSetOptionW function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the fourth argument. http_upload.cc 159 ----------------------------------------------------------------------------- V595 The '* jitp' pointer was utilized before it was verified against nullptr. Check lines: 547, 549. compiler.cpp 547 CompileStatus mjit::Compiler::performCompilation(JITScript **jitp) { ... JaegerSpew(JSpew_Scripts, "successfully compiled (code \"%p\") (size \"%u\")\n", (*jitp)->code.m_code.executableAddress(), unsigned((*jitp)->code.m_size)); if (!*jitp) return Compile_Abort; ... } ----------------------------------------------------------------------------- V595 The 'mShellLink' pointer was utilized before it was verified against nullptr. Check lines: 183, 187. nslocalfilewin.cpp 183 nsresult ShortcutResolver::Init() { CoInitialize(NULL); // FIX: we should probably move somewhere higher up during startup HRESULT hres; hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&(mShellLink)); if (SUCCEEDED(hres)) { // Get a pointer to the IPersistFile interface. hres = mShellLink->QueryInterface(IID_IPersistFile, (void**)&mPersistFile); } if (mPersistFile == nsnull || mShellLink == nsnull) return NS_ERROR_FAILURE; return NS_OK; } ----------------------------------------------------------------------------- V595 The 'mShell' pointer was utilized before it was verified against nullptr. Check lines: 1107, 1109. nsselection.cpp 1107 nsresult nsFrameSelection::MoveCaret(...) { ... mShell->FlushPendingNotifications(Flush_Layout); if (!mShell) { return NS_OK; } ... } ----------------------------------------------------------------------------- V519 The '* vp' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 711, 712. jsdbgapi.cpp 712 JS_PUBLIC_API(JSBool) JS_GetValidFrameCalleeObject(JSContext *cx, JSStackFrame *fp, jsval *vp) { Value v; if (!Valueify(fp)->getValidCalleeObject(cx, &v)) return false; *vp = v.isObject() ? v : JSVAL_VOID; *vp = v; return true; } ----------------------------------------------------------------------------- V519 The 'event.refPoint.x' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 545, 546. puppetwidget.cpp 546 nsresult PuppetWidget::DispatchPaintEvent() { ... event.refPoint.x = dirtyRect.x; event.refPoint.x = dirtyRect.y; ... } I think there could be written like this. event.refPoint.y = dirtyRect.y; ----------------------------------------------------------------------------- V557 Array overrun is possible. The value of 'i' index could reach 19. detectcharset.cpp 89 class nsBaseStatis : public nsStatis { public: ... PRUint32 mLWordLen[10]; ... nsBaseStatis::nsBaseStatis(unsigned char aL, unsigned char aH, float aR) { ... for(PRUint32 i = 0; i < 20; i++) mLWordLen[i] = 0; ... } } ... }; I think there could be written like this. for(PRUint32 i = 0; i < 10; i++) or for(PRUint32 i = 0; i < sizeof(mLWordLen)/sizeof(mLWordLen[0]); i++) -----------------------------------------------------------------------------