使用 _analysis_assume 函式來抑制誤報的瑕疵
您可以提供靜態驅動程式驗證器 (SDV) 與驅動程式原始碼的其他資訊,以便在驗證期間隱藏錯誤缺陷的報告。 當 SDV 報告明顯的規則違反時,偽缺陷會發生,即便在駕駛者正確行事的情況下。
若要提供 SDV 這項額外資訊,請使用 __analysis_assume 函式。 函式具有下列語法:
__analysis_assume( expression )
其中 表示式 可以是假設評估為 true 的任何表達式。
當您使用此函式時,SDV 會假設 表示式所代表的條件true 出現在 __analysis_assume 函式的點。 __analysis_assume 函式僅供靜態分析工具使用。 編譯程式會忽略函式。
如果您使用 __analysis_assume,請務必確定您進行之假設的有效性。 如果事實證明,您的假設是 錯誤的,無論是現在還是將來,這都可能掩蓋真正的瑕疵。 建議您一律在程序代碼中新增批注,以說明為何要使用 __analysis_assume 函式。 如果您無法撰寫假設的原因,請勿隱藏瑕疵。
您應該視需要新增 __analysis_assume 函式,每當發現可以安全地隱藏的錯誤缺陷時。
範例
在下列程式代碼範例中,KMDF 規則 RequestCompletedLocal 回報瑕疵。 這是一個誤報的問題,因為 SDV 無法正確解譯 switch 語句,因此未能進入執行要求完成的分支。
在此 switch 語句中,有六種可能的情況。 驅動程式已定義六個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 函式可用來隱藏可能導致的誤判缺陷。