Skip to content

The CPU paged attention reads past a block table shorter than the sequence it addresses, and the W6 seam case supplies one #1394

Description

@localai-bot

vt::cpu::PagedAttentionKernel reads btab[r * bt_row + (j / block_size) * bt_col] for every j < seq_lens[r] and never checks that the block table has that many columns. A caller that supplies a table shorter than ceil(seq_lens[r] / block_size) gets an out-of-bounds read of the tensor's own storage, a plausible-looking block index out of it, and attention over the wrong page. Nothing faults and nothing is reported.

tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp supplies exactly that. Its SpecAttnMeta helper hardcoded block_table_num_cols = 1 with one entry per request, while shape C of the W6 case sits at pos = 20 with q = 4, so seq_lens = 24 against CachePool's block_size = 16 and the kernel reads column 1 of a one-column table.

It was silent until the neighbouring bytes moved. Found while fixing #1380: a DevicePool change altered which pooled block holds the table and therefore what follows it, and the same read became a SIGSEGV on thor:gpu0. gdb at src/vt/cpu/cpu_paged_attn.cpp:224, one frame under FullAttnBlockPaged, reached from the eager fallback of Qwen3_5DecodeGraph::Step for that shape. The case passes at origin/main (8 cases / 138 assertions) purely because the read landed on bytes that decoded to an in-range block index.

Both halves are fixed in the same flow, per AGENTS.md: the kernel refuses a short table with one compare per request outside the token loop, and the test's helper sizes its block table for the sequence length it declares.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions