ISTQB CTAL-TTA study materials
ISTQB CTAL-TTA study resources

Triage of static analysis findings and misplaced dynamic analysis

ISTQB CTAL-TTA · Put your knowledge to work in context.

All case studies

Triage of static analysis findings and misplaced dynamic analysis

Sentinel Drive's motor-control firmware is 250 kLOC of C. The team enabled a MISRA C:2012 checker in CI; the first run reported 1,412 violations, which the team believes are mostly advisory. To get a green build, a developer added a suppression file covering the entire brake module and disabled the "uninitialized variable" and "pointer arithmetic" rule groups, arguing they were noisy.

Separately, one developer runs Valgrind manually on his laptop against the desktop simulator build, occasionally. Three weeks after release, a field unit reported erratic torque after roughly 400 hours of uptime; the root cause was an uninitialized pointer used only when a CAN message arrives in a rare order. The only dynamic analysis during system test is a 2-hour functional run on the simulator, which passed. The safety manager asks what must change before the next release in six weeks.

1. How should the team triage the 1,412 findings so the static analysis becomes actionable rather than a number to suppress?

Read the worked answer

The raw count is meaningless; the findings must be turned into a ranked, owned work list. A workable triage:

  1. Classify by rule category and severity, not by file. Distinguish mandatory/required rules from advisory ones, and separate genuine defect indicators (uninitialized data, unchecked returns, out-of-bounds indexes) from style and documentation rules. The team's "mostly advisory" belief must be tested against the actual breakdown.
  2. Deduplicate by root cause. One missing check in a helper function may produce dozens of findings; fixing the helper removes them all.
  3. Prioritise by context: code on the safety path, code changed in the current release, and code with high cyclomatic complexity or a defect history. The brake module's blanket suppression is unacceptable in a safety context; suppressions and deviations must be recorded individually with a justification and an owner.
  4. Establish a baseline and ratchet: fix the high-severity findings now, then fail the build only on new violations so the backlog can be reduced incrementally instead of blocking every commit.
  5. Track violation density and trend over time, plus the proportion of findings triaged as false positives, to tune the rule configuration without disabling whole rule groups.

Disabling "uninitialized variable" and "pointer arithmetic" outright is the specific decision that must be reversed: those are exactly the defect classes this codebase has already shipped.

2. Explain why the existing dynamic analysis did not catch this defect, and where in the lifecycle it should be applied.

Read the worked answer

Dynamic analysis only observes code that is actually executed, on the build that is actually run. The current setup fails on several counts:

  • Different build and environment: Valgrind on a desktop simulator does not exercise the same compiler optimisations, memory layout, timing or hardware interfaces as the target. The simulator may also stub the CAN driver entirely.
  • Rare execution path: the defect requires an unusual CAN message ordering, which the developer's ad-hoc run and the 2-hour functional run are very unlikely to produce. Running longer or with randomised message ordering matters more than running the same short scenario again.
  • Intermittent and manual: a single developer running the tool occasionally is not a repeatable control; results are not recorded, triaged or gated.

Where it belongs:

  • Unit and component level: run instrumented builds (sanitizers, memory checkers) continuously in CI against the unit test suite, where paths are exercised deterministically and failures are cheap.
  • System and integration level: instrumented target builds during long-duration and stress runs, with realistic and adversarial message sequences.
  • Pair it with static analysis. Dynamic analysis cannot find a defect on a path that is never executed, which is exactly the argument for the data-flow checking in the static tool.
  • Add coverage measurement to the dynamic runs so the team knows which paths were actually checked, not just that the run was green.

3. Identify the static analysis technique that targets this defect class and state what else should be introduced to prevent recurrence.

Read the worked answer

The defect is a use of an uninitialized pointer, i.e. a variable is read on a path where no definition has occurred. That is a data flow anomaly, found by data flow analysis, which builds definition-use information per path and reports cases such as used-before-defined, defined-but-never-used, and definitions killed before use. Control flow analysis complements it by exposing unreachable code and paths that no test can reach, and both are exactly what the disabled rule group was reporting.

Beyond re-enabling those rules:

  • Configure the tool to flag use-before-definition across function boundaries where the analyser supports it, and across interrupt handlers and callbacks, which is where a rare message ordering changes the path.
  • Review the CAN handler code specifically, including message-ordering assumptions, and add a code review checklist item on initialisation of pointers and state shared between the main loop and interrupts.
  • Add targeted tests that deliver CAN messages in unusual orders and with malformed payloads, so the path is exercised dynamically as well.
  • Require documented deviation records for any suppressed rule on safety-related code, reviewed by the safety manager rather than by the author alone.
  • Add a CI gate that fails on new high-severity findings in changed files, so the fix is enforced rather than remembered.