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

--- Comment #9 from Alejandro Colomar <[email protected]> ---
(In reply to Alejandro Colomar from comment #6)
> (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)

D'oh.  Paste-and-edit issues.  The p in the prototype should be 'dst'.

> {
>       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