Partilhar via


Ferramenta Geral do Verificador de Driver Estático e Limitações Técnicas

O SDV tem as seguintes limitações gerais:

  • O SDV verifica apenas um driver por vez e o driver deve seguir um desses modelos de driver para ser totalmente verificado: WDM, KMDF, NDIS ou Storport. Para obter mais informações sobre os drivers com suporte, consulte Determinando se o Verificador de Driver Estático dá suporte ao driver ou à biblioteca.

  • Os drivers que não se enquadram em uma das categorias acima serão severamente limitados nas regras que podem ser verificadas e têm maior probabilidade de falhar durante a análise.

  • O arquivo de projeto do driver e o código-fonte devem residir no computador local. Não é possível verificar os drivers remotamente.

  • O SDV é instalado com a localidade em inglês (Estados Unidos). Como resultado, elementos dependentes de localidade, como formatação de cadeia de caracteres, usam as variantes em inglês (Estados Unidos). Essa limitação está presente mesmo quando o SDV é instalado em versões localizadas do Windows diferentes do inglês (Estados Unidos).

O mecanismo de verificação SDV tem limitações técnicas que o impedem de interpretar corretamente algum código de driver. Especificamente, o mecanismo de verificação:

  • Não reconhece que inteiros de 32 bits são limitados a 32 bits. Como resultado, ele não detecta erros de estouro ou de subfluxo.

  • Garante que os drivers que declaram seus pontos de entrada com o palavra-chave estático sejam processados corretamente. No entanto, para garantir que os pontos de entrada estáticos sejam reconhecidos, o SDV exigiu uma alteração nos arquivos Sdv-map.h para funções estáticas: por exemplo, se você declarar um ponto de entrada estático:

    static DRIVER_UNLOAD Unload;
    

    O Sdv-map.h não conterá a entrada usual para fun_DriverUnload.

    #define fun_DriverUnload Unload
    

    Em vez disso, você verá que o nome da função está mutilado:

      #define fun_DriverUnload sdv_static_function_Unload_1
    

    Isso é necessário, pois vários módulos podem ter uma função estática chamada Unload. O nome é mutilado para evitar possíveis conflitos.

  • Não é possível interpretar as funções de expedição de driver ou de retorno de chamada de driver definidas em um driver de exportação em que o driver de exportação tem um arquivo de definição de módulo (.def) que oculta a função de expedição do driver. Para evitar esse problema, adicione a função de expedição do driver à seção EXPORTS do arquivo de definição de módulo (.def).

  • Não é possível detectar com êxito o tipo de função de uma função se as referências a seguir a essa função não estiverem na mesma unidade de compilação.

    • Declaração da função.
    • Definição da função.
    • Atribuição da função a um ponto de entrada de driver ou função de retorno de chamada.

    A unidade de compilação é definida aqui como o menor conjunto de arquivos de código-fonte e outros arquivos de origem incluídos por esse arquivo de código-fonte.

    Se um tipo de função não for detectado pelo SDV, o SDV não verificará os rastreamentos originados dessa função.

    Por exemplo, se um driver definir (ou implementar) uma função EvtDriverDeviceAdd no arquivo mydriver.c. Essa unidade de compilação (ou quaisquer arquivos .h que mydriver.c inclui) deve conter a declaração de tipo de função de função para a função EvtDriverDeviceAdd .

  • Não interpreta o tratamento de exceções estruturadas. Para instruções try/except , o SDV analisa a seção protegida como se nenhuma exceção fosse gerada. Não analisa a expressão ou o código do manipulador de exceção.

    // The try/except statement
    __try 
    {
       // guarded section
    }
    __except ( expression )
    {
       // exception handler
    } 
    

    Para instruções try/finally , o SDV analisa a seção protegida e, em seguida, o manipulador de terminação, como se nenhuma exceção fosse gerada.

    // The try/finally statement
    __try {
       // guarded section
    }
    __finally {
       // termination handler
    }
    

    Para as instruções try/except e try/finally , o SDV ignora a instrução leave .

    Para as instruções try/except e try/finally , um salto fora do bloco try impede a análise das instruções except ou finally . Para obter informações sobre como reescrever para que você possa usar uma instrução leave, consulte o tópico para o aviso do compilador C6242.

  • Ignora a aritmética do ponteiro. Por exemplo, ele perderá situações em que um ponteiro é incrementado ou decrementado. Essa limitação pode resultar em resultados falsos negativos e falsos positivos.

  • Ignora uniões. Na maioria das circunstâncias, uma união é tratada como um struct e isso pode resultar em falsos positivos ou falsos negativos.

  • Ignora as operações de conversão, portanto, ele perderá os dois erros que são resolvidos pela reformulação e erros causados pela conversão. Por exemplo, o mecanismo pressupõe que um inteiro que é reformulado como um caractere ainda tem o valor inteiro.

  • Inicializa apenas matrizes que são matrizes de ponteiros de função. O SDV emite um aviso e compacta o inicializador de matriz para os primeiros 1000 elementos. Para outros tipos de matriz, somente o primeiro elemento é inicializado.

  • Construtores de objetos inicializados em matrizes não são chamados. Por exemplo, no snippet de código a seguir, x não é definido como 10 porque o SDV não chama o construtor.

    class A
    {
    public:
        A() {
          x = 10;
        }
    
        int x;
    };
    
    void main()
    {
        A a[1];
    }
    
  • O SDV não dá suporte ao uso de construtores para inicializar matrizes. Por exemplo, no snippet de código a seguir, o construtor para P não será chamado corretamente na função main e não inicializará o elemento na matriz p2:

    class P
    {
    public:
        P() : x(0) {}
        int x;
    };
    
    void main()
    {
        P* p1 = new P[1];
    
        P p2[1] = {P()};
    }
    
  • O SDV ignora cabeçalhos pré-compilados. Os drivers que usam cabeçalhos pré-compilados apenas para acelerar a compilação serão compilados mais lentamente com SDV. Os drivers que devem usar cabeçalhos pré-compilados para compilação bem-sucedida não serão compilados com SDV.

  • Não é possível inferir alguns tipos de atribuições implícitas feitas por meio de chamadas para RtlZeroMemory ou NdisZeroMemory. O mecanismo faz uma análise de melhor esforço para inicializar a memória como zero, mas somente quando ele pode identificar seu tipo. Como resultado, o código que depende dessas funções para inicializar a memória pode gerar falsos defeitos em alguns caminhos de código.

  • Não dá suporte a um modelo de memória que permita que ele acompanhe o envio manual de solicitações de E/S para um driver KMDF. O mecanismo só dá suporte a métodos que dependem da estrutura para entregar as solicitações de E/S ao driver (para expedição sequencial ou paralela).

  • Não dá suporte ao uso do tipo de dados float para comparações. Essa limitação técnica pode produzir resultados falsos negativos e falsos positivos.

  • O SDV não dá suporte a herança virtual ou funções virtuais. O SDV não gera defeitos que seguem um caminho de código por meio de funções virtuais, o que pode levar a defeitos verdadeiros perdidos. A herança virtual é tratada como herança regular, o que pode levar a defeitos falsos ou defeitos verdadeiros perdidos.