diff --git a/sys/dev/drm/radeon/r100.c b/sys/dev/drm/radeon/r100.c --- a/sys/dev/drm/radeon/r100.c +++ b/sys/dev/drm/radeon/r100.c @@ -1322,14 +1322,21 @@ ib = p->ib.ptr; track = (struct r100_cs_track *)p->track; c = radeon_get_ib_value(p, idx++) & 0x1F; - if (c > 16) { + /* DF-1209: c == 0 must be rejected. The loop below uses (c - 1) as the + * bound; with c unsigned, c == 0 wraps (c - 1) to UINT_MAX and the loop + * writes unboundedly past track->arrays[16] (cb/zb/aa/textures/slab). + * c == 0 is also nonsensical (LOAD_VBPNTR with zero buffers), so reject + * it alongside the existing c > 16 check. */ + if (c > 16 || c == 0) { DRM_ERROR("Only 16 vertex buffers are allowed %d\n", pkt->opcode); radeon_cs_dump_packet(p, pkt); return -EINVAL; } track->num_arrays = c; - for (i = 0; i < (c - 1); i+=2, idx+=3) { + /* Guard with i + 1 < c so there is no unsigned underflow even if a + * future caller bypasses the c == 0 check above. */ + for (i = 0; i + 1 < c; i+=2, idx+=3) { r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) { DRM_ERROR("No reloc for packet3 %d\n",