mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-09-22 11:00:49 +00:00
python3-simpleeval: Fix CVE-2026-32640
Manually backport the three upstream security fixes for CVE-2026-32640 to the Scarthgap simpleeval 0.9.13 recipe [1][2][3]. Include the required unhashable-container correction [4], which prevents the recursive security checks from raising TypeError on legitimate list and tuple values. Harden the recursive callback-argument validation to inspect sets, frozensets, and dictionary keys, and safely handle cyclic containers. Add regression coverage for each of these cases. Do not include the separate generator/coroutine hardening or the optional performance follow-up. Omit the new ModuleWrapper API so this stable-branch fix adds no unrelated public feature. [1] https://github.com/danthedeckie/simpleeval/commit/9cb4a7b99498 [2] https://github.com/danthedeckie/simpleeval/commit/1654cbf02193 [3] https://github.com/danthedeckie/simpleeval/commit/cffa9f68cee5 [4] https://github.com/danthedeckie/simpleeval/commit/d1e4569db678 Signed-off-by: Hetvi Thakar <hthakar@cisco.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
From 42483617f1fd47c81bbf66c71c2ce5cbe2d3df29 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Fairhead <daniel@dev.ngo>
|
||||
Date: Fri, 13 Mar 2026 13:27:47 +0000
|
||||
Subject: [PATCH 4/4] Fix unhashable items inside tuples bug.
|
||||
|
||||
CVE: CVE-2026-32640
|
||||
Upstream-Status: Backport [https://github.com/danthedeckie/simpleeval/commit/d1e4569db678a3cb42b779f404aa203665d52ab0]
|
||||
|
||||
Backport Changes:
|
||||
- Omit the upstream 1.0.6 version metadata change and retain the 0.9.13 setuptools build configuration.
|
||||
- Remove the standalone Hashable import added by the preceding 0.9.13 backport while retaining the target Python compatibility flags.
|
||||
|
||||
(cherry picked from commit d1e4569db678a3cb42b779f404aa203665d52ab0)
|
||||
Signed-off-by: Hetvi Thakar <hthakar@cisco.com>
|
||||
---
|
||||
simpleeval.py | 16 +++++++++++++---
|
||||
test_simpleeval.py | 9 +++++++++
|
||||
2 files changed, 22 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/simpleeval.py b/simpleeval.py
|
||||
index 9f3003e..a6745db 100644
|
||||
--- a/simpleeval.py
|
||||
+++ b/simpleeval.py
|
||||
@@ -103,7 +103,6 @@ import sys
|
||||
import types
|
||||
import warnings
|
||||
from random import random
|
||||
-from typing import Hashable
|
||||
|
||||
PYTHON3 = sys.version_info[0] == 3
|
||||
PYTHON35 = PYTHON3 and sys.version_info > (3, 5)
|
||||
@@ -119,6 +118,17 @@ MAX_SHIFT_BASE = int(sys.float_info.max) # highest on left side of << or >>
|
||||
DISALLOW_PREFIXES = ["_", "func_"]
|
||||
DISALLOW_METHODS = ["format", "format_map", "mro"]
|
||||
|
||||
+########################################
|
||||
+# Tiny helpers:
|
||||
+
|
||||
+
|
||||
+def is_hashable(value):
|
||||
+ try:
|
||||
+ return hash(value)
|
||||
+ except TypeError:
|
||||
+ return False
|
||||
+
|
||||
+
|
||||
# Disallow functions:
|
||||
# This, strictly speaking, is not necessary. These /should/ never be accessable anyway,
|
||||
# if DISALLOW_PREFIXES and DISALLOW_METHODS are all right. This is here to try and help
|
||||
@@ -431,7 +441,7 @@ class SimpleEval(object): # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
if isinstance(item, types.ModuleType):
|
||||
raise FeatureNotAvailable("Sorry, modules are not allowed")
|
||||
- if isinstance(item, Hashable) and item in DISALLOW_FUNCTIONS:
|
||||
+ if is_hashable(item) and item in DISALLOW_FUNCTIONS:
|
||||
raise FeatureNotAvailable("This function is forbidden")
|
||||
|
||||
if not isinstance(item, (dict, list, tuple, set, frozenset)):
|
||||
@@ -657,7 +667,7 @@ class SimpleEval(object): # pylint: disable=too-few-public-methods
|
||||
if item is not _ATTR_NOT_FOUND:
|
||||
if isinstance(item, types.ModuleType):
|
||||
raise FeatureNotAvailable("Sorry, modules are not allowed in attribute access")
|
||||
- if isinstance(item, Hashable) and item in DISALLOW_FUNCTIONS:
|
||||
+ if is_hashable(item) and item in DISALLOW_FUNCTIONS:
|
||||
raise FeatureNotAvailable("This function is forbidden")
|
||||
return item
|
||||
|
||||
diff --git a/test_simpleeval.py b/test_simpleeval.py
|
||||
index f3c9a60..a654f6d 100644
|
||||
--- a/test_simpleeval.py
|
||||
+++ b/test_simpleeval.py
|
||||
@@ -347,6 +347,15 @@ class TestFunctions(DRYTest):
|
||||
self.t("foo(mult=2, to_return=4)", 8)
|
||||
self.t("foo(2, 10)", 20)
|
||||
|
||||
+ def test_function_with_list_args(self):
|
||||
+ # Regression test, makes sure we can pass lists (non-hashable) items as
|
||||
+ # kwargs to functions.
|
||||
+
|
||||
+ def func(*args, **kwargs):
|
||||
+ return 42
|
||||
+
|
||||
+ simple_eval("test(boo=x)", functions={"test": func}, names={"x": [1, 2]})
|
||||
+
|
||||
|
||||
class TestOperators(DRYTest):
|
||||
"""Test adding in new operators, removing them, make sure it works."""
|
||||
--
|
||||
2.35.6
|
||||
|
||||
Reference in New Issue
Block a user