bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Possible non-compliance of the restrict keyword contract in coreutils/to


From: Tim Lange
Subject: Possible non-compliance of the restrict keyword contract in coreutils/touch.c
Date: Wed, 27 Jul 2022 10:21:54 +0200

Hi everyone,

I'm currently working on new warnings for gcc's -fanalyzer. I've
implemented a version of Wrestrict inside the analyzer, using its
region model to detect more cases of overlapping buffers in memcpy and
aliases to restrict-qualified parameters. While testing my new warning,
I got one result on the gnu coreutils touch.c file [1].
See the output below:

../src/touch.c: In function 'get_reldate':
../src/touch.c:115:9: warning: argument passed to 'restrict'-qualified 
parameter aliases with another argument [-Wanalyzer-restrict]
  115 |   if (! parse_datetime (result, flex_date, now))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  'main': events 1-8
    |
    |  261 | main (int argc, char **argv)
    |      | ^~~~
    |      | |
    |      | (1) entry to 'mai
    |......
    |  279 |   while ((c = getopt_long (argc, argv, "acd:fhmr:t:", longopts, 
NULL)) != -1)
    |      |          
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                                                                    
    |
    |      |                                                                    
    (2) following 'true' branch (when 'c != -1')...
    |  280 |     {
    |  281 |       switch (c)
    |      |       ~~~~~~
    |      |       |
    |      |       (3) ...to here
    |......
    |  344 |   if (use_ref)
    |      |      ~
    |      |      |
    |      |      (4) following 'true' branch...
    |......
    |  349 |       if (no_dereference ? lstat (ref_file, &ref_stats)
    |      |          ~               ~
    |      |          |               |
    |      |          |               (5) ...to here
    |      |          (6) following 'false' branch...
    |......
    |  353 |       newtime[0] = get_stat_atime (&ref_stats);
    |      |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                    |
    |      |                    (7) ...to here
    |......
    |  356 |       if (flex_date)
    |      |          ~
    |      |          |
    |      |          (8) following 'true' branch (when 'flex_date' is 
non-NULL)...
    |
  'main': events 9-12
    |
    |  358 |           if (change_times & CH_ATIME)
    |      |              ~             ^
    |      |              |             |
    |      |              |             (9) ...to here
    |      |              (10) following 'true' branch...
    |  359 |             get_reldate (&newtime[0], flex_date, &newtime[0]);
    |      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |             |
    |      |             (11) ...to here
    |      |             (12) calling 'get_reldate' from 'main'
    |
    +--> 'get_reldate': events 13-14
           |
           |  112 | get_reldate (struct timespec *result,
           |      | ^~~~~~~~~~~
           |      | |
           |      | (13) entry to 'get_reldate'
           |......
           |  115 |   if (! parse_datetime (result, flex_date, now))
           |      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           |      |         |
           |      |         (14) 'result' and 'now' point to the same memory 
location
           |
In file included from ../src/touch.c:31:
../lib/parse-datetime.h:22:6: note: declared here
   22 | bool parse_datetime (struct timespec *restrict,
      |      ^~~~~~~~~~~~~~

My (and David's) understanding of the restrict keyword is that any read
or write to the memory location must occur through the restrict-qualified
parameter. In the case of 'parse_datetime' from gnulib, 'result' is an
output parameter, thus the function might write to 'result' before reading
'now' [2].

I'm a bit unsure, due to the bulky definition of restrict, whether this
is actually a true positive and does express what gnulib intended with
the change. So I'd like to hear your opinions on this.

- Tim

[1] 
https://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/touch.c;h=21c247d0b10eedb615bf044ba6ea08520f3d0546;hb=HEAD#l359
[2] The function does write 'result' after the last read of 'now' and
    does not use restrict in the implementation, so it should be safe
    but is still somewhat undefined behavior?



reply via email to

[Prev in Thread] Current Thread [Next in Thread]