https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122716
Bug ID: 122716
Summary: out-of-bounds operands write in aarch64-sme2.md
Product: gcc
Version: 15.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: tnfchris at gcc dot gnu.org
Target Milestone: ---
Commit g:0ec3d20bfbcb6f200ecdd85683aa9e8ea5a845c added a whole lot of SME2p1
intrinsics but there's something odd about them.
As an example
(define_insn "@aarch64_sme_<optab><mode><mode>"
[(set (match_operand:SVE_FULLx24 0 "aligned_register_operand"
"=Uw<vector_count>")
(unspec:SVE_FULLx24
[(reg:SVE_FULLx24 ZA_REGNUM)
(reg:DI SME_STATE_REGNUM)
(match_operand:DI 1 "const_int_operand")
(match_operand:SI 2 "register_operand" "Ucj")
(const_int 0)]
SME_READZ_HV))
(set (reg:SVE_FULLx24 ZA_REGNUM)
(unspec:SVE_FULLx24
[(reg:SVE_FULLx24 ZA_REGNUM)
(reg:DI SME_STATE_REGNUM)
(match_dup 1)
(match_dup 2)
(const_int 1)]
SME_READZ_HV))]
"TARGET_STREAMING_SME2p1"
{
operands[3] = GEN_INT (<vector_count> - 1);
return "movaz\t%0, za%1<hv>.<Vetype>[%w2, 0:%3]";
}
)
writes into operands[3] but only 3 operands were declared.
The generated code
rtx
gen_aarch64_sme_readz_horvnx32qivnx32qi (const rtx operand0, const rtx
operand1, const rtx operand2)
{
rtx operands[3] ATTRIBUTE_UNUSED = { operand0, operand1, operand2 };
static const uint8_t expand_encoding[] = {
0x17, 0x00, 0x02, 0x1f, 0x01, 0x00, 0x1a, 0x74,
0x05, 0x30, 0x74, 0x5d, 0x30, 0x11, 0x59, 0x01,
0x01, 0x01, 0x02, 0x27, 0x00, 0x85, 0x12, 0x1f,
0x30, 0x74, 0x5d, 0x1a, 0x74, 0x05, 0x30, 0x74,
0x5d, 0x30, 0x11, 0x59, 0x01, 0x01, 0x01, 0x02,
0x27, 0x01, 0x85, 0x12
};
return expand_rtx (expand_encoding, operands);
}
does indeed only create space for 3 operands and n_operands is also set to 3
{
"aarch64_sme_readz_horvnx32qivnx32qi",
#if HAVE_DESIGNATED_UNION_INITIALIZERS
{ .function = output_14744 },
#else
{ 0, 0, output_14744 },
#endif
{ (insn_gen_fn::stored_funcptr) gen_aarch64_sme_readz_horvnx32qivnx32qi },
&operand_data[19151],
3,
3,
2,
1,
3
},
yet the output function does indeed do
static const char *
output_14744 (rtx *operands ATTRIBUTE_UNUSED, rtx_insn *insn ATTRIBUTE_UNUSED)
{
{
operands[3] = GEN_INT (2 - 1);
return "movaz\t%0, za%1h.b[%w2, 0:%3]";
}
}
It's unclear to me how this can be safe.. and I think we're only getting away
with it because of the object alignments. Unless I've missed something?