Hi, On 16/09/16 13:29, Martin Sebor wrote:
__builtin_object_size fails for POINTER_PLUS expressions involving non-constant offsets into objects of known size, causing GCC to fail to detect (and add instrumentation to prevent) buffer overflow in some basic cases such as the following:void f (unsigned i) { char d [3]; memcpy (d + i, "abcdef", 5); } Since the size of the destination object is known, the call to memcpy is guaranteed to write past the end of it regardless of the value of the offset. The attached patch enhances __builtin_object_size to handle this case by returning the size of the whole object as the maximum and the size of the object minus T_MAX for the type of the offset T as the minimum. The patch also adds handling of ranges even though only very few cases benefit from it because the VRP pass runs after the object size pass. The one case that does appear to profit is when the value of the offset is constrained by its type, as in char a [1000]; unsigned g (unsigned char i) { char *p = a + i; return __builtin_object_size (p, 2); } Here get_range_info () lets __builtin_object_size determine that the minimum number of bytes between (a + i) and (a + sizeof s) is sizeof a - UCHAR_MAX. The patch results in 64 more checking calls in a Binutils build than before. Martin PS What would be a good way to arrange for the VRP pass to run before the object size pass so that the latter can benefit more from range information? As an experiment I added another instance of the VRP pass before the object size pass in passes.def and that worked, but I suspect that running VRP a third time isn't optimal.
I am working on early-vrp and that might be of interest to you. https://gcc.gnu.org/ml/gcc-patches/2016-09/msg00993.html Thanks, Kugan
