Bug 68270 - [MPX] Common pattern for variable sized data clashes with MPX bound checks
Summary: [MPX] Common pattern for variable sized data clashes with MPX bound checks
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 5.2.0
: P3 enhancement
Target Milestone: ---
Assignee: Martin Liška
URL:
Keywords:
Depends on:
Blocks: CHKP
  Show dependency treegraph
 
Reported: 2015-11-10 10:01 UTC by Jussi Judin
Modified: 2019-11-20 06:32 UTC (History)
0 users

See Also:
Host:
Target: x86_64-*-*, i?86-*-*
Build:
Known to work: 7.0
Known to fail:
Last reconfirmed: 2017-03-03 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jussi Judin 2015-11-10 10:01:28 UTC
A very common pattern due to pedantic C89, C90, and C++ compatibility is to declare an array of size 1 when having a structure with a variable sized member at the end. GCC's memory protection extensions, however, work in a way that only zero/variable sized members are treated in such way that their bounds are not explicitly checked (https://gcc.gnu.org/wiki/Intel%20MPX%20support%20in%20the%20GCC%20compiler#line-142). This makes it impossible to use existing code with MPX checks without changes that go through large amount of header files that use this pattern of arrays size 1.

To demonstrate this issue, here are 3 different ways to indicate structures with a variable sized array at the end of the structure:

typedef struct struktura1 {
    long len;
    char data[];
} struktura1;

typedef struct struktura2 {
    long len;
    char data[0];
} struktura2;

typedef struct struktura3 {
    long len;
    char data[1] __attribute__((bnd_variable_size));
} struktura3;

If we compile them with different standards and warning levels, we'll get these kind of results:

$ gcc-5.2.0 --std=c89 -pedantic tst.c
tst.c:3:10: warning: ISO C90 does not support flexible array members [-Wpedantic]
     char data[];
          ^
tst.c:8:10: warning: ISO C forbids zero-size array ‘data’ [-Wpedantic]
     char data[0];

$ gcc-5.2.0 -xc++ --std=c++14 -pedantic tst.c 
tst.c:3:15: warning: ISO C++ forbids zero-size array ‘data’ [-Wpedantic]
     char data[];
               ^
tst.c:8:16: warning: ISO C++ forbids zero-size array ‘data’ [-Wpedantic]
     char data[0];                                                                

$ gcc-4.8 --std=c11 -pedantic tst.c 
tst.c:8:10: warning: ISO C forbids zero-size array ‘data’ [-Wpedantic]            
     char data[0];                                                                
          ^                                                                       
tst.c:13:5: warning: ‘bnd_variable_size’ attribute directive ignored [-Wattributes]
     char data[1] __attribute__((bnd_variable_size));
     ^

Not to mention that a lot of code is compiled with other compilers than GCC that don't know about "bnd_variable_size" attribute, so making the code shown above to be compatible with different compilers and also having MPX checks in place requires some macro magic depending on which compiler is in use and which standard the compilation is done against.

GCC should ignore or have an option to ignore bound checks for arrays of size 1 at the end of the structure so that just trying out MPX support wouldn't need large scale changes to existing code bases.
Comment 1 Richard Biener 2015-11-10 11:01:26 UTC
MPX should just behave like the rest of GCC treating _all_ trailing arrays as possibly flexible.
Comment 2 Peter Wu 2016-09-02 21:31:38 UTC
GCC 6.2.1 is still affected by this. In C99 we can get away with flexible array members, but this feature is unfortunately not defined in the C++ specification.

The idiom with an array of length 1 is quite common, is it possible to detect that situation and relax the boundaries?
Comment 3 Alexander Ivchenko 2016-12-27 13:44:41 UTC
Addressed in 
------------------------------------------------------------------------
r243936 | aivchenk | 2016-12-27 16:31:43 +0300 (Tue, 27 Dec 2016) | 18 lines

2016-12-27  Alexander Ivchenko  <alexander.ivchenko@intel.com>

* c-family/c.opt (flag_chkp_flexible_struct_trailing_arrays):
  Add new option.
  (fchkp-narrow-to-innermost-array): Fix typo.
* doc/cpp.texi (flag_chkp_flexible_struct_trailing_arrays): Ditto.
* tree-chkp.c (chkp_may_narrow_to_field ): Forbid
  narrowing when flag_chkp_flexible_struct_trailing_arrays is used
  and the field is the last array field in the structure.


2016-12-27  Alexander Ivchenko  <alexander.ivchenko@intel.com>

* gcc.target/i386/mpx/vla-trailing-1-lbv.c: New test.
* gcc.target/i386/mpx/vla-trailing-1-nov.c: Ditto.
* gcc.target/i386/mpx/vla-trailing-1-ubv.c: Ditto.



The new option -fchkp-flexible-struct-trailing-arrays will allow to treat all trailing arrays in structures as possibly flexible.

The bug can be closed
Comment 4 Martin Liška 2017-03-03 14:42:42 UTC
The issue is not solved, let's consider:

$ cat /tmp/chkp.ii
typedef struct a *b;
struct a {
  struct {
    int e[1];
  } f;
};
int g(b ptr)
{
  return ptr->f.e[1];
}

$ ./xgcc -B. /tmp/chkp.ii -Werror -c -mmpx -fcheck-pointer-bounds -O1 -Wall -fchkp-flexible-struct-trailing-arrays 
/tmp/chkp.ii: In function ‘int g.chkp(b, \xe2\x80\x98pointer_bounds_typ\xe2\x80\x99 not supported by dump_type#<type error>, void, ...)’:
/tmp/chkp.ii:9:20: error: memory access check always fail [-Werror=chkp]
   return ptr->f.e[1];
                    ^
cc1plus: all warnings being treated as errors

It's wrong and reason is explained in Richi's email:
https://gcc.gnu.org/ml/gcc-patches/2017-01/msg00172.html

I'm testing the patch.
Comment 5 Martin Liška 2017-03-07 14:13:24 UTC
Author: marxin
Date: Tue Mar  7 14:12:52 2017
New Revision: 245951

URL: https://gcc.gnu.org/viewcvs?rev=245951&root=gcc&view=rev
Log:
Use array_at_struct_end_p in tree-chkp.c (PR middle-end/68270).

2017-03-07  Martin Liska  <mliska@suse.cz>

	PR middle-end/68270
	* tree-chkp.c (chkp_may_narrow_to_field): Add new argument ref.
	Use array_at_struct_end_p instead of DECL_CHAIN (field).
	(chkp_narrow_bounds_for_field): Likewise.
	(chkp_parse_array_and_component_ref): Pass one more argument to
	call.
2017-03-07  Martin Liska  <mliska@suse.cz>

	PR middle-end/68270
	* g++.dg/pr68270.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/pr68270.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-chkp.c
Comment 6 Martin Liška 2017-03-07 14:51:03 UTC
Fixed on trunk.
Comment 7 Martin Liška 2017-03-21 14:13:49 UTC
As the flag fchkp-flexible-struct-trailing-arrays was introduced in GCC7, the issue can be closed as resolved.