Upstream: ggml-org#28902
M-RoPE embedding batches read beyond the position array when pos is null or has the documented n_tokens length.
Reproduced on spark-a934.local, Linux aarch64, GCC 13.3, upstream 930e2fa5995789efbf249a8bf61325bb626e417b. This is a focused allocator-level ASan test, not an end-to-end model run; no model required.
Save as repro.cpp:
#include "llama-batch.h"
#include "llama-vocab.h"
#include <cstdio>
#include <cstdlib>
#include <vector>
int main(int argc, char ** argv) {
const int planes = argc > 1 ? std::atoi(argv[1]) : 0;
float embeddings[2] = {0.0f, 0.0f};
std::vector<llama_pos> positions(2 * planes);
for (size_t i = 0; i < positions.size(); ++i) {
positions[i] = i % 2;
}
llama_batch batch = {};
batch.n_tokens = 2;
batch.embd = embeddings;
batch.pos = planes ? positions.data() : nullptr;
llama_vocab vocab;
llama_batch_allocr alloc(4);
if (!alloc.init(batch, vocab, nullptr, 1, 1, true)) {
return 2;
}
alloc.split_reset();
auto ubatch = alloc.split_simple(2);
for (unsigned i = 0; i < ubatch.n_tokens * ubatch.n_pos; ++i) {
std::printf("%d ", ubatch.pos[i]);
}
std::puts("");
}
From the tested checkout, with its CPU Release library in build/bin:
g++ -std=c++17 -O1 -g -fsanitize=address -fno-omit-frame-pointer -Iinclude -Isrc -Iggml/include -Iggml/src repro.cpp src/llama-batch.cpp -Lbuild/bin -Wl,-rpath,"$PWD/build/bin" -lllama -lggml-base -o repro
ASAN_OPTIONS=detect_leaks=0 ./repro 0
ASAN_OPTIONS=detect_leaks=0 ./repro 1
ASAN_OPTIONS=detect_leaks=0 ./repro 4
Observed: modes 0 (null positions) and 1 (one plane) both report heap-buffer-overflow, a 4-byte read immediately after an 8-byte allocation, at llama_batch_allocr::ubatch_add, src/llama-batch.cpp:787. Mode 4 passes, printing 0 1 0 1 0 1 0 1.
Cause: the copy loop reads four position planes, while the null fallback allocates only one. Introducing commit not bisected.
Upstream: ggml-org#28902
M-RoPE embedding batches read beyond the position array when
posis null or has the documentedn_tokenslength.Reproduced on spark-a934.local, Linux aarch64, GCC 13.3, upstream
930e2fa5995789efbf249a8bf61325bb626e417b. This is a focused allocator-level ASan test, not an end-to-end model run; no model required.Save as
repro.cpp:From the tested checkout, with its CPU Release library in
build/bin:g++ -std=c++17 -O1 -g -fsanitize=address -fno-omit-frame-pointer -Iinclude -Isrc -Iggml/include -Iggml/src repro.cpp src/llama-batch.cpp -Lbuild/bin -Wl,-rpath,"$PWD/build/bin" -lllama -lggml-base -o repro ASAN_OPTIONS=detect_leaks=0 ./repro 0 ASAN_OPTIONS=detect_leaks=0 ./repro 1 ASAN_OPTIONS=detect_leaks=0 ./repro 4Observed: modes 0 (null positions) and 1 (one plane) both report
heap-buffer-overflow, a 4-byte read immediately after an 8-byte allocation, atllama_batch_allocr::ubatch_add,src/llama-batch.cpp:787. Mode 4 passes, printing0 1 0 1 0 1 0 1.Cause: the copy loop reads four position planes, while the null fallback allocates only one. Introducing commit not bisected.