From 56bb8c450c1d1bab8369dc9f53746fe921d3b0ce Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 26 Mar 2026 00:23:30 +0100 Subject: [PATCH] Remove unsafe dead code (CVE-2025-56005) from the bundled ply --- python-pycparser.spec | 3 + remove-ply-unsafe-pickle-code.patch | 138 ++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 remove-ply-unsafe-pickle-code.patch diff --git a/python-pycparser.spec b/python-pycparser.spec index 38973f3..8d55a90 100644 --- a/python-pycparser.spec +++ b/python-pycparser.spec @@ -13,6 +13,9 @@ URL: http://github.com/eliben/pycparser Source0: %{url}/archive/release_v%{version}.tar.gz Source1: pycparser-0.91.1-remove-relative-sys-path.py +# Remove unsafe dead code (CVE-2025-56005) from the bundled ply +Patch: remove-ply-unsafe-pickle-code.patch + BuildArch: noarch BuildRequires: python3-devel diff --git a/remove-ply-unsafe-pickle-code.patch b/remove-ply-unsafe-pickle-code.patch new file mode 100644 index 0000000..79f77b4 --- /dev/null +++ b/remove-ply-unsafe-pickle-code.patch @@ -0,0 +1,138 @@ +From a8e7cb61ccd5773c390b69112c24cbb6a20ec63c Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Thu, 26 Mar 2026 00:19:40 +0100 +Subject: [PATCH] Remove unsafe pickle code from bundled ply (CVE-2025-56005) + +--- + pycparser/ply/yacc.py | 73 ++----------------------------------------- + 1 file changed, 2 insertions(+), 71 deletions(-) + +diff --git a/pycparser/ply/yacc.py b/pycparser/ply/yacc.py +index 20b4f28..6b38a30 100644 +--- a/pycparser/ply/yacc.py ++++ b/pycparser/ply/yacc.py +@@ -90,8 +90,6 @@ yaccdevel = False # Set to True if developing yacc. This turns off + + resultlimit = 40 # Size limit of results when running in debug mode. + +-pickle_protocol = 0 # Protocol to use when writing pickle files +- + # String type-checking compatibility + if sys.version_info[0] < 3: + string_types = basestring +@@ -1995,33 +1993,6 @@ class LRTable(object): + self.lr_method = parsetab._lr_method + return parsetab._lr_signature + +- def read_pickle(self, filename): +- try: +- import cPickle as pickle +- except ImportError: +- import pickle +- +- if not os.path.exists(filename): +- raise ImportError +- +- in_f = open(filename, 'rb') +- +- tabversion = pickle.load(in_f) +- if tabversion != __tabversion__: +- raise VersionError('yacc table file version is out of date') +- self.lr_method = pickle.load(in_f) +- signature = pickle.load(in_f) +- self.lr_action = pickle.load(in_f) +- self.lr_goto = pickle.load(in_f) +- productions = pickle.load(in_f) +- +- self.lr_productions = [] +- for p in productions: +- self.lr_productions.append(MiniProduction(*p)) +- +- in_f.close() +- return signature +- + # Bind all production function names to callable objects in pdict + def bind_callables(self, pdict): + for p in self.lr_productions: +@@ -2839,32 +2810,6 @@ del _lr_goto_items + raise + + +- # ----------------------------------------------------------------------------- +- # pickle_table() +- # +- # This function pickles the LR parsing tables to a supplied file object +- # ----------------------------------------------------------------------------- +- +- def pickle_table(self, filename, signature=''): +- try: +- import cPickle as pickle +- except ImportError: +- import pickle +- with open(filename, 'wb') as outf: +- pickle.dump(__tabversion__, outf, pickle_protocol) +- pickle.dump(self.lr_method, outf, pickle_protocol) +- pickle.dump(signature, outf, pickle_protocol) +- pickle.dump(self.lr_action, outf, pickle_protocol) +- pickle.dump(self.lr_goto, outf, pickle_protocol) +- +- outp = [] +- for p in self.lr_productions: +- if p.func: +- outp.append((p.str, p.name, p.len, p.func, os.path.basename(p.file), p.line)) +- else: +- outp.append((str(p), p.name, p.len, None, None, None)) +- pickle.dump(outp, outf, pickle_protocol) +- + # ----------------------------------------------------------------------------- + # === INTROSPECTION === + # +@@ -3213,7 +3158,7 @@ class ParserReflect(object): + + def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None, + check_recursion=True, optimize=False, write_tables=True, debugfile=debug_file, +- outputdir=None, debuglog=None, errorlog=None, picklefile=None): ++ outputdir=None, debuglog=None, errorlog=None): + + if tabmodule is None: + tabmodule = tab_module +@@ -3221,10 +3166,6 @@ def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, star + # Reference to the parsing method of the last built parser + global parse + +- # If pickling is enabled, table files are not created +- if picklefile: +- write_tables = 0 +- + if errorlog is None: + errorlog = PlyLogger(sys.stderr) + +@@ -3281,10 +3222,7 @@ def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, star + # Read the tables + try: + lr = LRTable() +- if picklefile: +- read_signature = lr.read_pickle(picklefile) +- else: +- read_signature = lr.read_table(tabmodule) ++ read_signature = lr.read_table(tabmodule) + if optimize or (read_signature == signature): + try: + lr.bind_callables(pinfo.pdict) +@@ -3479,13 +3417,6 @@ def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, star + except IOError as e: + errorlog.warning("Couldn't create %r. %s" % (tabmodule, e)) + +- # Write a pickled version of the tables +- if picklefile: +- try: +- lr.pickle_table(picklefile, signature) +- except IOError as e: +- errorlog.warning("Couldn't create %r. %s" % (picklefile, e)) +- + # Build the parser + lr.bind_callables(pinfo.pdict) + parser = LRParser(lr, pinfo.error_func) +-- +2.53.0 +