Parasoft vs SonarQube ESL — Engineering Software Lab

Static analysis on C code with
50 known defects

Parasoft C/C++test Standard CLI and SonarQube CLI, run against the same ThreadX Win32 source states.

What was measured

50 valid planted C defects in six families, mapped line by line to the findings each tool produced. Every verdict in this deck comes from the committed reports, not from a summary.

Source states

harness-clean  844260e1
bugged  9d699595
52 markers · 50 valid on Win32

Headline

Latest Parasoft result: 21 of 50 valid defects with all Flow rules enabled at explicit Thorough depth. MISRA C:2025 added no further strict detections. SonarQube code analysis remains unavailable pending its license.

github.com/zuwasi/parasoft-vs-sonarqube-threadx  ·  evaluator: Daniel Liezrowice, ESL (Engineering Software Lab)  ·  run date 2026-10-08
01 · Scope

One source tree, one build, two analyzers

target: threads & size arithmetic
candidates: 52 markers, 50 valid

The question. Given C code with known, deliberately hard defects, do two mainstream tools report the same ones? Each finding was mapped back to the catalog entry it describes, so a verdict is never given for a finding that merely lands near a marker.

Held constant. Same machine, same MSVC v145 Win32 build data, same immutable git tags, same defect catalog. Only the analyzer differed.

Scored. 50 valid candidates after a post-scan audit removed two markers that are not defects on this target.

Adjudication rules used for every candidate
True positiveFinding sits at, or on a path directly implicated by, a catalog site, and its message describes that defect's root cause.
Partial / indirectRelated but not the cataloged defect (a lost resource instead of a double free, or a hint rather than the dereference). Recorded separately, still counted as a miss for strict recall.
Strict missValid catalog defect with no root-cause finding. Direct misses plus partial/indirect findings.
Not scoredFindings in pristine upstream ThreadX are real-code findings of that project, not false positives of this evaluation. Compiler warnings are excluded.
01

Plant defects

52 marked candidates added between two signed tags.

02

Build both states

azure_rtos.sln, Release|Win32, MSVC v145 build data.

03

Scan

Parasoft: paired clean/bugged follow-ups, all Flow rules and Flow + MISRA. SonarQube: earlier DEEP requests were rejected.

04

Adjudicate

Every finding mapped to a catalog entry by line and message.

05

Audit the benchmark

Two candidates were invalidated; one real issue found in the "clean" baseline.

Read the SonarQube column carefully. The earlier requests were rejected with HTTP 403 before any code file was analyzed. The code comparison is still pending an active license; a rejected scan is not a zero-finding result.
evaluation/COMPARISON_REPORT.md · evaluation/reports/adjudication/DETECTION_MATRIX.csv02 / 30
02 · Tool 1

Parasoft C/C++test Standard — the analyzer that ran

Parasoft
ItemValue recorded in the scan protocol
ProductC/C++test Standard 2026.1.3 · build 10.7.4.20260825B5553
InterfaceCommand line — cpptestcli.exe (Standard CLI, no IDE)
LicenseNetwork license server on the same host; edition server_compliance_edition
HostWindows 11 (10.0.26200) x64, machine id WIN32-2037c5fc
CompilerVisual Studio Professional 2026 (VC toolset v145), passed to the tool as -compiler vc_14_5
InputBuild data collected from azure_rtos.sln@Release|Win32
OutputNative HTML/XML reports per run, normalized findings CSVs, source-linked adjudication matrix and hashes
IsolationSeparate worktree per tag, separate tool workspace per run — no state carries between runs
Why this tool is the interesting one here

It performs interprocedural flow analysis and models ThreadX API semantics — byte-pool and block-pool lifecycle, mutex ownership rules, kernel-object create/delete. Several planted defects were designed to be reachable only if the analyzer knows what those APIs mean, which is what makes the results on the concurrency and pool families worth reading.

Test configuration used

Original scan: builtin://Flow Analysis Aggressive, 15/50; the preset did not explicitly set Thorough depth. Latest: all 144 Flow checkers, explicit Thorough depth (4), 240-second hotspot limit and the same TX API model.

A separate profile added all 388 shipped MISRA C:2025 checkers. It produced more compliance diagnostics but no additional strict planted-defect TP.

All four latest runs exited 0 and checked 214 files; 183–210 Flow-analysis timeouts remain. Native reports and UTC metadata are retained with raw-report hashes.
evaluation/SCAN_PROTOCOL.md §1, §3, §5 · threadx-allflow-misra-240/run-summary.csv03 / 30
03 · Tool 2

SonarQube CLI — what it can and cannot execute here

SonarQube
ItemValue recorded in the scan protocol
ProductSonarQube CLI 1.9.0 · build 1.9.0.15656, installed from the official SonarSource install script
InterfaceCommand line — sonar.exe, including sonar analyze with --depth DEEP
AuthenticationSigned in to SonarQube Cloud (EU region), organization zuwasi; token held in the OS keychain, status reported healthy
Projectzuwasi_parasoft-vs-sonarqube-threadx, imported from the public repository with the owner's approval
Engines invokedSecrets scanner (sonar-secrets 2.49.0.12346) — runs locally; and Vortex DEEP code analysis — runs on Sonar's service
Commands triedWhole-scope: --file ×8 --depth DEEP · change-set: --base harness-clean --depth DEEP · analyze secrets
Code resultNone — Vortex returned 403 Forbidden on every project-backed attempt; all requested files listed as skipped
Secrets result0 secrets found in each state, on the eight evaluated C files
The one sentence that matters.
Vortex analysis is not available on this connection (403 Forbidden)
And, from sonar system status: authentication healthy, VORTEX Status: Not entitled.
The two engines are not the same thing

The local secrets scanner found no credentials — that is a real, completed analysis, and it says nothing about C defects. The engine that would have analyzed the 50 planted defects is the service-backed deep code engine, and it never ran.

Why the difference matters for this deck

A zero-secrets result is often quoted as "SonarQube found nothing". It is not a code-analysis result and is never used as a score anywhere in this deck.

evaluation/SCAN_PROTOCOL.md §4, §6 · evaluation/reports/sonarqube/run-log.txt04 / 30
04 · The code

ThreadX Win32 sample application plus an evaluation harness

6 files changed by the plants
+219 / −122 lines
Harness source files — the defect sites live here
FileLinesRole in the pipeline
harness_common.h247Types, frame/header layout, limits, error codes
harness_init.c463Creates threads, queues, pools, mutexes, event group
harness_sizearith.c306Allocation sizing, length arithmetic, ring index, header store
harness_memory.c316Frame lifetime, pools, batch send, cache, retry
harness_concurrency.c209Shared stats, slot hand-off, lock order, job list, queue drain
harness_nullpaths.c238Lookup and validation paths, out-parameters, callbacks
harness_taint.c185Queue-sourced indices, lengths, names, format strings
harness_uninit.c176Pooled memory, stack headers, CRC scratch, snapshots

