Udostępnij przez


Pomijanie fałszywych wad za pomocą funkcji _analysis_assume

Możesz podać statycznemu weryfikatorowi sterowników (SDV) dodatkowe informacje o kodzie źródłowym sterownika, aby podczas weryfikacji można było zignorować raporty fałszywych wad. Fałszywe wady występują, gdy SDV zgłasza pozorne naruszenie reguły, ale w sytuacji, gdy sterownik działa prawidłowo.

Aby przekazać SDV tych dodatkowych informacji, użyj funkcji __analysis_assume. Funkcja ma następującą składnię:

__analysis_assume( expression ) 

Gdzie wyrażenie może być dowolnym wyrażeniem, które uznaje się za oceniające się na prawda.

Jeśli używasz tej funkcji, sdV zakłada, że warunek reprezentowany przez wyrażenie jest spełniony w momencie, w którym pojawia się funkcja __analysis_assume . Funkcja __analysis_assume jest używana tylko przez narzędzia do analizy statycznej. Funkcja jest ignorowana przez kompilator.

Jeśli używasz __analysis_assume, niezwykle ważne jest, aby mieć pewność ważności przyjętego założenia. Jeśli okaże się, że twoje założenie jest fałszywe, teraz lub w przyszłości, możesz pominąć prawdziwą wadę. Zalecamy, aby zawsze dodawać komentarz do kodu, który wyjaśnia, dlaczego używasz funkcji __analysis_assume . Jeśli nie możesz napisać przyczyny założenia, nie pomijaj wady.

Należy dodać funkcję __analysis_assume zgodnie z potrzebami, gdy znajdziesz fałszywe wady, które można bezpiecznie pominąć.

przykłady

W poniższym przykładzie kodu reguła KMDF RequestCompletedLocal zgłasza usterkę. Jest to fałszywa usterka, ponieważ SDV nie może poprawnie interpretować instrukcji switch i w związku z tym nie wchodzi do gałęzi, w której żądanie jest kompletowane.

W tej instrukcji switch istnieje sześć możliwych przypadków. Sterownik zdefiniował sześć kodów IOCTL, więc sterownik na pewno weźmie jedną z gałęzi. Jeśli jedna z gałęzi zostanie wybrana, żądanie zostanie ukończone pomyślnie.

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

Aby bezpiecznie stłumić fałszywy defekt, użyj funkcji __analysis_assume, aby określić, że IoControlCode jest gwarantowany jako jeden z IOCTLs, które sterownik zdefiniował.

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

Aby zapoznać się z innym przykładem użycia __analysis_assume, zobacz przykładowy kod używany w przykładzie z użyciem __sdv_save_request i __sdv_retrieve_request dla odroczonych wywołań procedur. W przykładzie pokazano, jak używać __sdv_save_request i __sdv_retrieve_request dla kontrolerów DPC (elementów roboczych, czasomierzy itd.). Funkcja __analysis_assume służy do pomijania fałszywych błędów, które w przeciwnym razie mogą wystąpić.