[tz] Minor (unimportant really) technical UB bug in strftime() ?

Yann Droneaud ydroneaud at opteya.com
Thu Nov 10 08:32:07 UTC 2022


Hi,

Le 10/11/2022 à 01:28, Paul Eggert via tz a écrit :
> On 11/9/22 11:25, Tom Lane wrote:
>
>> So in the case in strftime(), Valgrind would only
>> complain if mktime() actually tried to use any fields that had not
>> been initialized by the caller of strftime().  Which is just what
>> one would want.
>
> True, and good point.  And I understand why Valgrind wants to delay 
> checking here: it wants to avoid false alarms in some programs. 
> Unfortunately Valgrind's delay in reporting is problematic, because 
> Valgrind sometimes neglects to report behavior that the C standard 
> says is undefined. For example:
>
>    $ cat t.c
>    int main (void) { int a, b=a; return b; }
>    $ gcc t.c
>    $ valgrind ./a.out
>    [no error is reported]
>

Here I'm getting:

$ valgrind ./a.out
==511562== Memcheck, a memory error detector
==511562== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==511562== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==511562== Command: ./a.out
==511562==
==511562== Syscall param exit_group(status) contains uninitialised byte(s)
==511562==    at 0x4955DF1: _Exit (_exit.c:30)
==511562==    by 0x48B1561: __run_exit_handlers (exit.c:136)
==511562==    by 0x48B161F: exit (exit.c:143)
==511562==    by 0x4896516: (below main) (libc_start_call_main.h:74)
==511562==
==511562==
==511562== HEAP SUMMARY:
==511562==     in use at exit: 0 bytes in 0 blocks
==511562==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==511562==
==511562== All heap blocks were freed -- no leaks are possible
==511562==
==511562== Use --track-origins=yes to see where uninitialised values come from
==511562== For lists of detected and suppressed errors, rerun with: -s
==511562== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

> Conversely, as my previous email showed, Valgrind sometimes reports 
> behavior that I think is a program failure that should be fixed, but 
> the C standard says is well-defined behavior. Although Valgrind was 
> pickier in that email than the C standard really allows, I wish 
> Valgrind were a bit pickier still and reported each use of an 
> uninitialized variable when it happens and not optionally later (by 
> then, it may be difficult to debug), and I'd like tzcode to work with 
> such a Valgrind-like system.


With --track-origins=yes :

$ valgrind --track-origins=yes ./a.out
==511667== Memcheck, a memory error detector
==511667== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==511667== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==511667== Command: ./a.out
==511667==
==511667== Syscall param exit_group(status) contains uninitialised byte(s)
==511667==    at 0x4955DF1: _Exit (_exit.c:30)
==511667==    by 0x48B1561: __run_exit_handlers (exit.c:136)
==511667==    by 0x48B161F: exit (exit.c:143)
==511667==    by 0x4896516: (below main) (libc_start_call_main.h:74)
==511667==  Uninitialised value was created by a stack allocation
==511667==    at 0x109129: main (in /home/ydroneaud/src/test/a.out)
==511667==
==511667==
==511667== HEAP SUMMARY:
==511667==     in use at exit: 0 bytes in 0 blocks
==511667==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==511667==
==511667== All heap blocks were freed -- no leaks are possible
==511667==
==511667== For lists of detected and suppressed errors, rerun with: -s
==511667== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)


Using UBSan and MSan (requires clang) instead of valgrind would catch this too:

$ clang -fsanitize=undefined,memory -fsanitize-memory-track-origins=2 -g t.c
$ ./a.out
==511862==WARNING: MemorySanitizer: use-of-uninitialized-value
     #0 0x55a79df79b35 in main .../t.c:1:31
     #1 0x7f686dc2350f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
     #2 0x7f686dc235c8 in __libc_start_main csu/../csu/libc-start.c:381:3
     #3 0x55a79def3294 in _start (.../a.out+0x1e294) (BuildId: 576806214712a462122845f7fa09af26e1237aee)

   Uninitialized value was stored to memory at
     #0 0x55a79df79adf in main .../t.c:1:26
     #1 0x7f686dc2350f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

   Uninitialized value was created by an allocation of 'a' in the stack frame of function 'main'
     #0 0x55a79df799a0 in main .../t.c:1

SUMMARY: MemorySanitizer: use-of-uninitialized-value .../t.c:1:31 in main
Exiting

Regards.

-- 
Yann Droneaud
OPTEYA




More information about the tz mailing list