Bug 223165

Summary: Crash with pthread_condattr_destroy(NULL) on freebsd-11
Product: Base System Reporter: Rajendra <rajendra.sy>
Component: kernAssignee: freebsd-threads (Nobody) <threads>
Status: Closed Not A Bug    
Severity: Affects Many People CC: cem, kib, markj, pstef
Priority: ---    
Version: 11.0-STABLE   
Hardware: amd64   
OS: Any   

Description Rajendra 2017-10-22 11:16:37 UTC
Below program crashes on FreeBSD-11.

$ cat test.c
#include <pthread.h>
int main(int argc, char *argv[]) {
        pthread_condattr_destroy(NULL);
        return 0;
}
$ clang -o test test.c -lpthread
test.c:3:31: warning: null passed to a callee that requires a non-null argument [-Wnonnull]
        pthread_condattr_destroy(NULL);
                                 ~~~~^
1 warning generated.

syrajendra@[bm64-fbsd11] # ./test
Segmentation fault (core dumped)


The "pthread_condattr_destroy" has a argument which has _Nonnull quilifier but the function implementation properly handles the NULL value by returning "EINVAL" if argument is NULL.
Comment 1 Conrad Meyer freebsd_committer freebsd_triage 2017-10-22 17:10:40 UTC
Does not seem to affect CURRENT, FWIW.
Comment 2 Konstantin Belousov freebsd_committer freebsd_triage 2017-10-25 07:52:55 UTC
(In reply to Conrad Meyer from comment #1)
The SUSv7tc2 description of the function explicitely says that the behavior is undefined if the function is passed not a pointer to the previously initialized condattr object.  So the internal acceptance of NULL does not really matter much there.

Also, I am not sure why do you get SIGSEGV.
Comment 3 Mark Johnston freebsd_committer freebsd_triage 2017-10-25 15:34:15 UTC
clang will in some cases optimize away null checks of parameters qualified with _Nonnull. It doesn't seem to have done that in a libthr built with clang 5.0:

0000000000008cf0 <_pthread_condattr_destroy>:
    8cf0:       55                      push   %rbp
    8cf1:       48 89 e5                mov    %rsp,%rbp
    8cf4:       53                      push   %rbx
    8cf5:       50                      push   %rax
    8cf6:       48 89 fb                mov    %rdi,%rbx
    8cf9:       b8 16 00 00 00          mov    $0x16,%eax
    8cfe:       48 85 db                test   %rbx,%rbx
    8d01:       74 16                   je     8d19 <_pthread_condattr_destroy+0x29>
    ...

... but I've seen it do that a number of times in Isilon OneFS. With 3.9.1 we have:

0000000000008de0 <_pthread_condattr_destroy>:
    8de0:       55                      push   %rbp
    8de1:       48 89 e5                mov    %rsp,%rbp
    8de4:       53                      push   %rbx
    8de5:       50                      push   %rax
    8de6:       48 89 fb                mov    %rdi,%rbx
    8de9:       48 8b 3b                mov    (%rbx),%rdi
    8dec:       b8 16 00 00 00          mov    $0x16,%eax
    8df1:       48 85 ff                test   %rdi,%rdi
    ...

I don't think that there's a bug here in light of comment 2.