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

            Bug ID: 83251
           Summary: __builtin___bnd_narrow_ptr_bounds(x, x, ...) generates
                    wrong code that modifies a constant
           Product: gcc
           Version: 7.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: eggert at gnu dot org
  Target Milestone: ---

Created attachment 42773
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42773&action=edit
Test case main program (you also need foobody.i)

I ran into this problem trying to use -fcheck-pointer-bounds on GNU Emacs. I
used gcc (Ubuntu 7.2.0-8ubuntu3) 7.2.0 on x86-64 (Ubuntu 17.10); my CPU was a
Kaby Lake processor (Intel Core i3-7100U) that supports Intel MPX. To
reproduce, compile and run the attached source code as follows:

gcc -mmpx -fcheck-pointer-bounds -O2 -S foobody.i foomain.i
gcc -mmpx -fcheck-pointer-bounds -O2 foobody.s foomain.s
./a.out

a.out's output contains many incorrect lines like this:

Saw a #BR! status 1 at 0x55fae4af26da

The problem occurs because incorrect code is generated for the function
'calculate_address', whose source code looks like this:

  Lisp_Object *sym = &lispsym[1213];
  char *narsym = __builtin___bnd_narrow_ptr_bounds (sym, sym,
                                                    sizeof (Lisp_Object));
  return (Lisp_Object) (narsym + sizeof *sym);

This is a pure function that merely calculates an address and returns it.
Instead, as foobody.s shows, this function's implementation also modifies
global metadata, for example:

        movq    8+__chkp_bounds_of_lispsym(%rip), %rax
        cmpq    %rdx, %rax
        cmovb   %rdx, %rax
        movq    %rax, 8+__chkp_bounds_of_lispsym(%rip)

Here calculate_address's implementation conditionally shrinks
__chkp_bounds_of_lispsym, the bounds of the 'lispsym' array. But lispsym is a
static array and its bounds should never change. As a result of this mistaken
implementation, later valid attempts to access the lispsym array (in
'obviously_safe') fail their bounds check and this mistake in GCC causes the
program to crash even though it is a valid program.

Reply via email to