The scans also cover pristine upstream ThreadX kernel code in the same solution. Its findings are reported separately and never counted as benchmark false positives.

ThreadX objects created by the harness

4 threads  ·  3 queues  ·  1 byte pool
1 block pool  ·  4 mutexes  ·  1 event group
producer · consumer · logger · maintenance

Where the defect inputs come from

Trigger data arrives from queue receives (tx_queue_receive into caller memory) and from volatile simulated sensor registers. At runtime the producer only writes documented in-range values, so the application keeps running; statically, a cross-thread queue payload is an unknown value and a volatile read is a fresh unknown.

Runtime-benign by design. A 20-second soak ran with all 52 plants present and the process stayed alive. That establishes only that — it is not proof that every defect is harmless, and the deck never treats it as such.
evaluation/PLANTED_BUGS.md §1 · harness @ tag bugged 9d69959505 / 30
05 · The defect set

The detection target is a git diff, not a wish list

52 markers planted
50 valid on this target
Git stateTagCommitRole
Pristine upstream ThreadXbaseline-clean93387b0aReference for upstream findings
Win32 example build adapted to VS2026 / v145—bb0c450cBuildable state
Harness added (intended clean baseline)harness-clean844260e1Clean state scanned
+ 52 planted candidatesbugged9d699595Detection target

Both tools scanned the same two materialized states via git worktree checkouts of these immutable tags. For the bugged state the Sonar change-set base was harness-clean, so the change set is the 52 defect sites.

Every candidate is machine-mappable

Each plant carries an in-source banner at the defect line:

/* [PLANTED DEFECT BUG-003 | CWE-193 | off-by-one:
idx == LOG_DEPTH passes the bound check and
writes one past the ring] */

A finding can therefore be tied to its catalog entry by line and message instead of by judgement.

Two markers are not defects on Win32. BUG-005 and BUG-031 survived review as invalid (the arithmetic cannot wrap; the range guards are identical). Scoring uses the 50 valid candidates — the pair is still shown, with its evidence, on slide 24.
BUG-001…012

Size arithmetic

12 candidates — the emphasized family for this evaluation.

BUG-013…022

Memory lifecycle

10 — use after release, double release, leaks, interior free.

BUG-023…030

Concurrency

8 — races, lock inversion, TOCTOU, ownership.

BUG-031…038

NULL paths

7 valid — unchecked lookup, malloc, out-params, callbacks.

BUG-039…046

Taint / bounds

8 — queue-sourced indices, lengths, format strings.

BUG-047…052

Uninitialized

6 — pooled memory, stack headers, CRC, snapshots.

evaluation/PLANTED_BUGS.md §1, §2, §1006 / 30
06 · Method

How the defects were built to be hard, and fair

design intent, stated in advance
not tuned after the scan
1 · Flow-analysis grade

Candidates need interprocedural, path-sensitive or dataflow reasoning — a guard that is not exhaustive, a contract the caller ignores, ownership that crosses a function boundary. Rule-matching alone does not reach most of them.

2 · Runtime-benign, statically reachable

Defect branches depend on error paths that never fire under the harness's runtime conditions (queue full, allocation failure, abort request), so the demo keeps running while every defect stays reachable in the analysis.

3 · No constant-propagation give-aways

Bounds checks that exist use live values, and defect inputs come from volatile registers or cross-thread queue payloads that cannot be folded to a constant.

4 · ThreadX realism

Defects sit inside a real sensor-telemetry pipeline built from the same primitives real firmware uses. Candidates marked [TX] additionally require modeling ThreadX semantics — pool lifecycle, mutex ownership, kernel-object create/delete. These probe depth, not pattern coverage.

5 · Size arithmetic emphasized

12 candidates: truncation, wrap, signed/unsigned conversion, sizeof(pointer) misuse, masked-length checks, off-by-one. This is the family the report reads first, and the one the deck shows most code for.

Runtime inputs, documented per defect

The catalog states what the producer actually writes for each trigger (for example g_sensor_count = tx_time_get() & 0xF, so 0–15). That is how "hard statically, benign at runtime" is verified rather than asserted.

Why this matters when reading the results. A defect that a tool misses here is one that needs flow reasoning, not one that is unreachable or hidden behind a constant. The rule set used to attack the set is on slide 20.
evaluation/PLANTED_BUGS.md §1 (design principles)07 / 30
07 · The defects

Size arithmetic — all 12 candidates, file and line

emphasized family
11 valid · BUG-005 invalid
IDCWESiteFunctionPlanted defect
BUG-001190 → 787harness_sizearith.c:26sa_alloc_copycount*4 truncated to UINT16 for the allocation, full length for the copy
BUG-002197harness_sizearith.c:46sa_copy_checkedMagnitude check admits negative lengths, which convert to huge size_t
BUG-003193harness_sizearith.c:63sa_log_writeidx <= LOG_DEPTH off-by-one writes one entry past the ring
BUG-004131harness_sizearith.c:111sa_frame_newmemcpy of sizeof(pointer) leaves the frame partially initialized
BUG-005190harness_sizearith.c:133sa_packInvalid — UINT16 payload plus 16 bytes cannot wrap a 32-bit ULONG
BUG-006197harness_sizearith.c:154sa_store_lenStored length truncated for the allocation, full msg_len used for the copy
BUG-007787harness_sizearith.c:176sa_table_putRow checked, column not: negative columns walk below the table
BUG-008131harness_sizearith.c:196sa_cfg_snapshotsizeof(cfg) of the pointer copied instead of the struct
BUG-009190 → 690harness_sizearith.c:231sa_pool_resizeWrapped pool arithmetic, then an ignored tx_byte_allocate status reaching memset
BUG-010170harness_sizearith.c:252sa_scan_rawFull-length fill leaves no terminator; the terminator write and strlen both run past the buffer
BUG-011704harness_sizearith.c:276sa_masked_copyLength checked after a 16-bit mask, copy uses the full 32-bit length
BUG-012190/787harness_sizearith.c:295sa_hdr_storeConfigured pad size never validated against sizeof(FRAME_HDR)

Runtime values keep every one of these benign: the producer writes 0–255 to the length registers and 0–15 to the count register, so no truncation or wrap actually occurs while the pipeline runs. The defects are reachable only for values the analyzer must treat as unknown.

evaluation/PLANTED_BUGS.md §3 · evaluation/reports/adjudication/DETECTION_MATRIX.csv08 / 30
08 · The defects

The other five families — 38 valid candidates

