Bibliotecas de artes eletrônicas de quase boa qualidade

Chamamos nossa atenção para o repositório de Artes Eletrônicas no GitHub. É muito pequeno e, dos vinte e três projetos, estávamos interessados ​​apenas em algumas bibliotecas C ++: EASTL, EAStdC, EABase, EAThread, EATest, EAMain e EAAssert. Os projetos também eram muito pequenos (cerca de 10 arquivos); portanto, encontramos erros apenas no “maior” de 20 arquivos: D Mas também encontramos outros interessantes! Enquanto o artigo estava sendo escrito, meus colegas e eu também discutimos vigorosamente os jogos da EA e sua estratégia: D

Quadro 1


1. Introdução


A Electronic Arts (EA) é uma empresa americana que distribui videogames. No site do GitHub, ela possui um pequeno repositório e vários projetos em C ++. Estas são as bibliotecas C ++: EASTL, EAStdC, EABase, EAThread, EATest, EAMain e EAAssert. Eles são muito pequenos e encontramos erros interessantes usando o analisador PVS-Studio apenas no "maior" deles - EAStdC (20 arquivos). Com esses volumes, é difícil falar sobre a qualidade do código como um todo. Avalie apenas 5 avisos e decida por si mesmo.

Aviso 1


V524 É estranho que o corpo da função '>>' seja totalmente equivalente ao corpo da função '<<'. EAFixedPoint.h 287

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;} .... } 

Ao sobrecarregar os operadores de turno, o programador digitou um deles, confundindo os operadores << e >>. Muito provavelmente, este é o resultado da programação de copiar e colar.

Aviso 2


A saturação da matriz V557 é possível. O valor do índice 'nFormatLength' pode chegar a 16. EASprintfOrdered.cpp 246

 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; .... } 

A matriz spans [spanIndex] .mFormat consiste em 16 elementos, ou seja, o último item válido tem um índice de 15 . Agora, o código da função OVprintfCore é gravado para que, se o índice nFormatLength tiver o índice máximo possível - 15 , ocorrerá um incremento de até 16 . Além disso, na instrução switch, é possível ir além do limite da matriz.

Este fragmento de código foi copiado para mais 2 lugares:

  • A saturação da matriz V557 é possível. O valor do índice 'nFormatLength' pode chegar a 16. EASprintfOrdered.cpp 614
  • A saturação da matriz V557 é possível. O valor do índice 'nFormatLength' pode chegar a 16. EASprintfOrdered.cpp 977

Aviso 3


V560 Uma parte da expressão condicional é sempre verdadeira: (resultado> = 0). EASprintfOrdered.cpp 489

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

O resultado da condição > = 0 é sempre verdadeiro, porque a variável resultado não muda em nenhum lugar do loop. O código parece muito suspeito e provavelmente há um erro nesse código.

Este fragmento de código foi copiado para mais 2 lugares:

  • V560 Uma parte da expressão condicional é sempre verdadeira: (resultado> = 0). EASprintfOrdered.cpp 852
  • V560 Uma parte da expressão condicional é sempre verdadeira: (resultado> = 0). EASprintfOrdered.cpp 1215

Aviso 4


V1009 Verifique a inicialização do array. Somente o primeiro elemento é inicializado explicitamente. Os demais elementos são inicializados com zeros. EASprintfOrdered.cpp 151

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

Isso pode não ser um erro, mas os desenvolvedores devem ser avisados ​​de que apenas o primeiro elemento da matriz spanArgOrder é inicializado com o valor -1 , e todos os outros terão o valor 0.

Este fragmento de código foi copiado para mais 2 lugares:

  • V1009 Verifique a inicialização do array. Somente o primeiro elemento é inicializado explicitamente. Os demais elementos são inicializados com zeros. EASprintfOrdered.cpp 518
  • V1009 Verifique a inicialização do array. Somente o primeiro elemento é inicializado explicitamente. Os demais elementos são inicializados com zeros. EASprintfOrdered.cpp 881

Aviso 5


V728 Uma verificação excessiva pode ser simplificada. O '(A &&! B) || (! A && B) 'expressão é equivalente à expressão' bool (A)! = Bool (B) '. int128.h 1242

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

Esse fragmento de código foi formatado por conveniência, mas no original é uma condição muito longa e difícil de ler. Outra coisa é se simplificarmos a expressão condicional, como aconselha o analisador:

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

O código ficou muito mais curto, o que simplificou bastante o entendimento da lógica da expressão condicional.

Conclusão


Como você deve ter notado, a maioria dos avisos suspeitos é duplicada em três locais e no mesmo arquivo. A duplicação de código é uma prática de desenvolvimento muito ruim, pois complica o suporte ao código. E se ocorrer um erro nesse código, a estabilidade do programa diminuirá acentuadamente devido à propagação de erros por todo o código.

Vamos esperar que outra coisa interessante seja publicada e retornaremos a este repositório novamente :). Enquanto isso, sugiro aqueles que desejam baixar o PVS-Studio e tentar verificar seus próprios projetos.



Se você deseja compartilhar este artigo com um público que fala inglês, use o link para a tradução: Svyatoslav Razmyslov. Bibliotecas quase perfeitas pela Electronic Arts .

Source: https://habr.com/ru/post/pt461679/


All Articles