Skip to content

Filter::ApplyStencil ignores component offsets #6656

@WeiqunZhang

Description

@WeiqunZhang

Summary

All four overloads of Filter::ApplyStencil only clamp ncomp against the total number of components in the source MultiFab/FArrayBox (Filter/Filter.cpp:41,82,201,255). When callers pass a non-zero scomp/dcomp to filter a subset of components, the code happily iterates over ncomp entries even if scomp + ncomp > src.nComp() or dcomp + ncomp > dst.nComp(). The default ncomp=10000 makes this especially easy to trigger. The out-of-bounds reads/writes are undefined behaviour and can trample unrelated data the moment we filter a sub-range near the end of a MultiFab.

Impact

Charge/current filtering in WarpX::ApplyFilterandSumBoundaryRho already exercises the non-zero scomp path; today it relies on manually keeping ncomp within bounds. Any future refactoring (or user code) that passes ncomp greater than the remaining components will corrupt the MultiFab on both CPU and GPU backends. The bug also silently returns garbage because there is no assert or guard.

Fix

Clip ncomp relative to both scomp and dcomp for every overload, and bail out early if nothing remains to filter. This keeps existing callers working while making the API safe for partial-component filtering.

Patch

@@ Filter::ApplyStencil (MultiFab&, GPU path)
-    ncomp = std::min(ncomp, srcmf.nComp());
+    ncomp = std::min(ncomp, srcmf.nComp() - scomp);
+    ncomp = std::min(ncomp, dstmf.nComp() - dcomp);
+    if (ncomp <= 0) { return; }
@@ Filter::ApplyStencil (FArrayBox&, GPU path)
-    ncomp = std::min(ncomp, srcfab.nComp());
+    ncomp = std::min(ncomp, srcfab.nComp() - scomp);
+    ncomp = std::min(ncomp, dstfab.nComp() - dcomp);
+    if (ncomp <= 0) { return; }
@@ Filter::ApplyStencil (MultiFab&, CPU path)
-    ncomp = std::min(ncomp, srcmf.nComp());
+    ncomp = std::min(ncomp, srcmf.nComp() - scomp);
+    ncomp = std::min(ncomp, dstmf.nComp() - dcomp);
+    if (ncomp <= 0) { return; }
@@ Filter::ApplyStencil (FArrayBox&, CPU path)
-    ncomp = std::min(ncomp, srcfab.nComp());
+    ncomp = std::min(ncomp, srcfab.nComp() - scomp);
+    ncomp = std::min(ncomp, dstfab.nComp() - dcomp);
+    if (ncomp <= 0) { return; }

Prepared by Codex

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions