Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ the `master` branch.

## Reporting a Vulnerability

To report a security issue, please disclose it at [security advisory](https://github.com/eliben/pycparser/security/advisories/new).
We don't consider pycparser to be a project suitable to be used at a security
boundary. Please don't use it as such.

We will respond within 14 working days of your submission. If the issue is confirmed as a vulnerability, we will open a Security Advisory and acknowledge your contributions as part of it. This project follows a 90 day disclosure timeline.
If you found what you believe to be a security issue with pycparser, feel free
to open a public GitHub issue or email the project's maintainer.
3 changes: 3 additions & 0 deletions pycparser/_c_ast.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ FileAST: [ext**]
#
For: [init*, cond*, next*, stmt*]

GenericSelection: [expr*, assoc_list**]
GenericAssociation: [type*, expr*]

# name: Id
# args: ExprList
#
Expand Down
30 changes: 30 additions & 0 deletions pycparser/c_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1128,3 +1128,33 @@ def __iter__(self):

attr_names = ('string', )

class GenericAssociation(Node):
__slots__ = ('type', 'expr', 'coord', '__weakref__')
def __init__(self, type, expr, coord=None):
self.type = type
self.expr = expr
self.coord = coord

def children(self):
nodelist = []
if self.type is not None: nodelist.append(("type", self.type))
if self.expr is not None: nodelist.append(("expr", self.expr))
return tuple(nodelist)

attr_names = ()

class GenericSelection(Node):
__slots__ = ('expr', 'assoc_list', 'coord', '__weakref__')
def __init__(self, expr, assoc_list, coord=None):
self.expr = expr
self.assoc_list = assoc_list
self.coord = coord

def children(self):
nodelist = []
if self.expr is not None: nodelist.append(("expr", self.expr))
for i, child in enumerate(self.assoc_list or []):
nodelist.append(("assoc_list[%d]" % i, child))
return tuple(nodelist)

attr_names = ()
1 change: 1 addition & 0 deletions pycparser/c_lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def _make_tok_location(self, token):
'_NORETURN', '_THREAD_LOCAL', '_STATIC_ASSERT',
'_ATOMIC', '_ALIGNOF', '_ALIGNAS',
'_PRAGMA',
'_GENERIC',
)

keyword_map = {}
Expand Down
24 changes: 24 additions & 0 deletions pycparser/c_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1835,6 +1835,30 @@ def p_primary_expression_5(self, p):
p[0] = c_ast.FuncCall(c_ast.ID(p[1], coord),
c_ast.ExprList([p[3], p[5]], coord),
coord)

def p_primary_expression_6(self, p):
""" primary_expression : generic_selection """
p[0] = p[1]

def p_generic_selection(self, p):
""" generic_selection : _GENERIC LPAREN assignment_expression COMMA generic_assoc_list RPAREN """
p[0] = c_ast.GenericSelection(p[3], p[5], self._token_coord(p, 1))

def p_generic_assoc_list_1(self, p):
""" generic_assoc_list : generic_association """
p[0] = [p[1]]

def p_generic_assoc_list_2(self, p):
""" generic_assoc_list : generic_assoc_list COMMA generic_association """
p[0] = p[1] + [p[3]]

def p_generic_association_1(self, p):
""" generic_association : type_name COLON assignment_expression """
p[0] = c_ast.GenericAssociation(p[1], p[3], p[1].coord)

def p_generic_association_2(self, p):
""" generic_association : DEFAULT COLON assignment_expression """
p[0] = c_ast.GenericAssociation(None, p[3], self._token_coord(p, 1))

def p_offsetof_member_designator(self, p):
""" offsetof_member_designator : identifier
Expand Down