Guard the zero-length copy in the Span copy helpers - #74061
Conversation
CopySpanToMutableSpan, CopyCharSpanToMutableCharSpan and CopyCharSpanToMutableCharSpanWithTruncation passed span data() straight to memmove(). An empty Span may have a null data() -- TLVReader hands one out for every zero-length string -- and passing a null pointer to memmove() is undefined even at zero length, which -fsanitize=undefined reports. Skip the call when nothing is copied. The truncation helper checks the clamped size rather than source emptiness, since size_to_copy is zero for an empty destination even when the source is not empty. Add unit tests covering a null source for each helper, plus a non-empty source with a zero-size destination for the truncation helper. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe span copy helpers now skip Suggested reviewers: Merge Risk: ⚪ Minimal · up to Empty span copies now avoid undefined behavior while preserving destination contents; the change is ready to merge. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 2 files. (1 skipped: 1 unsupported.)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #74061 +/- ##
==========================================
- Coverage 57.34% 56.87% -0.47%
==========================================
Files 1943 1985 +42
Lines 128154 129319 +1165
Branches 14605 15044 +439
==========================================
+ Hits 73491 73556 +65
- Misses 54663 55763 +1100 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
ForemanZack-CableLabs
left a comment
There was a problem hiding this comment.
Looks good to me and catches that issue
Summary
Problem
Spancopy helpers insrc/lib/support/Span.hpassdata()straight tomemmove().Spanmay have a nulldata()—TLVReader::GetDataPtrreturns one for every zero-length string — and passing a null pointer tomemmove()is undefined even at zero length (C17 7.24.1p2), which-fsanitize=undefinedreports asnull pointer passed as argument 2, which is declared to never be null.Solution
CopyCharSpanToMutableCharSpanWithTruncationchecks the clamped size rather than source emptiness: it truncates instead of failing, sosize_to_copyis zero for an empty destination even when the source is not empty. Guarding on source emptiness there would leave the null destination case unguarded.Caveats
Testing
TestCopySpanToMutableSpanFromNullSource,TestCopyCharSpanToMutableCharSpanFromNullSourceandTestCopyCharSpanToMutableCharSpanWithTruncationFromNullSourcetosrc/lib/support/tests/TestSpan.cpp, covering a null source into both a sized and a default-constructed destination, plus a non-empty source into a zero-size destination for the truncation helper.linux-x64-tests-clang-ubsanwithUBSAN_OPTIONS=halt_on_error=1: without the change the suite exits 1 reportingSpan.h:406; with it, 14 tests pass and no reports are emitted.size_to_copy != 0with!span_to_copy.empty()reportsnull pointer passed as argument 1and exits 1, while the null-source tests alone stay green.🤖 Generated with Claude Code