The gcc-ASAN workflow passes, but its log carries 12 UBSan
nonnull-attribute reports, all from the same pair of methods:
ts_tbr.cpp:356:16: runtime error: null pointer passed as argument 1, which is declared to never be null
ts_tbr.cpp:356:16: runtime error: null pointer passed as argument 2, which is declared to never be null
ts_tbr.cpp:357:16: ...
ts_tbr.cpp:370:16: ...
ts_tbr.cpp:371:16: ...
ts_tbr.cpp:372:16: ...
Observed in run 30994944304 (job "AddressSanitizer tests").
Cause
TbrSnapshot::save() and ::restore() (src/ts_tbr.cpp:352-380) call
std::memcpy on std::vector::data(). When the vector is empty, data() may
return nullptr and the size is 0. memcpy(nullptr, nullptr, 0) is
undefined behaviour by the letter of the standard — memcpy's parameters
carry nonnull — even though every real implementation is a no-op.
The lines that report are the state_bytes and cost_bytes copies, which are
reached whenever a dataset yields zero-length state or cost arrays.
Why it is low severity
Benign in practice on every toolchain the package targets; nothing
miscompiles today. But it is real UB, it is the only remaining noise in an
otherwise clean sanitizer run, and a compiler is entitled to infer from the
nonnull attribute that the pointers cannot be null and delete a subsequent
null check.
Fix
Guard each copy on a non-zero size, e.g. if (state_bytes) { ... }, or hoist
one guard around the block. Six call sites.
Reopening condition
Closing this as wontfix would need the reports suppressed rather than fixed,
which would hide future genuine nonnull violations in the same file. Reopen
if a sanitizer run shows these lines again after a fix.
Found while making ASan runs clean in
#123; deliberately not widened into that PR.
The
gcc-ASANworkflow passes, but its log carries 12 UBSannonnull-attributereports, all from the same pair of methods:Observed in run 30994944304 (job "AddressSanitizer tests").
Cause
TbrSnapshot::save()and::restore()(src/ts_tbr.cpp:352-380) callstd::memcpyonstd::vector::data(). When the vector is empty,data()mayreturn
nullptrand the size is 0.memcpy(nullptr, nullptr, 0)isundefined behaviour by the letter of the standard —
memcpy's parameterscarry
nonnull— even though every real implementation is a no-op.The lines that report are the
state_bytesandcost_bytescopies, which arereached whenever a dataset yields zero-length state or cost arrays.
Why it is low severity
Benign in practice on every toolchain the package targets; nothing
miscompiles today. But it is real UB, it is the only remaining noise in an
otherwise clean sanitizer run, and a compiler is entitled to infer from the
nonnullattribute that the pointers cannot be null and delete a subsequentnull check.
Fix
Guard each copy on a non-zero size, e.g.
if (state_bytes) { ... }, or hoistone guard around the block. Six call sites.
Reopening condition
Closing this as wontfix would need the reports suppressed rather than fixed,
which would hide future genuine
nonnullviolations in the same file. Reopenif a sanitizer run shows these lines again after a fix.
Found while making ASan runs clean in
#123; deliberately not widened into that PR.