Partilhar via


Usando a função _analysis_assume para suprimir falsos defeitos

Você pode fornecer ao Verificador de Driver Estático (SDV) informações adicionais sobre o código-fonte do driver para que, durante a verificação, você possa suprimir os relatórios de defeitos falsos. Os falsos defeitos ocorrem quando o SDV relata uma aparente violação da regra, mas em uma situação em que o motorista está agindo corretamente.

Para fornecer essas informações adicionais ao SDV, use a função __analysis_assume . A função tem a seguinte sintaxe:

__analysis_assume( expression ) 

Onde expressão pode ser qualquer expressão que se supõe ser avaliada como verdadeira.

Quando você usa essa função, SDV assume que a condição representada pela expressão é verdadeira no ponto onde a função __analysis_assume aparece. A função __analysis_assume é usada apenas pelas ferramentas de análise estática. A função é ignorada pelo compilador.

Se você usa __analysis_assume, é extremamente importante que você esteja certo da validade da suposição que está fazendo. Se se verificar que a sua suposição é falsa, agora ou no futuro, pode estar a suprimir um verdadeiro defeito. Recomendamos que você sempre adicione um comentário ao seu código que explique por que você está usando a função __analysis_assume . Se você não puder escrever um motivo para a suposição, não suprima o defeito.

Você deve adicionar a função __analysis_assume conforme necessário, sempre que encontrar defeitos falsos que você pode suprimir com segurança.

exemplos

No exemplo de código a seguir, a regra KMDF RequestCompletedLocal relata um defeito. Este é um defeito falso porque SDV não pode interpretar corretamente a instrução switch e, consequentemente, não entra na ramificação onde a solicitação é concluída.

Nesta instrução switch, há seis casos possíveis. O controlador definiu seis códigos IOCTL, então o controlador definitivamente pegará um dos ramos. Se uma das ramificações for tomada, a solicitação será concluída com êxito.

VOID
PortIOEvtIoDeviceControl(
      __in WDFQUEUE     Queue,
      __in WDFREQUEST   Request,
      __in size_t       OutputBufferLength,
  __in size_t       InputBufferLength,
  __in ULONG        IoControlCode
     )
 
     PDEVICE_CONTEXT devContext = NULL;
     WDFDEVICE device;

     PAGED_CODE();
 
     device = WdfIoQueueGetDevice(Queue);
 
     devContext = PortIOGetDeviceContext(device);
 
     switch(IoControlCode)
         case IOCTL_GPD_READ_PORT_UCHAR:
         case IOCTL_GPD_READ_PORT_USHORT:
         case IOCTL_GPD_READ_PORT_ULONG:
             PortIOIoctlReadPort(devContext,
                                 Request,
                                 OutputBufferLength,
                                 InputBufferLength,
                                 IoControlCode);
             break;

 
         case IOCTL_GPD_WRITE_PORT_UCHAR:
         case IOCTL_GPD_WRITE_PORT_USHORT:
         case IOCTL_GPD_WRITE_PORT_ULONG:    
             PortIOIoctlWritePort(devContext,
                                  Request,
                                  OutputBufferLength,
                                  InputBufferLength,
                                  IoControlCode);
             break;
 
     }
 
}

Para suprimir com segurança o falso defeito, use a função __analysis_assume para especificar que o IoControlCode é garantido como um dos IOCTLs que o driver definiu.

VOID
PortIOEvtIoDeviceControl(
      __in WDFQUEUE     Queue,
      __in WDFREQUEST   Request,
      __in size_t       OutputBufferLength,
      __in size_t       InputBufferLength,
      __in ULONG        IoControlCode
     )
 
     PDEVICE_CONTEXT devContext = NULL;
     WDFDEVICE device;

     PAGED_CODE();
 
     device = WdfIoQueueGetDevice(Queue);
 
     devContext = PortIOGetDeviceContext(device);

/* Use __analysis_assume to suppress a false defect for the SDV RequestCompletedLocal rule. 
There are only 6 possible IOCTLs for IoControlCode; each case is covered in the switch statement.
*/

 __analysis_assume( IoControlCode == IOCTL_GPD_READ_PORT_UCHAR || \
                       IoControlCode == IOCTL_GPD_READ_PORT_USHORT|| \
                       IoControlCode == IOCTL_GPD_READ_PORT_ULONG || \
                       IoControlCode == IOCTL_GPD_WRITE_PORT_UCHAR|| \
                       IoControlCode == IOCTL_GPD_WRITE_PORT_USHORT|| \
                       IoControlCode == IOCTL_GPD_WRITE_PORT_ULONG);

     switch(IoControlCode)
         case IOCTL_GPD_READ_PORT_UCHAR:
         case IOCTL_GPD_READ_PORT_USHORT:
         case IOCTL_GPD_READ_PORT_ULONG:
             PortIOIoctlReadPort(devContext,
                                 Request,
                                 OutputBufferLength,
                                 InputBufferLength,
                                 IoControlCode);
             break;

 
         case IOCTL_GPD_WRITE_PORT_UCHAR:
         case IOCTL_GPD_WRITE_PORT_USHORT:
         case IOCTL_GPD_WRITE_PORT_ULONG:    
             PortIOIoctlWritePort(devContext,
                                  Request,
                                  OutputBufferLength,
                                  InputBufferLength,
                                  IoControlCode);
             break;
 
     }
 
}

Para obter outro exemplo de como você pode usar __analysis_assume, consulte o código de exemplo usado em Usando __sdv_save_request e __sdv_retrieve_request para chamadas de procedimento adiado. O exemplo mostra como usar __sdv_save_request e __sdv_retrieve_request para DPCs (itens de trabalho, temporizadores e assim por diante). A função __analysis_assume é usada para suprimir falsos defeitos que, de outra forma, poderiam resultar.