Condividi tramite


Uso della funzione _analysis_assume per eliminare i falsi difetti

È possibile fornire il verifica driver statico (SDV) con informazioni aggiuntive sul codice sorgente del driver in modo che durante la verifica sia possibile eliminare i report di falsi difetti. I falsi difetti si verificano quando SDV segnala una violazione di regola apparente, ma in una situazione in cui il driver agisce correttamente.

Per fornire SDV con queste informazioni aggiuntive, usare la funzione __analysis_assume . La funzione ha la sintassi seguente:

__analysis_assume( expression ) 

Dove l'espressione può essere qualsiasi espressione che si presuppone di valutare true.

Quando si usa questa funzione, SDV presuppone che la condizione rappresentata dall'espressione sia true nel punto in cui viene visualizzata la funzione __analysis_assume . La funzione __analysis_assume viene usata solo dagli strumenti di analisi statici. La funzione viene ignorata dal compilatore.

Se usi __analysis_assume, è fondamentale che tu sia certo della validità del presupposto che stai facendo. Se si verifica che il presupposto sia falso, ora o in futuro, si potrebbe eliminare un vero difetto. È consigliabile aggiungere sempre un commento al codice che spiega perché si usa la funzione __analysis_assume . Se non è possibile scrivere un motivo per il presupposto, non eliminare il difetto.

È necessario aggiungere la funzione __analysis_assume in base alle esigenze, ogni volta che si trovano falsi difetti che è possibile eliminare in modo sicuro.

Esempi:

Nell'esempio di codice seguente la regola KmDF RequestCompletedLocal segnala un difetto. Si tratta di un falso difetto perché SDV non riesce a interpretare correttamente l'istruzione switch e di conseguenza non immette il ramo in cui viene completata la richiesta.

In questa istruzione switch sono disponibili sei casi possibili. Il driver ha definito sei codici IOCTL, quindi il driver porterà sicuramente uno dei rami. Se viene eseguito uno dei rami, la richiesta viene completata correttamente.

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

Per eliminare in modo sicuro il falso difetto, usare la funzione __analysis_assume per specificare che IoControlCode è garantito essere uno degli IOCTLs definiti dal driver.

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

Per un altro esempio di come è possibile usare __analysis_assume, vedere il codice di esempio usato in Uso di __sdv_save_request e __sdv_retrieve_request per chiamate di procedure posticipate. Nell'esempio viene illustrato come usare __sdv_save_request e __sdv_retrieve_request per i controller di rete (elementi di lavoro, timer e così via). La funzione __analysis_assume viene usata per eliminare i falsi difetti che potrebbero risultare in caso contrario.