Introduction

Warning 1

template <class T, int upShiftInt, int downShiftInt, int upMulInt, int downDivInt> struct FPTemplate { .... FPTemplate operator<<(int numBits) const { return value << numBits; } FPTemplate operator>>(int numBits) const { return value << numBits; } FPTemplate& operator<<=(int numBits) { value <<= numBits; return *this;} FPTemplate& operator>>=(int numBits) { value >>= numBits; return *this;} .... }

Warning 2

static const int kSpanFormatCapacity = 16; struct Span8 { .... char mFormat[kSpanFormatCapacity]; .... }; static int OVprintfCore(....) { .... EA_ASSERT(nFormatLength < kSpanFormatCapacity); if(nFormatLength < kSpanFormatCapacity) spans[spanIndex].mFormat[nFormatLength++] = *p; // <= else return -1; switch(*p) { case 'b': case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'g': case 'G': case 'e': case 'E': case 'f': case 'F': case 'a': case 'A': case 'p': case 'c': case 'C': case 's': case 'S': case 'n': { // Finalize the current span. spans[spanIndex].mpEnd = p + 1; spans[spanIndex].mFormat[nFormatLength] = 0; // <= spans[spanIndex].mFormatChar = *p; if(++spanIndex == kSpanCapacity) break; .... }

V557 Array overrun is possible. The value of 'nFormatLength' index could reach 16. EASprintfOrdered.cpp 614

V557 Array overrun is possible. The value of 'nFormatLength' index could reach 16. EASprintfOrdered.cpp 977

Warning 3

static int OVprintfCore(....) { .... for(result = 1; (result >= 0) && (p < pEnd); ++p) { if(pWriteFunction8(p, 1, pWriteFunctionContext8, kWFSIntermediate) < 0) return -1; nWriteCountSum += result; } .... }

V560 A part of conditional expression is always true: (result >= 0). EASprintfOrdered.cpp 852

V560 A part of conditional expression is always true: (result >= 0). EASprintfOrdered.cpp 1215

Warning 4

static int OVprintfCore(....) { .... int spanArgOrder[kArgCapacity] = { -1 }; .... }

V1009 Check the array initialization. Only the first element is initialized explicitly. The rest elements are initialized with zeros. EASprintfOrdered.cpp 518

V1009 Check the array initialization. Only the first element is initialized explicitly. The rest elements are initialized with zeros. EASprintfOrdered.cpp 881

Warning 5

inline void int128_t::Modulus(....) const { .... bool bDividendNegative = false; bool bDivisorNegative = false; .... if( (bDividendNegative && !bDivisorNegative) || (!bDividendNegative && bDivisorNegative)) { quotient.Negate(); } .... }

if( bDividendNegative != bDivisorNegative) { quotient.Negate(); }

Conclusion

Our attention was recently attracted by the Electronic Arts repository on GitHub. It's tiny, and of the twenty-three projects available there, only a few C++ libraries seemed interesting: EASTL, EAStdC, EABase, EAThread, EATest, EAMain, and EAAssert. The projects themselves are tiny too (about 10 files each), so bugs were found only in the «largest» project of 20 files :D But we did find them, and they do look interesting! As I was writing this post, we were also having a lively discussion of EA games and the company's policy :D Electronic Arts (EA) is an American video game company. It has a small repository on GitHub and a few C++ projects, namely C++ libraries: EASTL, EAStdC, EABase, EAThread, EATest, EAMain, and EAAssert. They are tiny, and the PVS-Studio analyzer managed to find any bugs at all only in the «largest» project, EAStdC (20 files). With sizes like that, you can't reliably judge the overall code quality, so just take a look at the following five warnings and decide for yourselves. V524 It is odd that the body of '>>' function is fully equivalent to the body of '<>. This looks very much like a copy-paste mistake. V557 Array overrun is possible. The value of 'nFormatLength' index could reach 16. EASprintfOrdered.cpp 246Thearray consists ofelements, so the last valid element's index is. In its current form, thefunction ends up incrementing the index oftoif it has the highest possible index, i.e.. After that, an array-out-of-bounds error will occur in thestatement.This fragment was copied two more times: V560 A part of conditional expression is always true: (result >= 0). EASprintfOrdered.cpp 489Thecondition is always true as thevariable is not changed anywhere in the loop. The code doesn't look right at all, and there must be some mistake in it.This fragment was copied two more times: V1009 Check the array initialization. Only the first element is initialized explicitly. The rest elements are initialized with zeros. EASprintfOrdered.cpp 151This is not necessarily a bug, but the authors should be warned that only the first element of thearray is initialized to, while all the rest will be set to 0.This fragment was copied two more times: V728 An excessive check can be simplified. The '(A && !B) || (!A && B)' expression is equivalent to the 'bool(A) != bool(B)' expression. int128.h 1242I formatted this example for clarity, but in its original form, this condition is very long and difficult to read. But we can make it much better by simplifying the conditional expression, as the analyzer suggests:The code is much shorter now, which makes the condition's logic much easier to grasp.As you may have noticed, most of the warnings have two more duplicates, and all those duplicates are found in the same file. Code duplication is a very bad anti-pattern since it complicates program maintenance a lot. When bugs creep into such code, the program's stability drops drastically because they spread all over the code.Hopefully, EA will upload some other interesting projects and we'll visit their repository once again :). Meanwhile, welcome to download PVS-Studio and try it on your own projects.