Partager via


Utilisation de la fonction _analysis_assume pour supprimer les faux défauts

Vous pouvez fournir à Static Driver Verifier (SDV) des informations supplémentaires sur le code source de votre pilote afin que, pendant la vérification, vous puissiez supprimer les rapports de faux défauts. Les faux défauts se produisent lorsque SDV signale une violation apparente de règle, mais dans une situation où le conducteur agit correctement.

Pour fournir ces informations supplémentaires à SDV, utilisez la fonction __analysis_assume . La fonction a la syntaxe suivante :

__analysis_assume( expression ) 

expression peut être n’importe quelle expression supposée avoir la valeur true.

Lorsque vous utilisez cette fonction, SDV suppose que la condition représentée par l’expression est vraie au point où la fonction __analysis_assume apparaît. La fonction __analysis_assume est utilisée uniquement par les outils d’analyse statique. La fonction est ignorée par le compilateur.

Si vous utilisez __analysis_assume, il est essentiel que vous soyez certain de la validité de l’hypothèse que vous faites. S’il s’avère que votre hypothèse est fausse, maintenant ou à l’avenir, vous pourriez supprimer un vrai défaut. Nous vous recommandons d’ajouter toujours un commentaire à votre code qui explique pourquoi vous utilisez la fonction __analysis_assume . Si vous ne pouvez pas écrire une raison pour l’hypothèse, ne supprimez pas le défaut.

Vous devez ajouter la fonction __analysis_assume si nécessaire, chaque fois que vous trouvez de faux défauts que vous pouvez supprimer en toute sécurité.

Exemples

Dans l’exemple de code suivant, la règle KMDF RequestCompletedLocal signale un défaut. Il s’agit d’un faux défaut, car SDV ne peut pas interpréter correctement l’instruction switch et n’entre donc pas dans la branche où la demande est effectuée.

Dans cette instruction switch , il existe six cas possibles. Le pilote a défini six codes IOCTL, de sorte que le pilote prendra certainement l’une des branches. Si l’une des branches est prise, la demande est effectuée avec succès.

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

Pour supprimer en toute sécurité le faux défaut, utilisez la fonction __analysis_assume pour spécifier que l’IoControlCode est garanti comme étant l’un des IOCTL définis par le pilote.

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

Pour obtenir un autre exemple d’utilisation de __analysis_assume, consultez l’exemple de code utilisé dans Utilisation de __sdv_save_request et __sdv_retrieve_request pour les appels de procédure différée. L’exemple montre comment utiliser __sdv_save_request et __sdv_retrieve_request pour les DPC (workitems, timers, etc.). La fonction __analysis_assume est utilisée pour supprimer les faux défauts qui pourraient autrement en résulter.