This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Variadic macros in installed headers
On 11/25/19 1:02 AM, Florian Weimer wrote:
* Martin Sebor:
The syntax of the new attribute follows the pattern of attribute
format and I don't think it can easily be changed. I suspected
the variadic macros would be a problem for Glibc but I'm not sure
how to get around it other than by providing two macros for each
access mode. I'm open to ideas.
__attribute__ itself gets around this because of the extra
parentheses:
__attribute__ ((__access__ (__read_only__, 2)))
So the fallback definition can just look like this:
#define __attribute__(x)
We could do something similar and write:
#define __access(x) __attribute__ ((__access__ x))
__access ((__read_only__, 2))
Great!
One of the uses for this infrastructure that Joseph pointed out is
VLAs (as function arguments). I hope to add that in GCC 11 so that
something like
void f (int a[n], unsigned n);
will be automatically annotated as if it had been written like so:
__attribute__ ((access (read_write, 1, 2)))
void f (int a[n], unsigned n);
There is already weird syntax in this area:
void f (unsigned n; int a[n], unsigned n);
Ugh. I didn't even know this existed.
I'm not sure I know what you mean by C++-like pointer-pairs.
A range expressed by a pointer to its first element and a pointer one
past its last element.
I see what you mean now.
I think it's possible to express this with your patch with suitable
inline function wrappers. They would likely be simpler if there were
builtins that assert that a specific region of memory is going to be
accessed by the code below, i.e., you could write something like this:
static inline void
f (int *__begin, int *__end)
{
__builtin_access (__write_only__, __begin, __end - __begin);
__real_f (__begin, __end);
}
It's too late now (stage 3) to introduce a new built-in into GCC
but it might be an enhancement to consider for GCC 11 or later.
(FWIW, I'm not sure how well this will work with pointer
differences -- GCC doesn't track information about pointers
and their relationships nearly as reliably or extensively
as it does about integers.)
Without that, it would probably look like this:
static inline void __attribute__ ((__access__, (__write_only__, 1, 3)))
__f (int *__begin, int *__end, ptrdiff_t __size)
{
__real_f (__begin, __end);
}
static inline void
f (int *__begin, int *__end)
{
__f (__begin, __end, __end - __begin);
}
We probably should have two variants for __write_only__, one that says
“will write”, and one for “may write”.
You mean a "full write" to guarantee that exactly as many elements
will have been written (as in memset) and "may write" to denote
a partial write (like strcpy or fgets)? Those extensions certainly
are possible within the attribute framework.
Furthermore, this scheme is unfortunately incompatible with SAL:
<https://docs.microsoft.com/en-us/visualstudio/code-quality/understanding-sal>
I considered the annotations some other compilers expose when
designing the attribute only as a high-level precedent for
the feature (like C# In and Out). Bit source compatibility
with any of them was never my goal (nor has anyone requested
it). I suppose it would be possible to implement the SAL
scheme on top of the attributes but it would require changes
to the parsers. But I would rather see us provide support
for C++ contracts.
In any case, if you think any of these solutions are important
for GCC to provide please open requests for them in Bugzilla.
I may not have the bandwidth to implement them in GCC 11 but
I might be able to work on some, and someone else might
implement the others.
Until then, I'm hoping Glibc will put the existing attributes
to use to benefit from the improved our-of-bounds detection
(as the mode names suggest, the attribute detects both out-
of-bounds reads and writes).
Martin
PS I'm excited about this feature because besides out-of-bounds
accesses, the attribute makes it possible (and I have patches)
to detect uninitialized reads by annotated functions
(-Wuninitialized), variables that are written to but not read
from (-Wunused), and overlapping copies (-Wrestrict).
In addition, the attribute also opens up similar optimization
opportunities for user-defined functions as those compilers
already take advantage of for built-in functions.