From aa9ec0c27a878e4d12bea08a05a7c31bd93a1242 Mon Sep 17 00:00:00 2001 From: Mauro Amico Date: Mon, 23 Feb 2026 00:11:40 +0100 Subject: [PATCH 1/4] prevent builtin shadowing in DTML --- src/DocumentTemplate/DT_Util.py | 3 +++ src/DocumentTemplate/tests/testDTML.py | 32 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/DocumentTemplate/DT_Util.py b/src/DocumentTemplate/DT_Util.py index 9b43eb2..029d2d3 100644 --- a/src/DocumentTemplate/DT_Util.py +++ b/src/DocumentTemplate/DT_Util.py @@ -204,6 +204,9 @@ def eval(self, md): d.update(self.globals) for name in self.used: __traceback_info__ = name + # Don't try to override builtins, since they need to be protected + if d["__builtins__"] and name in d["__builtins__"]: + continue try: if name not in d: d[name] = md.getitem(name, 0) diff --git a/src/DocumentTemplate/tests/testDTML.py b/src/DocumentTemplate/tests/testDTML.py index ab8ee11..d1ff24f 100644 --- a/src/DocumentTemplate/tests/testDTML.py +++ b/src/DocumentTemplate/tests/testDTML.py @@ -408,6 +408,38 @@ def y(self): ''')(i=C()) self.assertEqual(res, expected) + def test_subitem_with_builtins_names(self): + # Test builtins names shadowing + import Acquisition + from ExtensionClass import Base + + class C(Base, Acquisition.Implicit): + __allow_access_to_unprotected_subobjects__ = 1 + + def __init__(self, x): + self.x = x + + def __call__(self, *args, **kwargs): + return f"rendering: {self.x}" + + foo = C("foo") + foo.str = bar = C("bar") + expected = ( + ''' + foo, + foo, + bar, + rendering: foo, + rendering: bar''') + res = self.doc_class( + ''' + , + , + , + , + ''')(**{"foo": foo, "str": bar}) + self.assertEqual(res, expected) + def testWith(self): class person: __allow_access_to_unprotected_subobjects__ = 1 From 72ca15da65bb894d75dd5618f6b5c8c0bfa1859d Mon Sep 17 00:00:00 2001 From: Mauro Amico Date: Mon, 23 Feb 2026 00:25:58 +0100 Subject: [PATCH 2/4] changelog --- CHANGES.rst | 2 ++ src/DocumentTemplate/tests/testDTML.py | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 1ea6f62..57e6426 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,8 @@ Changelog 5.2 (unreleased) ---------------- +- Prevent builtins shadowing in DTML Var. + 5.1 (2026-01-19) ---------------- diff --git a/src/DocumentTemplate/tests/testDTML.py b/src/DocumentTemplate/tests/testDTML.py index d1ff24f..3596034 100644 --- a/src/DocumentTemplate/tests/testDTML.py +++ b/src/DocumentTemplate/tests/testDTML.py @@ -422,22 +422,30 @@ def __init__(self, x): def __call__(self, *args, **kwargs): return f"rendering: {self.x}" + def __len__(self): + return len(self.x) + foo = C("foo") foo.str = bar = C("bar") + foo.len = baz = C("baz") expected = ( ''' foo, foo, bar, rendering: foo, - rendering: bar''') + rendering: bar, + 3, + rendering: baz''') res = self.doc_class( ''' , , , , - ''')(**{"foo": foo, "str": bar}) + , + , + ''')(**{"foo": foo, "str": bar, "len": baz}) self.assertEqual(res, expected) def testWith(self): From 7492faf2484f03d9e44c6ab16e506e344e8ba34f Mon Sep 17 00:00:00 2001 From: Mauro Amico Date: Mon, 23 Feb 2026 00:29:06 +0100 Subject: [PATCH 3/4] missing builtins ? --- src/DocumentTemplate/DT_Util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DocumentTemplate/DT_Util.py b/src/DocumentTemplate/DT_Util.py index 029d2d3..63ebbc9 100644 --- a/src/DocumentTemplate/DT_Util.py +++ b/src/DocumentTemplate/DT_Util.py @@ -205,7 +205,7 @@ def eval(self, md): for name in self.used: __traceback_info__ = name # Don't try to override builtins, since they need to be protected - if d["__builtins__"] and name in d["__builtins__"]: + if d.get("__builtins__") and name in d["__builtins__"]: continue try: if name not in d: From 57a29bf6dac568ee481984aee0e9a951972461bb Mon Sep 17 00:00:00 2001 From: Mauro Amico Date: Mon, 23 Feb 2026 11:52:26 +0100 Subject: [PATCH 4/4] Update CHANGES.rst Co-authored-by: Jens Vagelpohl --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 57e6426..cc45628 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,7 @@ Changelog ---------------- - Prevent builtins shadowing in DTML Var. + (`Zope#1285 `_) 5.1 (2026-01-19)