다음을 통해 공유


_analysis_assume 함수를 사용하여 잘못된 결함 억제

확인 중에 잘못된 결함에 대한 보고서를 표시하지 않도록 드라이버 소스 코드에 대한 추가 정보를 SDV(정적 드라이버 검증 도구)에 제공할 수 있습니다. 잘못된 결함은 SDV가 명백한 규칙 위반을 보고하지만 드라이버가 올바르게 작동하는 상황에서 발생합니다.

이 추가 정보를 SDV에 제공하려면 __analysis_assume 함수를 사용합니다. 함수에는 다음 구문이 있습니다.

__analysis_assume( expression ) 

여기서 true로 계산되는 모든 식일 수 있습니다.

이 함수를 사용하는 경우 SDV 식이 나타내는 조건이 __analysis_assume 함수가 나타나는 지점에서 true라고 가정합니다. __analysis_assume 함수는 정적 분석 도구에서만 사용됩니다. 함수는 컴파일러에서 무시됩니다.

__analysis_assume 사용하는 경우 가정이 유효한지 확인하는 것이 매우 중요합니다. 가정이 현재 또는 미래에 거짓인 것으로 밝혀지면 진정한 결함을 억제할 수 있습니다. __analysis_assume 함수를 사용하는 이유를 설명하는 주석을 코드에 항상 추가하는 것이 좋습니다. 가정을 위한 이유를 작성할 수 없는 경우 결함을 표시하지 마세요.

안전하게 억제할 수 있는 잘못된 결함을 발견할 때마다 필요에 따라 __analysis_assume 함수를 추가해야 합니다.

예제

다음 코드 예제에서 KMDF 규칙 RequestCompletedLocal은 결함을 보고합니다. 이는 SDV가 switch 문을 올바르게 해석할 수 없으므로 요청이 완료된 분기에 들어가지 않기 때문에 잘못된 결함입니다.

switch 문에는 6가지 가능한 사례가 있습니다. 드라이버는 6개의 IOCTL 코드를 정의했기 때문에 드라이버는 확실히 분기 중 하나를 사용합니다. 분기 중 하나가 수행되면 요청이 성공적으로 완료됩니다.

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

잘못된 결함을 안전하게 억제하려면 __analysis_assume 함수를 사용하여 IoControlCode 가 드라이버가 정의한 IOCTL 중 하나로 보장되도록 지정합니다.

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

__analysis_assume 사용하는 방법에 대한 또 다른 예제는 지연 프로시저 호출에 __sdv_save_request 및 __sdv_retrieve_request 사용에서 사용되는 예제 코드를 참조하세요. 이 예제에서는 DPC(작업 영역, 타이머 등)에 __sdv_save_request 및 __sdv_retrieve_request 사용하는 방법을 보여 줍니다. __analysis_assume 함수는 그렇지 않으면 발생할 수 있는 잘못된 결함을 표시하지 않는 데 사용됩니다.