Bug 1074940

Summary: Autogenerated aoGetsText() function has to be marked with __attribute__ ((format_arg(1)))
Product: [Fedora] Fedora Reporter: Petr Pisar <ppisar>
Component: autogenAssignee: Miroslav Lichvar <mlichvar>
Status: CLOSED RAWHIDE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: rawhideCC: bkorb, green, mlichvar
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
URL: http://thread.gmane.org/gmane.comp.gnu.utils.bugs/18126
Whiteboard:
Fixed In Version: autogen-5.18.3-1.fc21 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2014-05-27 14:08:17 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1074912    

Description Petr Pisar 2014-03-11 09:26:45 UTC
Fedora enabled -Werror=format-security which broke building sharutils because sharutils sources come with pregenerated libopts code <http://thread.gmane.org/gmane.comp.gnu.utils.bugs/18126>, bug #1037323.

I fixed the issue by patching the generated header this way:

--- a/src/shar-opts.h
+++ b/src/shar-opts.h
@@ -373,6 +373,7 @@ extern tOptions sharOptions;
 #     include <libintl.h>
 #   endif
 
+static inline char* aoGetsText(char const* pz) __attribute__ ((format_arg(1)));
 static inline char* aoGetsText(char const* pz) {
     if (pz == NULL) return NULL;
     return (char*)gettext(pz);

This is in line with gettext(3) which is marked the same way.

Now I decided to unbundle the libopts because patching messages printed by libopts is a nightmare (bug #1074912). Thus I need to fix autogen.

I can see in the autogen sources:

petr@dhcp-0-146:~/fedora/autogen/autogen-5.18.2 $ grep -Hnr aoGetsText
autoopts/genshell.h:170:static inline char* aoGetsText(char const* pz) {
autoopts/genshell.h:174:#   define _(s)  aoGetsText(s)
autoopts/tpl/opthead.tlib:668:static inline char* aoGetsText(char const* pz) {
autoopts/tpl/opthead.tlib:672:#   define _(s)  aoGetsText(s)

So I guess you one of the locations has be patched.

If you are not interested in this issue, I can develop the fix the commit it into Fedora.

Comment 1 Miroslav Lichvar 2014-03-11 09:54:53 UTC
CCing upstream maintainer.

Comment 2 Bruce Korb 2014-03-12 00:06:04 UTC
"genshell.h" is a derived file that you are not using.

Obviously, I cannot just put the __attribute__ string
into the template file.  I have to do something like:

#ifndef ATTRIBUTE
#define ATTRIBUTE(_a)
#endif
static inline char* aoGetsText(char const* pz)
   ATTRIBUTE((format_arg(1))) {

but I do not know the conventional spelling of the
attribute wrapper macro.

Comment 3 Petr Pisar 2014-03-12 08:43:09 UTC
See GCC texinfo page (info gcc 'C Extensions' 'Attribute Syntax').

Comment 4 Bruce Korb 2014-03-14 00:09:46 UTC
Doing it for GCC is not the issue.  The problem is that the generated code needs to be compilable with other compilers that may not be using GCC's conventions.  Therefore, it must be macro-wrapped in some way.  e.g.

#ifdef __GNUC__
#define ATTRIBUTE(_a) __attribute__(_a)
#else
#define ATTRIBUTE(_a)
#endif

So my question to you is, "How would you like that wrapped?"

I will not emit all of that in the code.  I am willing to emit
the "#ifndef" variation in comment #2.  How would you like
the attribute wrapper spelled?


Thanks!

Comment 5 Miroslav Lichvar 2014-03-26 16:23:13 UTC
How about GNUC_ATTRIBUTE?

Comment 6 Miroslav Lichvar 2014-03-26 16:36:33 UTC
After some googling, it seems to me the convention is to define __attribute__() as a macro expanding to nothing with non-gcc compilers.

Comment 7 Bruce Korb 2014-03-29 18:52:55 UTC
The new template will now produce the following code:


    # ifndef __attribute__
    #   define __attribute__(_a)
    # endif

    static inline char* aoGetsText(char const* pz) __attribute__ ((format_arg(1)));
    static inline char* aoGetsText(char const* pz) {
        if (pz == NULL) return NULL;
        return (char*)gettext(pz);
    }

Comment 8 Bruce Korb 2014-03-29 18:54:37 UTC
P.S. "Thank you!" :)

Comment 10 Miroslav Lichvar 2014-04-01 13:36:29 UTC
(In reply to Bruce Korb from comment #7)
> The new template will now produce the following code:
>
>     # ifndef __attribute__
>     #   define __attribute__(_a)
>     # endif

Hm, so the applications are now expected to define __attribute__ with gcc?

Comment 11 Bruce Korb 2014-04-04 15:52:58 UTC
Your original suggestion of just using __attribute__ would have required defining it for all compilers other than GNU.  The _Noreturn attribute I can get from gnulib.  The format attribute is not available via gnulib.  Probably the best thing is an autoconf feature test that yields some wrapper macro.  Unfortunately, this is just a play time activity and I am neck deep in a start up.  Play time is limited.  Please make a suggestion soon because I hope to make a release this weekend.  Thank you for your help!  Regards, Bruce

Comment 12 Petr Pisar 2014-04-08 13:49:28 UTC
What about?


#if !defined(__GNUC__)
#define __attribute__(a)
#endif

static inline char* aoGetsText(char const* pz) __attribute__ ((format_arg(1)));


I could track format_arg support to GCC 2.95.3. So I guess there is no need to constrain the definition with a specific GCC version.

Comment 13 Bruce Korb 2014-04-13 18:31:34 UTC
I got a short break.  The wrapper macro will be named ATTRIBUTE_FORMAT_ARG(_a):

>     AC_DEFUN([AG_COMPILE_FORMAT_ARG],[
>       AC_MSG_CHECKING([whether __attribute__((format_arg(n))) works])
>       AC_CACHE_VAL([ag_cv_compile_format_arg],[
>       AC_COMPILE_IFELSE(
>         AC_LANG_PROGRAM([@%:@include <stdio.h>
>     char const * foo(char const * fmt, int v)
>         __attribute__((format_arg(1)));],
>           [printf( foo("argc is %d\n", argc), argc);]),
>         [ag_cv_compile_format_arg=yes],
>         [ag_cv_compile_format_arg=no]
>       ) # end of AC_COMPILE_IFELSE
>       ]) # end of AC_CACHE_VAL for ag_cv_compile_format_arg
>       AC_MSG_RESULT([${ag_cv_compile_format_arg}])
>       if test "X${ag_cv_compile_format_arg}" != Xno
>       then
>         format_arg_expansion="__attribute__((format_arg(_a)))"
>       else
>         format_arg_expansion=""
>       fi
>         AC_DEFINE_UNQUOTED([ATTRIBUTE_FORMAT_ARG(_a)],
>     	[${format_arg_expansion}],
>     	[format_arg attribute wrapper])
>     ]) # end of AC_DEFUN of AG_COMPILE_FORMAT_ARG

Comment 14 Miroslav Lichvar 2014-05-27 14:08:17 UTC
autogen has been updated to 5.18.4. To fix the format warnings the applications need to define the ATTRIBUTE_FORMAT_ARG macro, it's not defined automatically.

FWIW, the AG_COMPILE_FORMAT_ARG test code doesn't seem to work correctly here as main is declared without argc.