使用 _analysis_assume 函式來隱藏 False 瑕疵
您可以為靜態驅動程式驗證程式 (SDV) 提供驅動程式原始程式碼的其他資訊,以便在驗證期間隱藏誤判瑕疵的報告。 當 SDV 回報明顯的規則違規時,就會發生誤判瑕疵,但在驅動程式正常運作的情況下發生。
若要提供 SDV 的額外資訊,請使用 __analysis_assume 函式。 函式具有下列語法:
__analysis_assume( expression )
其中 expression 可以是假設評估為 true的任何運算式。
當您使用此函式時,SDV 會假設運算式所代表的條件在__analysis_assume函式出現時為true。 __analysis_assume函式僅供靜態分析工具使用。 編譯器會忽略函式。
如果您使用 __analysis_assume,請務必確定您所做假設的有效性。 如果假設假設為 false,可能是現在或未來,您可能會隱藏真正的瑕疵。 建議您一律將批註新增至程式碼,以說明您使用 __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 保證為驅動程式已定義的其中一個 IOCTLs。
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中使用的範例程式碼。 此範例示範如何在工作專案、計時器等 (工作專案、計時器等) 使用 __sdv_save_request 和 __sdv_retrieve_request 。 __analysis_assume函式是用來隱藏可能導致的誤判瑕疵。