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?

Reply via email to