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

--- Comment #6 from Alejandro Colomar <[email protected]> ---
(In reply to Andrew Pinski from comment #5)
> (In reply to Alejandro Colomar from comment #0)
> > I propose [[gnu::returns_input_ptr(1)]] for strcpy(3),
> > and [[gnu::returns_derived_ptr(1)]] for strstr(3),
> > where in both attributes, the '1' is a parameter index, indicating
> > which parameter is the provenance of the returned pointer.
> 
> And GCC already has code to special case some builtins:
> ```
> /* Return the argument that the call STMT to a built-in function returns
>    (including with an offset) or null if it doesn't.  */
> 
> tree
> pass_waccess::gimple_call_return_arg (gcall *call)
> {
>   /* Check for attribute fn spec to see if the function returns one
>      of its arguments.  */
>   attr_fnspec fnspec = gimple_call_fnspec (call);
>   unsigned int argno;
>   if (!fnspec.returns_arg (&argno))
>     {
>       if (gimple_call_num_args (call) < 1)
>         return NULL_TREE;
> 
>       if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
>         return NULL_TREE;
> 
>       tree fndecl = gimple_call_fndecl (call);
>       switch (DECL_FUNCTION_CODE (fndecl))
>         {
>         case BUILT_IN_MEMPCPY:
>         case BUILT_IN_MEMPCPY_CHK:
>         case BUILT_IN_MEMCHR:
>         case BUILT_IN_STRCHR:
>         case BUILT_IN_STRRCHR:
>         case BUILT_IN_STRSTR:
>         case BUILT_IN_STPCPY:
>         case BUILT_IN_STPCPY_CHK:
>         case BUILT_IN_STPNCPY:
>         case BUILT_IN_STPNCPY_CHK:
>           argno = 0;
>           break;
> 
>         default:
>           return NULL_TREE;
>         }
>     }
> 
>   if (gimple_call_num_args (call) <= argno)
>     return NULL_TREE;
> 
>   return gimple_call_arg (call, argno);
> }
> 
> ```
> 
> Exposing this might be useful but it might also get abused incorrectly ...

I have a function which I'd like to be marked with it:


```
[[gnu::returns_derived_pointer(1)]]
char *
stpecpy(char p[], const char end[];
    char p[p ? end - p : 0], const char end[0], const char *restrict src)
{
        bool    trunc;
        char    *p;
        size_t  dsize, dlen, slen;

        if (dst == NULL)
                return NULL;

        dsize = end - dst;
        slen = strnlen(src, dsize);
        trunc = (slen == dsize);
        dlen = slen - trunc;

        p = stpcpy(mempcpy(dst, src, dlen), "");
        if (trunc) {
                errno = E2BIG;
                return NULL;
        }

        return p;
}
```

This function is to be used like this:

```
#define endof(a)  (&a[countof(a)])

char  buf[1024];
char  *p, *e;

p = buf;
e = endof(buf);

p = stpecpy(p, e, "foo");
p = stpecpy(p, e, "bar");
p = stpecpy(p, e, "baz");
if (p == NULL)
    goto fail;
```

Currently, the compiler is blind to this function.  It can't know the
relationship between p and e.

If the compiler knew that p is always derived from the original p, it would
also know that 'e' is always >=p, regardless of the value of p.  This would
improve static analysis.

I think this would be necessary for a future where buffer overflows are
impossible in C.

Reply via email to