https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77718

            Bug ID: 77718
           Summary: expand_builtin_memcmp swaps args
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: acsawdey at gcc dot gnu.org
                CC: bernds at gcc dot gnu.org
  Target Milestone: ---

Created attachment 39674
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39674&action=edit
test case

If you have a memcmp call that has const string args but one or both of them
are shorter than the constant length given, the builtin expansion machinery
will get called to expand the builtin, but the arguments given are reversed so
the result is unexpected. The attached test will provoke this condition.

In expand_buildin_memcmp () the following code is where this happens:

  by_pieces_constfn constfn = NULL;

  const char *src_str = c_getstr (arg1);
  if (src_str == NULL)
    src_str = c_getstr (arg2);
  else
    std::swap (arg1_rtx, arg2_rtx);

  /* If SRC is a string constant and block move would be done
     by pieces, we can avoid loading the string from memory
     and only stored the computed constants.  */
  if (src_str
      && CONST_INT_P (len_rtx)
      && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1)
    constfn = builtin_memcpy_read_str;

  rtx result = emit_block_cmp_hints (arg1_rtx, arg2_rtx, len_rtx,
                                     TREE_TYPE (len), target,
                                     result_eq, constfn,
                                     CONST_CAST (char *, src_str));

If you have arg1 a const str, then you get the swap of arg1_rtx and arg2_rtx.
Normally this would be hidden because ccp folding earlier would have evaluated
the memcmp to a const value since all args are const. However that folding does
not happen when one/both of the strings are shorter than the given length since
that is an undefined situation. Thus we come in here and get this swap but in
this case result_eq won't be set.

I think the solution might be to only do the swap when result_eq is set.

Reply via email to