genksyms: Duplicate function pointer type definitions segfault

I noticed that genksyms will segfault when it sees duplicate function
pointer type declaration when I placed the same function pointer
definition in two separate headers in a local branch as an intermediate
step of some refactoring. This can be reproduced by piping the following
minimal test case into `genksyms -r /dev/null` or alternatively, putting
it into a C file attempting a build:

typedef int (*f)();
typedef int (*f)();

Attaching gdb to genksyms to understand this failure is useless without
changing CFLAGS to emit debuginfo. Once you have debuginfo, you will
find that the failure is that `char *s` was NULL and the program
executed `while(*s)`. At which point, further debugging requires
familiarity with compiler front end / parser development.

What happens is that flex identifies the first instance of the token "f"
as IDENT and the yacc parser adds it to the symbol table. On the second
instance, flex will identify "f" as TYPE, which triggers an error case
in the yacc parser. Given that TYPE would have been IDENT had it not
been in the symbol table, the the segmentaion fault could be avoided by
treating TYPE as IDENT in the affected rule.

Some might consider placing identical function pointer type declarations
in different headers to be poor style might consider a failure to be
beneficial. However, failing through a segmentation fault makes the
cause non-obvious and can waste the time of anyone who encounters it.

Signed-off-by: Richard Yao <richard.yao@clusterhq.com>
Acked-by: Madhuri Yechuri <madhuriyechuri@clusterhq.com>
Signed-off-by: Michal Marek <mmarek@suse.com>
This commit is contained in:
Richard Yao 2015-07-20 19:52:48 -04:00 committed by Michal Marek
parent 9bebe9e5b0
commit 1c722503fa
1 changed files with 9 additions and 0 deletions

View File

@ -303,6 +303,15 @@ direct_declarator:
$$ = $1;
}
}
| TYPE
{ if (current_name != NULL) {
error_with_pos("unexpected second declaration name");
YYERROR;
} else {
current_name = (*$1)->string;
$$ = $1;
}
}
| direct_declarator '(' parameter_declaration_clause ')'
{ $$ = $4; }
| direct_declarator '(' error ')'