Bug 83251 - __builtin___bnd_narrow_ptr_bounds(x, x, ...) generates wrong code that modifies a constant
Summary: __builtin___bnd_narrow_ptr_bounds(x, x, ...) generates wrong code that modifi...
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 7.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Keywords: wrong-code
Depends on:
Reported: 2017-12-01 23:30 UTC by Paul Eggert
Modified: 2018-06-22 08:46 UTC (History)
0 users

See Also:
Target: x86_64-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:

Test case main program (you also need foobody.i) (173 bytes, text/plain)
2017-12-01 23:30 UTC, Paul Eggert
Test case subroutines (you also need foomain.i) (243 bytes, text/plain)
2017-12-01 23:31 UTC, Paul Eggert

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Eggert 2017-12-01 23:30:36 UTC
Created attachment 42773 [details]
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'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.
Comment 1 Paul Eggert 2017-12-01 23:31:33 UTC
Created attachment 42774 [details]
Test case subroutines (you also need foomain.i)
Comment 2 Martin Liška 2018-06-22 08:46:32 UTC
MPX is removed, won't fix then.