ggml : fix set_rows CPU crash when the destination is F32 (#2038)

The CPU `set_rows` kernel for F32 sources fetches `type_traits[dst->type].from_float`
and calls it for every scattered row. F32 has no `from_float` entry, it is NULL in
`type_traits`, so any `set_rows` into an F32 destination calls a NULL function pointer
and segfaults. Other destination types work because they all have a real `from_float`.

Repro (CPU backend, standalone ggml graph):

    dst = new_tensor_2d(F32, 8, 6)   // F32 destination
    src = new_tensor_2d(F32, 8, 4)
    idx = new_tensor_1d(I64, 4)      // {0,2,4,5}
    out = ggml_set_rows(dst, src, idx)
    // ggml_backend_graph_compute(cpu, ...) -> SIGSEGV on current main

When the destination is F32, copy the row with `memcpy` instead of going through
`from_float`. The I32 and I64 index branches both get the same treatment. An assert
guards the remaining case, non-F32 dst with a NULL `from_float`, so a future
unsupported type fails loudly instead of crashing.

I ran a normal model after this and it still decodes fine (DeepSeek-V2-Lite-Q4_K_M,
CPU, coherent output), and the non-F32 path is untouched. On the F32 path you pay one
`memcpy` per row in place of the indirect call.

Co-authored-by: local-llm <local-llm@local-llm-R740.cruvis.org>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
mb8565 2026-06-26 01:46:26 -05:00 committed by GitHub
parent b84902d2ad
commit 0ffdf509ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -19007,6 +19007,11 @@ static void ggml_compute_forward_set_rows_f32(
const int64_t ir1 = MIN(ir0 + dr, nr);
ggml_from_float_t const from_float = type_traits[dst->type].from_float;
// F32 has no from_float entry in type_traits (it is NULL), so set_rows into an F32
// destination would call a NULL function pointer and crash. Handle F32 dst with a
// direct float copy. Hit by graphs that scatter F32 rows into an F32 base.
const bool dst_is_f32 = (dst->type == GGML_TYPE_F32);
GGML_ASSERT(dst_is_f32 || from_float);
if (src1->type == GGML_TYPE_I64) {
for (int64_t i03 = 0; i03 < ne03; ++i03) {
@ -19020,8 +19025,10 @@ static void ggml_compute_forward_set_rows_f32(
GGML_ASSERT(i1 >= 0 && i1 < ne1);
from_float((const float *) ((char *) src0->data + i*nb01 + i02*nb02 + i03*nb03),
((char *) dst->data + i1*nb1 + i02*nb2 + i03*nb3), nc);
const float * src_row = (const float *) ((char *) src0->data + i*nb01 + i02*nb02 + i03*nb03);
char * dst_row = (char *) dst->data + i1*nb1 + i02*nb2 + i03*nb3;
if (dst_is_f32) memcpy(dst_row, src_row, nc*sizeof(float));
else from_float(src_row, dst_row, nc);
}
}
}
@ -19038,8 +19045,10 @@ static void ggml_compute_forward_set_rows_f32(
GGML_ASSERT(i1 >= 0 && i1 < ne1);
from_float((const float *) ((char *) src0->data + i*nb01 + i02*nb02 + i03*nb03),
((char *) dst->data + i1*nb1 + i02*nb2 + i03*nb3), nc);
const float * src_row = (const float *) ((char *) src0->data + i*nb01 + i02*nb02 + i03*nb03);
char * dst_row = (char *) dst->data + i1*nb1 + i02*nb2 + i03*nb3;
if (dst_is_f32) memcpy(dst_row, src_row, nc*sizeof(float));
else from_float(src_row, dst_row, nc);
}
}
}