bug-gnulib
[Top][All Lists]
Advanced

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

clang's __diagnose_if__ and glibc fortify


From: Bruno Haible
Subject: clang's __diagnose_if__ and glibc fortify
Date: Sun, 23 Aug 2020 15:46:50 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-186-generic; KDE/5.18.0; x86_64; ; )

Paul Eggert wrote:
>+      libc-config: avoid Clang’s __diagnose_if__
>+      * lib/cdefs.h (__warndecl, __warnattr, __errordecl):
>+      For now, do not use __diagnose_if__ here, as this fails
>+      on Fedora 31 with Clang 9.0.1, with diagnostic
>+      "/usr/include/bits/stdio2.h:263:9: error: fgets called with bigger
>+      size than length of destination buffer
>+      [-Werror,-Wuser-defined-warnings]".  I guess Clang 9 warns even
>+      for functions that are not called?

I can reproduce the redundant warnings, on Fedora 31 with Clang 9.0.1, when
applying the change to gnulib/lib/cdefs.h also to /usr/include/sys/cdefs.h.

With the attached program foo.c I get warnings for each of these inline
functions that conditionally invokes a *_chk_warn function.

Apparently, clang - unlike GCC - processes the body of the inline function
also when the inline function is never referenced.

It would be possible to silence these warnings by adding a gnulib module
as attached (clang-warnings.tar.gz).

BUT since the macros __warndecl and __warnattr are ONLY used by Fortify
inline functions - there are no other uses in the glibc headers, nor in gnulib -
and most of these uses produce redundant warnings, this is all pointless.

What matters for user code is that gnulib's "attribute.h" defines
ATTRIBUTE_WARNING and ATTRIBUTE_ERROR in a way that works with clang.

In order to use the clang __diagnose_if__ primitive, the Fortify inline
functions would need to be written in a different way. This has been done
in the Android header files. For example, here is the fgets function in
glibc - tailored for GCC -:

extern char *__REDIRECT (__fgets_chk_warn,
                         (char *__restrict __s, size_t __size, int __n,
                          FILE *__restrict __stream), __fgets_chk)
     __wur __warnattr ("fgets called with bigger size than length "
                       "of destination buffer");

__fortify_function __wur char *
fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
{
  if (__bos (__s) != (size_t) -1)
    {
      if (!__builtin_constant_p (__n) || __n <= 0)
        return __fgets_chk (__s, __bos (__s), __n, __stream);

      if ((size_t) __n > __bos (__s))
        return __fgets_chk_warn (__s, __bos (__s), __n, __stream);  // <=== 
line 263
    }
  return __fgets_alias (__s, __n, __stream);
}

and here it is in Android - tailored for clang -:

__BIONIC_FORTIFY_INLINE
char* fgets(char* const __pass_object_size dest, int size, FILE* stream)
        __overloadable
        __clang_error_if(size < 0, "in call to 'fgets', size should not be 
negative")
        __clang_error_if(size > __bos(dest),
                         "in call to 'fgets', size is larger than the 
destination buffer") {
    size_t bos = __bos(dest);

    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
        return __call_bypassing_fortify(fgets)(dest, size, stream);
    }

    return __fgets_chk(dest, size, stream, bos);
}


2020-08-23  Bruno Haible  <bruno@clisp.org>

        libc-config: Improve comments.
        * lib/cdefs.h (__warndecl, __warnattr, __errordecl): Explain why we
        cannot use clang's __diagnose_if__ here.

diff --git a/lib/cdefs.h b/lib/cdefs.h
index 32a2c40..1ae9ffc 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -148,7 +148,11 @@
 # define __warnattr(msg) __attribute__((__warning__ (msg)))
 # define __errordecl(name, msg) \
   extern void name (void) __attribute__((__error__ (msg)))
-#elif __glibc_clang_has_attribute (__diagnose_if__) && 0 /* fails on Fedora 31 
with Clang 9.  */
+#elif __glibc_clang_has_attribute (__diagnose_if__) && 0
+/* These definitions are not enabled, because they produce bogus warnings
+   in the glibc Fortify functions.  These functions are written in a style
+   that works with GCC.  In order to work with clang, these functions would
+   need to be modified.  */
 # define __warndecl(name, msg) \
   extern void name (void) __attribute__((__diagnose_if__ (1, msg, "warning")))
 # define __warnattr(msg) __attribute__((__diagnose_if__ (1, msg, "warning")))

Attachment: foo.c
Description: Text Data

Attachment: foo-warnings.txt
Description: Text document

Attachment: clang-warnings.tar.gz
Description: application/compressed-tar


reply via email to

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