BUG-013…052
4 files, 5 families
FamilyValidRepresentative candidates and what makes them hard
Memory lifecycle10BUG-013 write after tx_byte_release · 016 block released to the byte pool · 017 callee releases and returns success · 021 two cache slots alias one frame, so the flush double-frees
Concurrency8BUG-023 unlocked stats update · 025 lock-order inversion versus net_update_a · 030 queue count checked, then received with the status ignored
NULL / validation7BUG-033 unchecked malloc · 034 out-parameter used after an ignored error · 037 the guard protects the loop but not the returned value · 038 NULL propagated four calls deep
Taint / bounds8BUG-040 length validated against queue capacity · 042 bound checked against a stale table size · 044 received text used as a format string · 046 nibble indexes a 12-entry handler table
Uninitialized6BUG-047 pooled memory read before initialization · 049 a widely called helper stops setting two fields · 051 fill loop stops one short of the compared entry
Why the concurrency family is the sharpest test

All four threads are created with tx_thread_create inside harness_init.c. A tool that does not model ThreadX thread creation cannot see that the functions run concurrently at all, and the eight races become invisible rather than merely hard.

The [TX] candidates

Eight candidates additionally require ThreadX API semantics: byte-pool memory is not zeroed, a block-pool block must be released with tx_block_release, a mutex put requires ownership, a created TX_TIMER must be deleted. They probe RTOS knowledge rather than pattern coverage.

Compiler-visible controls

Two plants (BUG-008, BUG-048) are things MSVC itself warns about — C4700 class defects. They are useful as a floor: any flow analyzer that misses the compiler-visible cases would be reported as such.

evaluation/PLANTED_BUGS.md §4–§8 · 8 candidates marked [TX]09 / 30
09 · Code, defect, verdict

BUG-001 · the allocation and the copy disagree

