User account creation filtered due to spam.

Bug 34710 - FORTIFY_SOURCE matches to many patterns
Summary: FORTIFY_SOURCE matches to many patterns
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.1.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-01-07 23:40 UTC by Stefan Brüns
Modified: 2008-02-09 01:41 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan Brüns 2008-01-07 23:40:04 UTC
The following is a short code fragment similar to code to be found in the open source Argyll CMS (http://www.argyllcms.com/)
---
#include <stdio.h>

struct _iFile {
        int (*fprintf)(struct _iFile *p, const char *format, ...);
};

typedef struct _iFile iFile;

static int testprint(iFile *p, const char *format, ...) { };

int main(int argc, char* argv[]) {
        iFile p;

        p.fprintf = testprint;
        p.fprintf(&p, "%i", 123);
}
-----
gcc -D_FORTIFY_SOURCE=2 -O2  test.c -E | tail
-----
typedef struct _iFile iFile;

static int testprint(iFile *p, const char *format, ...) { };

int main(int argc, char* argv[]) {
 iFile p;

 p.fprintf = testprint;
 p.__fprintf_chk (&p, 2 - 1, "%i", 123);
}
-----
The second to last line is clearly wrong (or at least unintended)
Comment 1 Andrew Pinski 2008-01-07 23:46:12 UTC
Two things, fprintf is valid as being done as a macro and second thing is that this is a glibc issue and not a GCC issue as you are using a define and GCC just includes the header file.
Comment 2 Steven Bosscher 2008-01-08 08:37:54 UTC
Let's bring this problem to Jakub's attention...
Comment 3 Jakub Jelinek 2008-01-08 08:46:07 UTC
Just have to agree with Andrew, the code is buggy, fprintf etc. really are allowed to be defined as macros.  That said, glibc 2.7 and later when used with
gcc 4.3 and later uses inline functions instead of macros even for fprintf etc.
With older gccs that's not possible, as it lacks __builtin_va_arg_pack{,_len}
builtins.
Comment 4 Jakub Jelinek 2008-01-08 08:49:26 UTC
The easiest fix is to use (p.fprintf)(&p, "%i", 123); instead of
p.fprintf(&p, "%i", 123); whenever using some identifier which POSIX allows to
be defined as function-like macro, BTW.
Comment 5 GraemeGill 2008-02-09 00:04:27 UTC
The code is not "buggy". printf and fprintf are not reserved words, and
occupy a separate namespace with regard to the structure name and any
global function names. Because macros are a pre-process and don't understand
the language syntax, they don't respect the difference in namespace
and are therefore inherently dangerous and not guaranteed to work as
a mechanism to change the number of arguments to a function.

Ideally FORTIFY_SOURCE should use some other mechanism
that does respect the name spaces.
Comment 6 Andreas Schwab 2008-02-09 00:20:37 UTC
As soon as <stdio.h> is included fprintf becomes reserved as a function like macro.  That is independent of _FORTIFY_SOURCE, and is true for every function defined in the standard C libaray.
Comment 7 Andrew Pinski 2008-02-09 00:21:52 UTC
(In reply to comment #5)
> The code is not "buggy". printf and fprintf are not reserved words, and
> occupy a separate namespace with regard to the structure name and any
> global function names. 

No they can be function macros if you include stdio.h, please read the standard.

From C99 (7.1.4/1):
Any function declared in a header may be additionally implemented as a function-likemacro defined in the header, so if a library function is declared explicitly when its header is included, one 
of the techniques shown belowcan be used to ensure the declaration is not affected by 
such a macro.


So you can do:

        p.(fprintf)(&p, "%i", 123);

or
#undef fprintf after including stdio.h.
Comment 8 GraemeGill 2008-02-09 01:37:49 UTC
I've read this section of the standard, and don't see that
it is applicable. "Any function declared in a header may be additionally
implemented as a function-like macro defined in the header, so if a
library function is declared explicitly when its header is included, one
of the techniques shown below can be used to ensure the declaration is
not affected by such a macro."

This isn't applicable, since I'm not explicitly declaring the library
function fprintf. What I'm declaring is my function (that happens to
be called fprintf) as a member of a structure. They are two distinct
names and functions in different scopes.

The problem is that the function-like macro is being (wrongly) substituted
for something that isn't the library function declared in the header.

To claim that including a header makes all the identifiers in that
header reserved words for everything is simply unworkable I think.
Why is a #include file special code that doesn't obey the language scoping
rules ? Modern systems may have countless thousands of identifiers in their
headers, so how can anyone sitting down to do some programming avoid
using any of them for anything, including what are normally
private scope identifiers such as structure member names ?
This is exactly the opposite of modularization and information hiding!
Comment 9 Andrew Pinski 2008-02-09 01:41:56 UTC
(In reply to comment #8)
> I've read this section of the standard, and don't see that
> it is applicable. "Any function declared in a header may be additionally
> implemented as a function-like macro defined in the header, so if a
> library function is declared explicitly when its header is included, one
> of the techniques shown below can be used to ensure the declaration is
> not affected by such a macro."

Huh???  Look, fprintf becomes a function like macro, you use it was a function like macro when you do:
        p.fprintf(&p, "%i", 123);


So Guess what the preprocessor happens before the rest of the processing so you end up with the macro function substation and you get the incorrect result you wantted.  so again there is no issue inside GCC.