|
83 | 83 | "level": "warning" |
84 | 84 | }, |
85 | 85 | "help": { |
86 | | - "text": "# Irql Float State Mismatch\nThe IRQL where the floating-point state was saved does not match the current IRQL (for this restore operation).\n\n\n## Recommendation\nThe IRQL at which the driver is executing when it restores a floating-point state is different than the IRQL at which it was executing when it saved the floating-point state. Because the IRQL at which the driver runs determines how the floating-point state is saved, the driver must be executing at the same IRQL when it calls the functions to save and to restore the floating-point state.\n\n\n## Example\nExample of incorrect code. Floating point state was saved at APC_LEVEL but restored at PASSIVE_LEVEL\n\n```c\n \n\t\t_IRQL_requires_(PASSIVE_LEVEL) \n\t\tvoid driver_utility_bad(void)\n\t\t{\n\t\t\tKIRQL oldIRQL;\n\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\t\t\t// running at APC level\n\t\t\tKFLOATING_SAVE FloatBuf;\n\t\t\tif (KeSaveFloatingPointState(&FloatBuf))\n\t\t\t{\n\t\t\t\tKeLowerIrql(oldIRQL); // lower back to PASSIVE_LEVEL\n\t\t\t\t// ...\n\t\t\t\tKeRestoreFloatingPointState(&FloatBuf);\n\t\t\t}\n\t\t}\n\t\t\n```\nCorrect example\n\n```c\n \n\t\t\t_IRQL_requires_(PASSIVE_LEVEL) \n\t\t\tvoid driver_utility_good(void)\n\t\t\t{\n\t\t\t\t// running at APC level\n\t\t\t\tKFLOATING_SAVE FloatBuf;\n\t\t\t\tKIRQL oldIRQL;\n\t\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\n\t\t\t\tif (KeSaveFloatingPointState(&FloatBuf))\n\t\t\t\t{\n\t\t\t\t\tKeLowerIrql(oldIRQL);\n\t\t\t\t\t// ...\n\t\t\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\t\t\t\t\tKeRestoreFloatingPointState(&FloatBuf);\n\t\t\t\t}\n\t\t\t}\n\t\t\n```\n\n## References\n* [ C28111 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28111-floating-point-irql-mismatch)\n\n## Semmle-specific notes\n**Known false negatives.** The query suppresses save / restore pairs when no IRQL-changing call sits between the save call and the restore call on a source line that lies textually within the enclosing function. This suppression eliminates a class of may-analysis false positives where the save and the restore are at the same IRQL within a single dynamic invocation but the IRQL inference reports different hypothetical entry IRQLs. The check has the following limitations:\n\n* **Cross-function save / restore.** When the save and the restore are routed through helper functions that wrap `KeSaveFloatingPointState` / `KeRestoreFloatingPointState`, and the IRQL change happens in the caller, no in-function intermediate call is found and the mismatch is silently suppressed.\n* **Indirect calls.** IRQL changes performed by an indirect call (function pointer or dispatch-table call) between save and restore are not detected, because the predicate only inspects the static call target.\n* **Loops where the restore is textually before the save.** The filter compares source line numbers; in a loop body whose first statement is the restore and last statement is the save (with the IRQL change after the save), the line range becomes empty and no intermediate IRQL change is seen.\nIf a real mismatch is being suppressed, eliminate the wrapper or add explicit `_IRQL_raises_` / `_IRQL_saves_global_` annotations to the helper so its IRQL behavior is visible without body inspection.\n\n", |
87 | | - "markdown": "# Irql Float State Mismatch\nThe IRQL where the floating-point state was saved does not match the current IRQL (for this restore operation).\n\n\n## Recommendation\nThe IRQL at which the driver is executing when it restores a floating-point state is different than the IRQL at which it was executing when it saved the floating-point state. Because the IRQL at which the driver runs determines how the floating-point state is saved, the driver must be executing at the same IRQL when it calls the functions to save and to restore the floating-point state.\n\n\n## Example\nExample of incorrect code. Floating point state was saved at APC_LEVEL but restored at PASSIVE_LEVEL\n\n```c\n \n\t\t_IRQL_requires_(PASSIVE_LEVEL) \n\t\tvoid driver_utility_bad(void)\n\t\t{\n\t\t\tKIRQL oldIRQL;\n\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\t\t\t// running at APC level\n\t\t\tKFLOATING_SAVE FloatBuf;\n\t\t\tif (KeSaveFloatingPointState(&FloatBuf))\n\t\t\t{\n\t\t\t\tKeLowerIrql(oldIRQL); // lower back to PASSIVE_LEVEL\n\t\t\t\t// ...\n\t\t\t\tKeRestoreFloatingPointState(&FloatBuf);\n\t\t\t}\n\t\t}\n\t\t\n```\nCorrect example\n\n```c\n \n\t\t\t_IRQL_requires_(PASSIVE_LEVEL) \n\t\t\tvoid driver_utility_good(void)\n\t\t\t{\n\t\t\t\t// running at APC level\n\t\t\t\tKFLOATING_SAVE FloatBuf;\n\t\t\t\tKIRQL oldIRQL;\n\t\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\n\t\t\t\tif (KeSaveFloatingPointState(&FloatBuf))\n\t\t\t\t{\n\t\t\t\t\tKeLowerIrql(oldIRQL);\n\t\t\t\t\t// ...\n\t\t\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\t\t\t\t\tKeRestoreFloatingPointState(&FloatBuf);\n\t\t\t\t}\n\t\t\t}\n\t\t\n```\n\n## References\n* [ C28111 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28111-floating-point-irql-mismatch)\n\n## Semmle-specific notes\n**Known false negatives.** The query suppresses save / restore pairs when no IRQL-changing call sits between the save call and the restore call on a source line that lies textually within the enclosing function. This suppression eliminates a class of may-analysis false positives where the save and the restore are at the same IRQL within a single dynamic invocation but the IRQL inference reports different hypothetical entry IRQLs. The check has the following limitations:\n\n* **Cross-function save / restore.** When the save and the restore are routed through helper functions that wrap `KeSaveFloatingPointState` / `KeRestoreFloatingPointState`, and the IRQL change happens in the caller, no in-function intermediate call is found and the mismatch is silently suppressed.\n* **Indirect calls.** IRQL changes performed by an indirect call (function pointer or dispatch-table call) between save and restore are not detected, because the predicate only inspects the static call target.\n* **Loops where the restore is textually before the save.** The filter compares source line numbers; in a loop body whose first statement is the restore and last statement is the save (with the IRQL change after the save), the line range becomes empty and no intermediate IRQL change is seen.\nIf a real mismatch is being suppressed, eliminate the wrapper or add explicit `_IRQL_raises_` / `_IRQL_saves_global_` annotations to the helper so its IRQL behavior is visible without body inspection.\n\n" |
| 86 | + "text": "# Irql Float State Mismatch\nThe IRQL where the floating-point state was saved does not match the current IRQL (for this restore operation).\n\n\n## Recommendation\nThe IRQL at which the driver is executing when it restores a floating-point state is different than the IRQL at which it was executing when it saved the floating-point state. Because the IRQL at which the driver runs determines how the floating-point state is saved, the driver must be executing at the same IRQL when it calls the functions to save and to restore the floating-point state.\n\n\n## Example\nExample of incorrect code. Floating point state was saved at APC_LEVEL but restored at PASSIVE_LEVEL\n\n```c\n \n\t\t_IRQL_requires_(PASSIVE_LEVEL) \n\t\tvoid driver_utility_bad(void)\n\t\t{\n\t\t\tKIRQL oldIRQL;\n\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\t\t\t// running at APC level\n\t\t\tKFLOATING_SAVE FloatBuf;\n\t\t\tif (KeSaveFloatingPointState(&FloatBuf))\n\t\t\t{\n\t\t\t\tKeLowerIrql(oldIRQL); // lower back to PASSIVE_LEVEL\n\t\t\t\t// ...\n\t\t\t\tKeRestoreFloatingPointState(&FloatBuf);\n\t\t\t}\n\t\t}\n\t\t\n```\nCorrect example\n\n```c\n \n\t\t\t_IRQL_requires_(PASSIVE_LEVEL) \n\t\t\tvoid driver_utility_good(void)\n\t\t\t{\n\t\t\t\t// running at APC level\n\t\t\t\tKFLOATING_SAVE FloatBuf;\n\t\t\t\tKIRQL oldIRQL;\n\t\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\n\t\t\t\tif (KeSaveFloatingPointState(&FloatBuf))\n\t\t\t\t{\n\t\t\t\t\tKeLowerIrql(oldIRQL);\n\t\t\t\t\t// ...\n\t\t\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\t\t\t\t\tKeRestoreFloatingPointState(&FloatBuf);\n\t\t\t\t}\n\t\t\t}\n\t\t\n```\n\n## References\n* [ C28111 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28111-floating-point-irql-mismatch)\n\n## Semmle-specific notes\n**Wrapper / common-caller pattern.** The query reasons about IRQL-changing calls between save and restore not only when both calls share an enclosing function, but also when they sit inside one-level helper wrappers that are called from a common caller (for example, thin `save_fp_helper` / `restore_fp_helper` functions that simply forward to `KeSaveFloatingPointState` / `KeRestoreFloatingPointState`). In those cases the intermediate IRQL transition is searched in the common caller (or in either helper's enclosing function for the asymmetric case where one side is a helper and the other is direct).\n\n**Remaining limitations.** The position-based filter still does not detect:\n\n* **IRQL changes performed deep inside helper bodies.** If the helper function itself raises or lowers the IRQL after the save (or before the restore), the change is not visible from the common caller's source-position view, and no intermediate IRQL change is found. Annotating the helper with `_IRQL_raises_` or `_IRQL_saves_global_` makes its IRQL behavior visible without body inspection.\n* **Indirect calls.** IRQL changes performed by an indirect call (function pointer or dispatch-table call) between save and restore are not detected, because the predicate only inspects the static call target.\n* **Loops where the restore is textually before the save.** The filter compares source line numbers; in a loop body whose first statement is the restore and last statement is the save (with the IRQL change after the save), the line range becomes empty and no intermediate IRQL change is seen.\n* **Wrapper chains longer than one level.** Only one level of wrapping is currently modelled (the helper is called directly from the common caller). Multi-level wrappers require the same annotation hint described above, or a direct call site.\n", |
| 87 | + "markdown": "# Irql Float State Mismatch\nThe IRQL where the floating-point state was saved does not match the current IRQL (for this restore operation).\n\n\n## Recommendation\nThe IRQL at which the driver is executing when it restores a floating-point state is different than the IRQL at which it was executing when it saved the floating-point state. Because the IRQL at which the driver runs determines how the floating-point state is saved, the driver must be executing at the same IRQL when it calls the functions to save and to restore the floating-point state.\n\n\n## Example\nExample of incorrect code. Floating point state was saved at APC_LEVEL but restored at PASSIVE_LEVEL\n\n```c\n \n\t\t_IRQL_requires_(PASSIVE_LEVEL) \n\t\tvoid driver_utility_bad(void)\n\t\t{\n\t\t\tKIRQL oldIRQL;\n\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\t\t\t// running at APC level\n\t\t\tKFLOATING_SAVE FloatBuf;\n\t\t\tif (KeSaveFloatingPointState(&FloatBuf))\n\t\t\t{\n\t\t\t\tKeLowerIrql(oldIRQL); // lower back to PASSIVE_LEVEL\n\t\t\t\t// ...\n\t\t\t\tKeRestoreFloatingPointState(&FloatBuf);\n\t\t\t}\n\t\t}\n\t\t\n```\nCorrect example\n\n```c\n \n\t\t\t_IRQL_requires_(PASSIVE_LEVEL) \n\t\t\tvoid driver_utility_good(void)\n\t\t\t{\n\t\t\t\t// running at APC level\n\t\t\t\tKFLOATING_SAVE FloatBuf;\n\t\t\t\tKIRQL oldIRQL;\n\t\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\n\t\t\t\tif (KeSaveFloatingPointState(&FloatBuf))\n\t\t\t\t{\n\t\t\t\t\tKeLowerIrql(oldIRQL);\n\t\t\t\t\t// ...\n\t\t\t\t\tKeRaiseIrql(APC_LEVEL, &oldIRQL);\n\t\t\t\t\tKeRestoreFloatingPointState(&FloatBuf);\n\t\t\t\t}\n\t\t\t}\n\t\t\n```\n\n## References\n* [ C28111 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28111-floating-point-irql-mismatch)\n\n## Semmle-specific notes\n**Wrapper / common-caller pattern.** The query reasons about IRQL-changing calls between save and restore not only when both calls share an enclosing function, but also when they sit inside one-level helper wrappers that are called from a common caller (for example, thin `save_fp_helper` / `restore_fp_helper` functions that simply forward to `KeSaveFloatingPointState` / `KeRestoreFloatingPointState`). In those cases the intermediate IRQL transition is searched in the common caller (or in either helper's enclosing function for the asymmetric case where one side is a helper and the other is direct).\n\n**Remaining limitations.** The position-based filter still does not detect:\n\n* **IRQL changes performed deep inside helper bodies.** If the helper function itself raises or lowers the IRQL after the save (or before the restore), the change is not visible from the common caller's source-position view, and no intermediate IRQL change is found. Annotating the helper with `_IRQL_raises_` or `_IRQL_saves_global_` makes its IRQL behavior visible without body inspection.\n* **Indirect calls.** IRQL changes performed by an indirect call (function pointer or dispatch-table call) between save and restore are not detected, because the predicate only inspects the static call target.\n* **Loops where the restore is textually before the save.** The filter compares source line numbers; in a loop body whose first statement is the restore and last statement is the save (with the IRQL change after the save), the line range becomes empty and no intermediate IRQL change is seen.\n* **Wrapper chains longer than one level.** Only one level of wrapping is currently modelled (the helper is called directly from the common caller). Multi-level wrappers require the same annotation hint described above, or a direct call site.\n" |
88 | 88 | }, |
89 | 89 | "properties": { |
90 | 90 | "tags": [ |
|
112 | 112 | "extensions": [ |
113 | 113 | { |
114 | 114 | "name": "microsoft/windows-drivers", |
115 | | - "semanticVersion": "1.9.0+2515238ad8912d03a18aab75fcacace2a4f4d307", |
| 115 | + "semanticVersion": "1.9.0+a76f8551b47f01adada99ddc44a5ea4fa9839fca", |
116 | 116 | "locations": [ |
117 | 117 | { |
118 | 118 | "uri": "file:///F:/source/repos/Windows-Driver-Developer-Supplemental-Tools/src/", |
|
254 | 254 | "text": "" |
255 | 255 | }, |
256 | 256 | "level": "none", |
257 | | - "timeUtc": "2026-04-28T23:26:00.575823400Z", |
| 257 | + "timeUtc": "2026-04-29T04:38:29.808991Z", |
258 | 258 | "descriptor": { |
259 | 259 | "id": "cli/file-coverage-baseline", |
260 | 260 | "index": 1 |
261 | 261 | }, |
262 | 262 | "properties": { |
263 | 263 | "attributes": { |
264 | | - "durationMilliseconds": 288 |
| 264 | + "durationMilliseconds": 253 |
265 | 265 | }, |
266 | 266 | "visibility": { |
267 | 267 | "statusPage": false, |
|
274 | 274 | "text": "" |
275 | 275 | }, |
276 | 276 | "level": "none", |
277 | | - "timeUtc": "2026-04-28T23:26:00.581682100Z", |
| 277 | + "timeUtc": "2026-04-29T04:38:29.815492900Z", |
278 | 278 | "descriptor": { |
279 | 279 | "id": "cli/platform", |
280 | 280 | "index": 2 |
|
297 | 297 | "markdown": "Internal telemetry for the C++ extractor.\n\nNo action needed." |
298 | 298 | }, |
299 | 299 | "level": "note", |
300 | | - "timeUtc": "2026-04-28T23:26:39.590845200Z", |
| 300 | + "timeUtc": "2026-04-29T04:39:07.709847200Z", |
301 | 301 | "descriptor": { |
302 | 302 | "id": "cpp/extractor/summary", |
303 | 303 | "index": 3 |
|
369 | 369 | "index": 0 |
370 | 370 | }, |
371 | 371 | "region": { |
372 | | - "startLine": 112, |
| 372 | + "startLine": 111, |
373 | 373 | "startColumn": 33, |
374 | 374 | "endColumn": 36 |
375 | 375 | } |
|
0 commit comments