harness_sizearith.c:26
Parasoft: miss
21UINT sa_alloc_copy(UINT count)
22{
23 UINT16 size;
24 UCHAR *p;
25
26 /* [PLANTED DEFECT BUG-001 | CWE-190/787 | count*4 truncated to
27 UINT16 for the allocation but not for the copy] */
28 size = (UINT16)(count * 4u);
29 p = (UCHAR *)malloc((size_t)size);
30 if (p == TX_NULL)
31 return HR_FAIL;
32
33 memcpy(p, sa_src, (size_t)count * 4u);
34 free(p);
35 return HR_OK;

Trigger: producer_entry → harness_tick → sa_alloc_copy(count = g_sensor_count), a volatile simulated register.

What is wrong

Both expressions come from the same value through different routes. For any count above 16383 the truncated 16-bit size is smaller than the copy, so the heap buffer is overrun. Detection needs integer-range reasoning that a 32-bit input can exceed that bound, then correlation of the two expressions.

Parasoft verdict — strict miss

No finding on either line, and no finding anywhere in this function. The scan reported two unrelated diagnostics in this file — one on the unused copy in sa_copy_checked and one on the ring index at line 68.

SonarQube on this defect

No code scan The file was among the eight requested; the request was rejected with 403 before analysis. Not a miss — an absence of any result.

PLANTED_BUGS.md §3 · DETECTION_MATRIX.csv: BUG-001 = FN10 / 30
10 · Code, defect, verdict

BUG-003 · off-by-one, and the finding that proves it

harness_sizearith.c:63
Parasoft: reported
59void sa_log_write(UINT16 code)
60{
61 UINT idx;
62
63 /* [PLANTED DEFECT BUG-003 | CWE-193 | off-by-one: == LOG_DEPTH
64 passes the bound check and writes one past the ring] */
65 idx = (UINT)code >> 3;
66 if (idx <= (UINT)LOG_DEPTH)
67 {
68 log_ring[idx].code = code;
69 log_ring[idx].seq = (UINT16)(code ^ 0x5Au);
70 log_ring[idx].stamp = tx_time_get();
71 }
72}

The subtlety: LOG_DEPTH is 32 and the ring holds 32 entries, so the correct guard is <. With <=, index 32 passes and writes past the end of the array.

Parasoft finding — flow analysis
68BD-PB-ARRAY
Possibly accessing array
"log_ring" out of bounds at
index [0...32]. Correct
index(es): [0...31]

The message names the exact bound the plant violates, which is why this counts as a root-cause true positive rather than a nearby hint.

Why this one is reachable at all

The index is derived (code >> 3) from a volatile value, so the analyzer must reason about the derived range against a macro bound instead of folding a constant.

SonarQube on this defect

No code scan 403, file skipped.

DETECTION_MATRIX.csv: BUG-003 = TP in the flow-analysis scan11 / 30
11 · Code, defect, verdict

BUG-006 · what the plant removed, on the same function

harness_sizearith.c:154
Parasoft: miss
Bugged state — tag bugged
149UINT sa_store_len(ULONG msg_len)
150{
151 UINT16 stored;
152 UCHAR *p;
153
154 /* [PLANTED DEFECT BUG-006 | CWE-197 | stored length
155 truncated for the allocation, full msg_len used
156 for the copy] */
156 stored = (UINT16)msg_len;
157 p = (UCHAR *)malloc((size_t)stored);
158 if (p == TX_NULL)
159 return HR_FAIL;
160
161 memcpy(p, sa_src, (size_t)msg_len);
162 free(p);
163 return HR_OK;
164}
Clean state — tag harness-clean, same function
152 /* The UINT16 stored length must represent
153 msg_len exactly. */
153 if (msg_len > 0xFFFFu)
154 return HR_FAIL;
155
156 stored = (UINT16)msg_len;
157 p = (UCHAR *)malloc((size_t)stored + 1u);
158 if (p == TX_NULL)
159 return HR_FAIL;
160
161 memcpy(p, sa_src, (size_t)msg_len);
The finding that moved

On the clean state Parasoft reported BD-PB-OVERFRD at line 161 — reading up to 65535 bytes from the 128-byte sa_src. In the bugged state the guard and the + 1u are gone and the copy is worse, but the function produced no finding at all. The plant turned a reported condition into a strict miss.

Strict miss  BUG-006 scored as a false negative. An allocation sized from a truncated value while the copy uses the full value is exactly the class of defect this evaluation exists to measure, and the scan did not report it.
DETECTION_MATRIX.csv: BUG-006 = FN · clean-state finding: reports/parasoft/clean-…-Aggressive-findings.csv:16112 / 30
12 · Code, defect, verdict

BUG-011 · a check that hides the value it should bound

harness_sizearith.c:276
Parasoft: miss
272UINT sa_masked_copy(ULONG msg_len)
273{
274 UCHAR dst[64];
275
276 /* [PLANTED DEFECT BUG-011 | CWE-704 | length checked after
277 masking to 16 bits, but the copy uses the full
278 32-bit length] */
278 if ((msg_len & 0xFFFFu) < 64u)
279 memcpy(dst, sa_src, (size_t)msg_len);
280 return HR_OK;
281}

Concrete counterexample: msg_len = 0x1003F (65599). The masked value is 63, so the check passes; the copy then moves 65599 bytes into a 64-byte stack buffer.

Parasoft verdict — strict miss

The scan reports BD-PB-MEMOPT at line 279 — "call to memcpy may be optimized out as the dst buffer is not used later". That diagnostic is about the unused copy, not about the length mismatch, so it is not credited as a detection of this defect.

Why the distinction is kept

A finding that lands on the defect line but describes a different problem is exactly how "detected" counts get inflated. Here it is disclosed and scored as a miss.

SonarQube on this defect

No code scan 403, file skipped.

DETECTION_MATRIX.csv: BUG-011 = FN; adjudication note "unused-copy report does not identify the masked-length mismatch"13 / 30
13 · Code, defect, verdict

BUG-018 · the loop that keeps using the freed block

harness_memory.c:175
Parasoft: reported
163UINT batch_send(FRAME *batch, UINT count)
164{
165 UINT i;
166
167 if (batch == TX_NULL)
168 return HR_FAIL;
169
170 for (i = 0; i < count; i++)
171 {
172 if (frame_send(&batch[i]) != HR_OK)
173 {
174 free(batch); /* whole contiguous block */
175 /* [PLANTED DEFECT BUG-018 | CWE-416 | the loop keeps
176 sending from the freed batch] */
177 }
178 }
179
180 free(batch);
181 return HR_OK;
182}
Parasoft findings — flow analysis
172BD-RES-FREE Usage of freed
resource "batch"
180BD-RES-FREE Usage of freed
resource "batch"

Two findings, at the failing send and at the unconditional free — the loop-carried use-after-free and the second free it can cause.

Why this counts as a clean detection

The analyzer tracked the block across free() and reported both later uses — the failing send inside the loop and the unconditional free below it. Nothing in the message needs interpretation: it names the object that was released.

SonarQube on this defect

No code scan 403, file skipped.

DETECTION_MATRIX.csv: BUG-018 = TP14 / 30
14 · Code, defect, verdict

BUG-023 · the locked function is right above it

harness_concurrency.c:39
Latest Flow profile: TP
24void stats_record(ULONG v) /* correct sibling */
25{
26 tx_mutex_get(&stats_mutex, TX_WAIT_FOREVER);
27 g_stats.total = g_stats.total + v;
28 tx_mutex_put(&stats_mutex);
29}
30
35void stats_record_fast(ULONG v)
36{
37 /* [PLANTED DEFECT BUG-023 | CWE-362 | read-modify-write of
38 shared stats without holding stats_mutex] */
39 g_stats.total = g_stats.total + v;
40}

Callers: the producer thread calls stats_record_fast while the consumer thread updates the same field through the locked stats_record. The two functions are adjacent, in one file, on one shared field.

New finding — BD-TRS-MLOCK

“The g_stats variable is used when locks are not held on stats_mutex.” At line 39 the read-modify-write omits the mutex used by its sibling function. This is the newly counted BUG-023 TP.

The clean state also reports an unlocked g_stats callback at harness_init.c:65; that is a separate, unplanted baseline concern and is disclosed in the clean review.

Why it is a fair test

This latest profile enabled every installed Flow checker, including BD-TRS-MLOCK, and used the TX API model. The earlier shipped Aggressive preset missed this site; the full-rule follow-up reports it at the planted update.

SonarQube on this defect

No code scan 403, file skipped.

DETECTION_MATRIX.csv: BUG-023 = TP · BD-TRS-MLOCK at harness_concurrency.c:3915 / 30
15 · Code, defect, verdict

BUG-040 and BUG-042 · two bounds errors, both reported

harness_taint.c:71 and :101
Parasoft: both reported
BUG-040 — length checked against the wrong constant
66void msg_data_copy(CMD_MSG *m)
67{
68 UCHAR dst[64];
69 UINT16 len;
70
71 /* [PLANTED DEFECT BUG-040 | CWE-787 | copy length
72 validated against the queue capacity, not the
73 destination buffer] */
73 len = (UINT16)((ULONG)m->param + 4u);
74 if (len <= 128u) /* dst is 64 bytes */
75 memcpy(dst, m, (size_t)len);
76}
75BD-PB-OVERFWR Overflow when writing to buffer
"dst" (UCHAR[64], 64 bytes large). Number of bytes
written 4 <= len <= 128

The message carries the whole argument: the bound in the code is 128, the buffer is 64.

BUG-042 — a check against a stale table size
95void slot_store(CMD_MSG *m)
96{
97 UINT idx;
98
99 idx = (UINT)m->sensor_id;
100
101 /* [PLANTED DEFECT BUG-042 | CWE-129 | check uses the
102 old table size (8); the slot table has only 4
103 entries] */
103 if (idx < 8u)
104 slot_values[idx] = (ULONG)m->param;
105}
104BD-PB-ARRAY Possibly accessing array
"slot_values" out of bounds at index [0...7].
Correct index(es): [0...3]

A bound check is present and looks reassuring; the tool compared it with the array's real size.

Both are true positives. This family produced three detections out of eight, all of them array or buffer bounds — the taint path into the value was not the deciding factor.
DETECTION_MATRIX.csv: BUG-040 = TP, BUG-042 = TP16 / 30
16 · Code, defect, verdict

BUG-049 and BUG-050 · initialization across call boundaries

harness_uninit.c:17 and :127
Parasoft: both reported
BUG-049 — the helper stops setting two fields
15void init_hdr(FRAME_HDR *h)
16{
17 /* [PLANTED DEFECT BUG-049 | CWE-457 | flags and
18 reserved are never initialized by this helper;
19 callers read them] */
20 h->magic = FRAME_HDR_MAGIC;
21 h->type = 0;
22 h->seq = 0;
23 h->payload_len = 0;
24}
/* five callers build on this helper: frame_build,
hdr_send, frame_chain_check, batch_send,
sa_hdr_store. hdr_send reads h.flags. */
88BD-PB-NOTINIT Non-initialized "h.flags" is used

The finding lands at the read site, in a different function from the plant — whole-program initialization tracking.

BUG-050 — an error contract the caller ignores
123UINT slot_track(void)
124{
125 SLOT *u;
126
127 /* [PLANTED DEFECT BUG-050 | CWE-457 | the error
128 contract is ignored: on failure get_slot leaves
129 u untouched] */
129 (void)get_slot(&u);
130 free(u);
131 return HR_OK;
132}
130BD-RES-INVFREE Invalid memory freeing: "u" is
not initialized in heap memory
130BD-PB-NOTINIT Non-initialized "u" is used

Two diagnostics on one line, both describing the actual defect: the pointer was never assigned because the return value was discarded.

Both are true positives. The Thorough follow-up also detected BUG-048 with BD-PB-NOTINIT, bringing this family's score to 3 of 6.
DETECTION_MATRIX.csv: BUG-049 = TP, BUG-050 = TP17 / 30
17 · Process

How Parasoft was run — the original Aggressive scan on both states

original run pair · both exited 0
follow-up profiles on slide 20
cpptestcli -config "builtin://Flow Analysis Aggressive" -compiler vc_14_5 \
-input <worktree>\ports\win32\vs_2019\example_build\azure_rtos.sln@Release|Win32 \
-report <reports>\parasoft\<state> -workspace <isolated workspace>
StateConfigurationUTC startUTC endXML findingsOf which harness
harness-cleanbuiltin://Flow Analysis Aggressive18:31:58Z18:34:05Z906
buggedbuiltin://Flow Analysis Aggressive18:34:06Z18:36:16Z11127

The clean run is the false-positive baseline and the bugged run is the detection target; both use the same configuration, compiler and build data, so the only difference between them is the planted diff.

What keeps the runs comparable

Each state was materialized as a git worktree at an immutable tag, and each run got its own workspace, so no cached analysis leaked from one run into the next. The compiler identifier was resolved once with -list-compilers on the first licensed run and reused.

Evidence retained

Two XML reports for this original pair — plus four more from the latest all-Flow and MISRA profiles — with run logs, UTC timestamps, exit codes, normalized CSV exports in the repository, and SHA-256 hashes of every raw report. The raw reports themselves stay outside the repository.

evaluation/SCAN_PROTOCOL.md §3, §5 · evaluation/reports/parasoft/run-log.txt18 / 30
18 · Process

How SonarQube CLI was run — twelve recorded invocations, one working engine

CLI 1.9.0 · org zuwasi · EU region
every invocation, exit code and log is committed
StateCommandExitOutcome
cleananalyze --file ×8 --depth DEEP (no project)0No project configured; Vortex skipped
cleananalyze secrets (whole worktree)1Timed out at the CLI's 30-second limit
cleananalyze --file ×8 --depth DEEP (no project)0No project configured; Vortex skipped
cleananalyze secrets (8 C files)00 secrets
buggedanalyze --base harness-clean --depth DEEP0No project configured; Vortex skipped
buggedanalyze --file ×8 --depth DEEP0No project configured; Vortex skipped
buggedanalyze secrets (8 C files)00 secrets
clean--project … --file ×8 --depth DEEP1Vortex 403 · 8 files skipped
bugged--project … --base harness-clean --depth DEEP1Vortex 403 · 6 files skipped
bugged--project … --file ×8 --depth DEEP1Vortex 403 · 8 files skipped
bothsonar system status0Auth healthy · VORTEX: Not entitled
Sequence that was followed

Sign in → verify status → import the public repository as a project → attempt whole-file DEEP analysis → attempt change-set analysis against harness-clean → narrow the secrets scan to the eight evaluated files after the whole-worktree scan timed out → re-check status. Nothing was skipped in the attempt order; the failures are part of the record.

What the CLI told the script, verbatim
Vortex analysis is not available
on this connection (403 Forbidden)
VORTEX Status: Not entitled
The JSON response marks each requested C file as skipped, not as clean. Skipped is the word that keeps this experiment honest.
evaluation/SCAN_PROTOCOL.md §4, §6 · evaluation/reports/sonarqube/run-log.txt19 / 30
19 · Follow-up method

Four controlled scans: all Flow rules, then MISRA

same source tags · compiler · TX model
fresh workspaces · 214 files
Held constant across the latest clean/bugged pair
Sourceharness-clean 844260e1 vs bugged 9d699595
Targetazure_rtos.sln@Release|Win32 · MSVC v145 / vc_14_5
Scope214 files · isolated CLI workspace for every scan
Flow rulesAll 144 installed checker IDs; 25 aggressive/unvalidated options plus two NOTINIT options
Depth / timeThorough (depthOfAnalysis=4) · 240-second hotspot limit
RTOS semanticsSame custom ThreadX multithreading API model in both profiles
Second profileAll 388 shipped MISRA C:2025 checkers added; other settings held constant
Latest Parasoft follow-up · total / harness findings
ProfileCleanBuggedTPTimeouts C/B
All Flow324 / 26354 / 4921187 / 183
Flow + MISRA C:20254,661 / 5584,745 / 61521210 / 206

Clean/bugged counts are total XML findings and harness entries. MISRA aliases and compliance diagnostics are not additional planted-defect TPs.

Limit: all runs exited 0, but still reported 183–210 hotspot timeouts. These are completed CLI reports, not exhaustive path analysis. Full commands and native report paths are in PARASOFT_RUN_GUIDE.md.
evaluation/THREADX_ALLFLOW_MISRA_240_REPORT.md · threadx-allflow-misra-240/run-summary.csv20 / 30
20 · Result

Latest all-Flow profile: 21 of 50 planted defects

42% strict recall · 29 strict misses
50 valid candidates
21 / 50
Strict true positives

42% strict recall · explicit Thorough depth

29
Strict false negatives

27 direct misses · one partial · one indirect

49
Bugged harness finding entries

Findings are not unique defects; each TP was adjudicated at its source site.

N/A
SonarQube code result

Pending license entitlement; prior code requests returned 403

ProfileBugged total / harnessStrict TPPartial / indirectStrict FN
Initial builtin Aggressive (depth not explicit)111 / 27151 / 135
All 144 Flow · Thorough / 240s354 / 49211 / 129
All Flow + 388 MISRA C:2025 rules4,745 / 615211 / 129
Partial and indirect signals remain separate

BUG-021 (partial): a lost-resource signal, not the planted double free. BUG-035 (indirect): BD-PB-CC flags the late null check, not the dereference. Both remain strict misses.

evaluation/COMPARISON_REPORT.md § Executive summary, § Results at a glance, § Parasoft recall by defect family21 / 30
21 · Result

Recall by defect family — where the misses cluster

TP + FN = 50
latest all-Flow Thorough/240s profile
FamilyValid True positivesPartial / indirectDirect misses What the scan saw
Size arithmetic11209Ring and raw-buffer bounds; truncation, wrap, masked length and sizeof misuse remain missed
Memory lifecycle1031 partial6Use-after-free, interior free and retry leak; no root-cause finding for six other candidates
Concurrency8503New BD-TRS-MLOCK finding for BUG-023; BUG-024, 027 and 030 remain missed
NULL / validation751 indirect1Unchecked lookup, allocation, out-param and deep NULL propagation
Taint / bounds8305Buffer overflow and table bounds; indices, format string and allocation size remain missed
Uninitialized6303Thorough follow-up adds BUG-048; pooled memory and partial-array cases remain missed
Total50211 / 127 direct29 strict FN, including partial and indirect
The honest reading of this table

The all-Flow profile adds one race detection without closing the remaining size-arithmetic, memory-contract, or queue/list concurrency gaps. The score is source-adjudicated, not a count of all emitted warnings.

The emphasized family scored 2 of 11

Size arithmetic was the stated focus of this evaluation, and it produced the largest miss block: truncation, wrap, signed-to-unsigned conversion, masked bounds and sizeof(pointer) misuse all went unreported.

Concurrency: 5 of 8

The five root-cause findings require the ThreadX API model and the full Flow checker set. Three planted races/queue defects still have no matching finding.

evaluation/COMPARISON_REPORT.md § Parasoft recall by defect family · values as published22 / 30
22 · Evidence

Parasoft rule messages behind the strict detections

initial detections plus Thorough follow-up
full exports and matrix in the repository
RuleLocationMessage as emitted by ParasoftCatalog
BD-PB-ARRAYsizearith.c:68Possibly accessing array "log_ring" out of bounds at index [0...32]. Correct index(es): [0...31]BUG-003
BD-PB-ARRAYsizearith.c:259Possibly accessing array "raw" out of bounds at index [2...64]. Correct index(es): [0...63]BUG-010
BD-RES-FREEmemory.c:172, :180Usage of freed resource "batch"BUG-018
BD-RES-INVFREEmemory.c:237Invalid memory freeing: "body" does not point to the beginning of a resource in memoryBUG-020
BD-RES-LEAKSmemory.c:299, :316Memory not deallocated: pBUG-022
BD-PB-NPnullpaths.c:96"ch" may possibly be nullBUG-032
BD-PB-CHECKRETGEN
BD-PB-NP
nullpaths.c:111, :115Value returned from method "malloc" should be checked · "s" may possibly be nullBUG-033
BD-PB-NOTINITnullpaths.c:154Non-initialized "f" is usedBUG-034
BD-PB-CCnullpaths.c:170Condition "cfg == 0" always evaluates to falseBUG-035 · indirect
BD-PB-NOTINITnullpaths.c:211Non-initialized "v" is usedBUG-037
BD-PB-NPnullpaths.c:226 (×2)"c" may possibly be nullBUG-038
BD-PB-NOTINITuninit.c:88Non-initialized "h.flags" is usedBUG-049
BD-PB-NOTINIT
BD-RES-INVFREE
uninit.c:130Non-initialized "u" is used · Invalid memory freeing: "u" is not initialized in heap memoryBUG-050
BD-PB-OVERFWRtaint.c:75Overflow when writing to buffer "dst" (UCHAR[64], 64 bytes large). Number of bytes written 4 <= len <= 128BUG-040
BD-PB-ARRAYtaint.c:104Possibly accessing array "slot_values" out of bounds at index [0...7]. Correct index(es): [0...3]BUG-042
BD-PB-ARRAYtaint.c:182Possibly accessing array "handlers" out of bounds at index [0...15]. Correct index(es): [0...11]BUG-046
BD-RES-LEAKSmemory.c:244, :260Memory not deallocated: base · Memory not deallocated: ((FRAME_STRUCT[2])frame_cache)[1]BUG-021 · partial
BD-TRS-MLOCKconcurrency.c:39The "g_stats" variable is used when locks are not held on "stats_mutex"BUG-023 · new TP
BD-TRS-ORDERconcurrency.c:75Possible deadlock - acquiring locks "net_mutex_2", "net_mutex_1" in different ordersBUG-025
BD-TRS-THRDRconcurrency.c:111The global variable "g_ready" is used without holding a lockBUG-026
BD-TRS-REVLOCKconcurrency.c:155The "net_mutex_1" lock is released, but it has not been acquiredBUG-028
BD-TRS-THRDRconcurrency.c:166The global variable "g_inited" is used without holding a lockBUG-029
BD-PB-NOTINITuninit.c:69Non-initialized "h.flags" is usedBUG-048

Light-blue rows were absent from the original Aggressive run: BUG-025…029 first appeared with the ThreadX API model at Thorough depth, BUG-048 with the added NOTINIT options, and only BUG-023 needed the full all-Flow profile. MISRA C:2025 repeats the BUG-023 site as MISRAC2025-DIR_5_1-a and is counted once, not as another detection.

evaluation/reports/threadx-allflow-misra-240/flow-bugged-findings.csv · DETECTION_MATRIX.csv23 / 30
23 · Evidence

What went unreported, and two candidates that are not defects

29 strict misses: 27 direct + 2 related signals
2 of 52 markers invalidated
Strict misses by class — 29 total
ClassCandidates
Concurrency — 3 directBUG-024 · BUG-027 · BUG-030 (BUG-023, 025, 026, 028, 029 detected)
Size arithmeticBUG-001 truncation · 002 signed/unsigned · 004 sizeof(pointer) · 006 truncated stored length · 007 unchecked column · 008 sizeof(pointer) config · 009 wrapped pool arithmetic · 011 masked length · 012 unvalidated pad
Memory lifecycleBUG-013 write after release · 014 double release · 015 early-return leak · 016 wrong pool release · 017 release-then-success · 019 timer leak · 021 partial signal
Taint / boundsBUG-039 unmasked index · 041 strcpy into 16-byte label · 043 unclamped loop · 044 format string · 045 legacy allocation without terminator
UninitializedBUG-047 pooled memory · 051 fill loop stops one short · 052 snapshot read before zeroing
NULL pathsBUG-036 unchecked callback · BUG-035 remains an indirect signal
BUG-005 is not a defect on this target

The planted size addition uses a UINT16 payload, so the maximum total is 65535 + 12 + 4 = 65,551. ULONG is 32-bit on Win32, so the addition cannot wrap, and the resulting allocation covers the payload copy. Excluded from valid-defect scoring — and Parasoft correctly reported nothing here.

BUG-031 is not a defect either

The checked accessor and the primary lookup share the same range guard and the same table slot. A non-NULL accessor result therefore proves the primary result is non-NULL. Again, no finding here is the right answer.

Why these are shown rather than deleted. Invalidating the benchmark's own candidates is part of the evidence. Scoring the tools on 52 would have charged them for two misses that do not exist.
evaluation/PLANTED_BUGS.md §10 · DETECTION_MATRIX.csv "ValidOnWin32" column24 / 30
24 · Evidence

The clean reference contains unplanted issues too

all-Flow clean: 26 harness entries
Flow + MISRA clean: 558
Genuine issue found in the clean state — harness-clean 844260e1
147UINT sa_store_len(ULONG msg_len)
148{
149 UINT16 stored;
150 UCHAR *p;
151
152 /* The UINT16 stored length must represent msg_len exactly. */
153 if (msg_len > 0xFFFFu)
154 return HR_FAIL;
155
156 stored = (UINT16)msg_len;
157 p = (UCHAR *)malloc((size_t)stored + 1u);
158 if (p == TX_NULL)
159 return HR_FAIL;
160
161 memcpy(p, sa_src, (size_t)msg_len);
162 free(p);
163 return HR_OK;
164}
161BD-PB-OVERFRD Overflow when reading from
buffer "sa_src" (UCHAR[128], 128 bytes large).
Number of bytes read 0 <= msg_len <= 65535

The allocation is sized msg_len + 1, but the 128-byte source can still be over-read for lengths above 128. This issue predates the planted diff and is not credited to any candidate.

Other clean-state findings reviewed (9 of 26)
RuleLocationReview outcome
BD-PB-MEMOPTsizearith.c:51Scratch copy with no observable output — intentional
BD-PB-CCsizearith.c:260Length already clamped below 64; redundant check
BD-PB-MEMOPTsizearith.c:277Scratch copy — intentional
BD-PB-VOVRmemory.c:61Initial value overwritten before any read
BD-PB-MEMOPTtaint.c:71Scratch copy — intentional
BD-TRS-MLOCKinit.c:65Unplanted: clean callback updates g_stats without stats_mutex
BD-TRS-THRDRinit.c:215ThreadX-managed queue receive, not an app data race
BD-TRS-THRDRsizearith.c:66–68, 84File-static ring used only by the logger thread
BD-API-STRSIZEsizearith.c:161Duplicate of the known source-buffer over-read
What this does to the comparison

The clean reference already has a real 128-byte source over-read and a separate unlocked callback. They are not planted TPs. Some concurrency warnings are contextual or assumption-dependent; MISRA also emits compliance diagnostics. The 558 MISRA clean entries are not 558 unique defects.

evaluation/reports/threadx-allflow-misra-240/CLEAN_FLOW_REVIEW.csv · original review: reports/adjudication/CLEAN_FINDING_REVIEW.csv25 / 30
25 · The SonarQube result

SonarQube code analysis is pending license entitlement

SonarQube
What the CLI reported, verbatim
Vortex analysis is not available on this
connection (403 Forbidden)
SonarQube CLI 1.9.0 system status:
- System check: healthy
- Authentication: active
- Server: https://sonarcloud.io
- Organization: zuwasi
- Vortex: Not entitled

Authentication was healthy the whole time. The CLI reached the service, the project existed, the commands were accepted — and the code-analysis engine refused every job.

Why: an entitlement, not a setting

Sonar's documentation states that Vortex is part of Sonar Agent Essentials, a separate subscription for SonarQube Cloud annual Team or Enterprise plans. The zuwasi organization has no Agent Essentials entitlement. No CLI flag, region switch or project setting can grant it, and none was attempted after this was established.

What this result is not
Not zero findingsEvery requested file is marked skipped. Nothing was analyzed, so nothing was found or missed.
Not a Sonar scoreNo TP, FP or FN value for SonarQube exists in this experiment, in either state.
Real but differentThe local secrets scanner did complete: 0 secrets in each state, on the same eight files. It does not analyze C defects.
What would change it. An entitled connection — Agent Essentials on this organization, or a supported entitled Server connection. The exact commands in this deck can then be re-run unchanged, and the comparison column becomes a measurement.
Attempt 1

Whole-scope DEEP

8 files requested → 8 skipped, exit 1

Attempt 2

Change-set DEEP

6 changed files → 6 skipped, exit 1

Attempt 3

Status check

Auth healthy · Vortex not entitled

Conclusion

No code result

Every table reports it as pending license, never zero

evaluation/reports/sonarqube/outcomes.csv, system-status.txt, run-log.txt · SCAN_PROTOCOL.md §426 / 30
26 · Comparison

Measured results, with the profiles kept separate

one harness · one target · one version of each tool
not a product ranking
Profile / toolClean total / harnessBugged total / harnessValidTPPartial / indirectStrict FNStatus
Initial builtin Aggressive · depth not explicit90 / 6111 / 2750151 / 135Historical baseline
All 144 Flow · Thorough / 240s324 / 26354 / 4950211 / 129Completed; timeouts remain
All Flow + 388 MISRA C:20254,661 / 5584,745 / 61550211 / 129No added strict TP
SonarQube CLI · DEEP code analysisN/AN/A50N/AN/AN/APending license; prior 403
What this experiment does claim

In the latest all-Flow, ThreadX-aware Thorough scan, Parasoft reported 21 of 50 valid planted root causes and missed 29. The new full-rule scan found BUG-023; MISRA C:2025 aliases that same message and added no strict TP.

What it does not claim

This is not a product ranking: one Win32 target, one C/C++test version and TX model, and one entitlement state. All profiles still had Flow timeouts. The SonarQube code result remains unavailable pending license, never zero.

How to quote it safely

Quote the profile and settings: “All installed Flow rules at Thorough/240s found 21/50; adding shipped MISRA C:2025 rules did not increase strict detections.” SonarQube is still pending an entitled code scan.

evaluation/COMPARISON_REPORT.md § Results at a glance, § Known limitations27 / 30
27 · Reproduce

Everything needed to run this again

Parasoft C/C++test — latest committed profile on each state
msbuild ports\win32\vs_2019\example_build\azure_rtos.sln \
/p:Configuration=Release /p:Platform=Win32 /m:1
cpptestcli -config "TX_All Flow Aggressive Thorough 240s.properties" \
-compiler vc_14_5 \
-input <state>\...\azure_rtos.sln@Release|Win32 \
-report <out> -workspace <isolated>

The MISRA profile swaps the second committed properties file; run-threadx-allflow-misra-240.ps1 drives all four scans and PARASOFT_RUN_GUIDE.md documents every step.

SonarQube CLI — same eight files, same states
sonar auth login # org zuwasi
sonar analyze --file <8 C files> --depth DEEP --format json
sonar analyze --base harness-clean --depth DEEP --format json
sonar analyze secrets <8 C files>
sonar system status # shows the Vortex entitlement
Do not build product code from the bugged tree. It is an evaluation fork of Eclipse ThreadX with 52 planted candidates.
Audit anchors
baseline-clean93387b0a
harness-clean844260e1
bugged9d699595
bugged XMLb1f32ffd81dfc3b0…e96f8
clean XML235fd61d0eafa584…539c3

Original-pair hashes: reports/parasoft/SHA256SUMS.txt. Latest four runs: raw-report and console SHA-256 in threadx-allflow-misra-240/run-summary.csv.

Committed evidence in the repository
PLANTED_BUGS.md52 candidates, validity audit, trigger paths
SCAN_PROTOCOL.md · PARASOFT_RUN_GUIDE.mdVersions, commands, UTC times, exit codes, export steps
…/threadx-allflow-misra-240/Latest matrix, four findings CSVs, run summary, clean review
…/adjudication/ · …/parasoft/Original Aggressive matrix and its findings exports
…/sonarqube/*CLI JSON, secrets logs, outcomes, system status
README.md · evaluation/SCAN_PROTOCOL.md · evaluation/reports/SHA256SUMS.txt28 / 30
Appendix A

Every candidate, BUG-001 … BUG-026

TP FN partial / indirect N/A
Sonar code: no entitled scan (403)
IDCWESiteAll-Flow 240sSonarAdjudication note
BUG-001190/787sa:26FNN/ANo matching flow finding
BUG-002197sa:46FNN/AOnly an unrelated unused-copy finding near this routine
BUG-003193sa:63TPN/ABD-PB-ARRAY reports ring index 32
BUG-004131sa:111FNN/ANo matching partial-initialization finding
BUG-005190sa:133InvalidN/AUINT16 plus 16 cannot wrap 32-bit ULONG
BUG-006197sa:154FNN/ANo matching allocation-versus-copy finding
BUG-007787sa:176FNN/ANo matching unchecked-index finding
BUG-008131sa:196FNN/ANo matching partial-configuration-copy finding
BUG-009190/690sa:231FNN/ANo overflow or unchecked ThreadX allocation finding
BUG-010170sa:252TPN/ABD-PB-ARRAY reports raw[64]
BUG-011704sa:276FNN/AUnused-copy report does not identify the masked-length mismatch
BUG-012190/787sa:295FNN/ANo matching undersized-header-buffer finding
BUG-013416mem:45FNN/AThreadX release not treated as invalidating the frame
BUG-014415con:203FNN/ANo finding on the caller's unconditional second release
BUG-015401mem:85FNN/ANo matching early-return leak finding
BUG-016762mem:125FNN/AWrong ThreadX pool release not reported
BUG-017415mem:148FNN/ANo finding on the release-on-success contract
BUG-018416mem:175TPN/ABD-RES-FREE — use of the freed batch
BUG-019404mem:206FNN/ANo matching ThreadX timer lifecycle finding
BUG-020761mem:233TPN/ABD-RES-INVFREE — freeing an interior pointer
BUG-021415mem:257PartialN/ARelated lost-resource effect at the alias assignment, not the double free
BUG-022401mem:311TPN/ABD-RES-LEAKS — failed-retry buffer leaks
BUG-023362con:37TPN/ABD-TRS-MLOCK — unlocked g_stats update (con:39)
BUG-024366con:56FNN/ANo matching TOCTOU report; init.c:225 leak is a different path
BUG-025833con:87TPN/ATX model: BD-TRS-ORDER lock-order deadlock (con:75)
BUG-026364con:108TPN/ATX model: BD-TRS-THRDR on unsynchronized g_ready (con:111)

Legend: sa = harness_sizearith.c · mem = harness_memory.c · con = harness_concurrency.c. Verdicts reproduce the committed threadx-allflow-misra-240/DETECTION_MATRIX.csv; the original-run matrix stays in reports/adjudication/.

evaluation/reports/threadx-allflow-misra-240/DETECTION_MATRIX.csv · original: reports/adjudication/29 / 30
Appendix B

Every candidate, BUG-027 … BUG-052, and where to check all of it

50 valid candidates · 21 true positives
Sonar code result: unavailable (403)
IDCWESiteAll-Flow 240sSonarAdjudication note
BUG-027362con:134FNN/ANo matching list race finding
BUG-028667con:153TPN/ATX model: BD-TRS-REVLOCK — mutex released unacquired (con:155)
BUG-029366con:164TPN/ATX model: BD-TRS-THRDR on unsynchronized g_inited (con:166)
BUG-030366con:190FNN/ANo queue-status or unchecked-read finding
BUG-031476np:74InvalidN/ASame range check means a non-NULL mirror implies a non-NULL primary
BUG-032476np:94TPN/ABD-PB-NP — possible null channel dereference
BUG-033690np:113TPN/AAllocation return-check and null-dereference findings
BUG-034457np:151TPN/ABD-PB-NOTINIT — use of unassigned frame pointer
BUG-035476np:166IndirectN/ABD-PB-CC flags the late null check as always false; no direct dereference finding
BUG-036690np:184FNN/ANo matching unchecked-callback finding
BUG-037476np:200TPN/ABD-PB-NOTINIT — uninitialized return value
BUG-038476np:224TPN/ABD-PB-NP — possible null channel dereference
BUG-039129ta:56FNN/ANo matching calibration-table bounds finding
BUG-040787ta:71TPN/ABD-PB-OVERFWR — destination overflow
BUG-041120ta:86FNN/ANo matching unbounded-string-copy finding
BUG-042129ta:101TPN/ABD-PB-ARRAY — index 4 through 7 in a 4-entry table
BUG-043787ta:116FNN/ANo matching accumulator-array bounds finding
BUG-044134ta:133FNN/ANo matching tainted-format-string finding
BUG-045680/787ta:151FNN/ANo matching allocation-size / string-copy finding
BUG-046129ta:179TPN/ABD-PB-ARRAY — handler index 12 through 15
BUG-047457un:41FNN/ANo finding on pooled frame flags
BUG-048457un:63TPN/ABD-PB-NOTINIT — non-initialized h.flags (un:69)
BUG-049457un:17TPN/ABD-PB-NOTINIT traces the helper's missing flags initialization
BUG-050457un:127TPN/AUninitialized-use and invalid-free findings at slot_track
BUG-051457un:143FNN/ANo finding on the uninitialized CRC entry
BUG-052457un:167FNN/ANo matching uninitialized stats-field finding

Legend: np = harness_nullpaths.c · ta = harness_taint.c · un = harness_uninit.c · mem = harness_memory.c · con = harness_concurrency.c.

Verify any row: PLANTED_BUGS.md · *-findings.csv · latest DETECTION_MATRIX.csv · PARASOFT_RUN_GUIDE.md · run-summary.csv hashes. Repository: github.com/zuwasi/parasoft-vs-sonarqube-threadx (MIT). Prepared by Daniel Liezrowice, ESL — Engineering Software Lab, 2026-10-08.

evaluation/reports/threadx-allflow-misra-240/DETECTION_MATRIX.csv · evaluation/PLANTED_BUGS.md30 / 30