fix: add virtual destructor to npu_cmd to prevent heap corruption (affects v0.9.42+) - #580
Open
rmanicardi wants to merge 1 commit into
Open
fix: add virtual destructor to npu_cmd to prevent heap corruption (affects v0.9.42+)#580rmanicardi wants to merge 1 commit into
rmanicardi wants to merge 1 commit into
Conversation
Without a virtual destructor, deleting a derived npu_cmd object (e.g. npu_write_cmd, 48 bytes) through a base npu_cmd pointer invokes the base-class destructor and calls operator delete with sizeof(npu_cmd)=8, not sizeof(npu_write_cmd)=48. This is undefined behaviour per [expr.delete] §3 and causes heap corruption: SIGABRT during model loading or on the first inference request. The bug is latent in all prior versions. It became fatal in 0.9.42 because npu_write_cmd gained several data fields, growing from ~8 bytes to 48 bytes. With the old layout, the wrong-sized delete accidentally freed the correct number of bytes; at 48 bytes it corrupts the allocator's chunk metadata. Fix: add `virtual ~npu_cmd() = default;` so that unique_ptr<npu_cmd> destruction dispatches through the vtable to the correct derived destructor and sized-deallocation uses the actual object size. Also add #include <climits> to npu_cmd.hpp: UCHAR_MAX (used by the op_headers enum for XAIE_IO_CUSTOM_OP_MAX) is defined there; relying on it arriving transitively from other headers is fragile. All pre-built NPU libraries must be recompiled against this updated header for the fix to take effect in those translation units. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
astrelsky
approved these changes
Jul 12, 2026
|
This is clearly correct. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
npu_cmddeclares pure virtual methods but has no virtual destructornpu_sequenceowns astd::vector<std::unique_ptr<npu_cmd>>of heterogeneous derived objects (e.g.npu_write_cmd, 48 bytes)unique_ptr<npu_cmd>callsoperator delete(ptr, sizeof(npu_cmd))=operator delete(ptr, 8)— wrong-sized deallocation of a 48-byte object, corrupting glibc heap metadata →SIGABRT#include <climits>which is required forUCHAR_MAXused in theop_headersenum (XAIE_IO_CUSTOM_OP_MAX = UCHAR_MAX)Affected versions
npu_write_cmdwas ~8 bytes, so wrong-sized delete freed the correct amount by accidentnpu_write_cmdis now 48 bytes; wrong-sized delete corrupts allocator chunk metadata →SIGABRTRoot cause
Deleting through a base pointer without a virtual destructor is undefined behaviour per C++ [expr.delete] §3 when the dynamic type differs from the static type.
Crash — reproduced on v0.9.43 (Fedora 44 / GCC 14 / ASan)
Trigger:
flm serve qwen3.5:4b --ctx-len 4096— process aborts during model loading before serving any request.Fix
Test plan
flmwith ASan (-fsanitize=address)flm serve qwen3.5:4b --ctx-len 4096— confirm nonew-delete-type-mismatchat startup.solibraries against the updated header🤖 Generated with Claude Code