Compare commits
No commits in common. "53c463c3a44dc8db3d209fc61270d1b5d6e54247" and "63d36438294377990894a15da7acea9c26775060" have entirely different histories.
53c463c3a4
...
63d3643829
19
0fbf25e4857423f6a38ca7f5aeee1c84acaa3fc1.patch
Normal file
19
0fbf25e4857423f6a38ca7f5aeee1c84acaa3fc1.patch
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User robin <robin@reportlab.com>
|
||||||
|
# Date 1495525707 -3600
|
||||||
|
# Node ID 0fbf25e4857423f6a38ca7f5aeee1c84acaa3fc1
|
||||||
|
# Parent 0f6004ec2916b76cfbd0444de6f551bcb1949781
|
||||||
|
fix bitbucket issue 113
|
||||||
|
|
||||||
|
diff --git a/setup.py b/setup.py
|
||||||
|
--- a/setup.py
|
||||||
|
+++ b/setup.py
|
||||||
|
@@ -539,7 +539,7 @@
|
||||||
|
],
|
||||||
|
|
||||||
|
#this probably only works for setuptools, but distutils seems to ignore it
|
||||||
|
- install_requires=['pillow>=2.4.0','pip>=1.4.1', 'setuptools>=2.2'],
|
||||||
|
+ install_requires=['pillow>=2.4.0'],
|
||||||
|
)
|
||||||
|
print()
|
||||||
|
print('########## SUMMARY INFO #########')
|
||||||
81
CVE-2019-17626.patch
Normal file
81
CVE-2019-17626.patch
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# HG changeset patch
|
||||||
|
# User mkasik@redhat.com
|
||||||
|
# Date 1580132768 -3600
|
||||||
|
# Mon Jan 27 14:46:08 2020 +0100
|
||||||
|
# Node ID b47055e78d8b3e49e7bb5b9cdaa55d449b996764
|
||||||
|
# Parent 9bb6ebf1b8473e3dc11740cbdce0d5dc1a1afae2
|
||||||
|
Parse input string of toColor.__call__ for color classes
|
||||||
|
|
||||||
|
It constructs respective object from the string then.
|
||||||
|
This currently supports CMYKColor, PCMYKColor, CMYKColorSep
|
||||||
|
and PCMYKColorSep.
|
||||||
|
|
||||||
|
--- a/src/reportlab/lib/colors.py
|
||||||
|
+++ b/src/reportlab/lib/colors.py
|
||||||
|
@@ -833,6 +833,53 @@ class cssParse:
|
||||||
|
|
||||||
|
cssParse=cssParse()
|
||||||
|
|
||||||
|
+def parseColorClassFromString(arg):
|
||||||
|
+ '''Parses known classes which holds color information from string
|
||||||
|
+ and constructs respective object.
|
||||||
|
+ It constructs CMYKColor, PCMYKColor, CMYKColorSep and PCMYKColorSep now.
|
||||||
|
+ '''
|
||||||
|
+
|
||||||
|
+ # Strips input string and splits it with {'(', ')', ','} delimiters
|
||||||
|
+ splitted = "".join(arg.split()).replace('(', ',').replace(')','').split(',')
|
||||||
|
+
|
||||||
|
+ # Creates a "fingerprint" of given string made of {'(', ')', ','} characters only.
|
||||||
|
+ fingerprint = ''.join(c for c in arg if c in set('(,)'))
|
||||||
|
+
|
||||||
|
+ if (len(splitted) > 0):
|
||||||
|
+ if (splitted[0] == 'Color'):
|
||||||
|
+ if (fingerprint == '(,,,)'):
|
||||||
|
+ try:
|
||||||
|
+ return Color(*list(map(float, splitted[1:5])))
|
||||||
|
+ except:
|
||||||
|
+ return None
|
||||||
|
+ elif (fingerprint == '(,,)'):
|
||||||
|
+ try:
|
||||||
|
+ return Color(*list(map(float, splitted[1:4])))
|
||||||
|
+ except:
|
||||||
|
+ return None
|
||||||
|
+ elif (splitted[0] == 'CMYKColor' and fingerprint == '(,,,)'):
|
||||||
|
+ try:
|
||||||
|
+ return CMYKColor(*list(map(float, splitted[1:5])))
|
||||||
|
+ except:
|
||||||
|
+ return None
|
||||||
|
+ elif (splitted[0] == 'PCMYKColor' and fingerprint == '(,,,)'):
|
||||||
|
+ try:
|
||||||
|
+ return PCMYKColor(*list(map(float, splitted[1:5])))
|
||||||
|
+ except:
|
||||||
|
+ return None
|
||||||
|
+ elif (splitted[0] == 'CMYKColorSep' and fingerprint == '(,,,)'):
|
||||||
|
+ try:
|
||||||
|
+ return CMYKColorSep(*list(map(float, splitted[1:5])))
|
||||||
|
+ except:
|
||||||
|
+ return None
|
||||||
|
+ elif (splitted[0] == 'PCMYKColorSep' and fingerprint == '(,,,)'):
|
||||||
|
+ try:
|
||||||
|
+ return PCMYKColorSep(*list(map(float, splitted[1:5])))
|
||||||
|
+ except:
|
||||||
|
+ return None
|
||||||
|
+ else:
|
||||||
|
+ return None
|
||||||
|
+
|
||||||
|
class toColor:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
@@ -858,10 +905,8 @@ class toColor:
|
||||||
|
C = getAllNamedColors()
|
||||||
|
s = arg.lower()
|
||||||
|
if s in C: return C[s]
|
||||||
|
- try:
|
||||||
|
- return toColor(eval(arg))
|
||||||
|
- except:
|
||||||
|
- pass
|
||||||
|
+ parsedColor = parseColorClassFromString(arg)
|
||||||
|
+ if (parsedColor): return parsedColor
|
||||||
|
|
||||||
|
try:
|
||||||
|
return HexColor(arg)
|
||||||
@ -1,346 +0,0 @@
|
|||||||
From 1bd6d30aed39acb026f51c309b81d81e8b79e5ad Mon Sep 17 00:00:00 2001
|
|
||||||
From: liningjie <liningjie@xfusion.com>
|
|
||||||
Date: Sat, 17 Jun 2023 18:21:22 +0800
|
|
||||||
Subject: [PATCH] CVE-2023-33733 with rl_safe_eval & rl_config.toColorCanUse
|
|
||||||
changes
|
|
||||||
|
|
||||||
---
|
|
||||||
src/reportlab/lib/colors.py | 75 +++++++++++++++++++++++++------
|
|
||||||
src/reportlab/lib/rl_safe_eval.py | 71 ++++++++++++++++++++++++++++-
|
|
||||||
src/reportlab/lib/utils.py | 2 +-
|
|
||||||
src/reportlab/rl_settings.py | 5 ++-
|
|
||||||
tests/test_lib_rl_safe_eval.py | 49 ++++++++++++++++++--
|
|
||||||
5 files changed, 181 insertions(+), 21 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/reportlab/lib/colors.py b/src/reportlab/lib/colors.py
|
|
||||||
index 84e8679..09d078f 100644
|
|
||||||
--- a/src/reportlab/lib/colors.py
|
|
||||||
+++ b/src/reportlab/lib/colors.py
|
|
||||||
@@ -41,7 +41,8 @@ ValueError: css color 'pcmyka(100,0,0,0)' has wrong number of components
|
|
||||||
'''
|
|
||||||
import math, re, functools
|
|
||||||
from reportlab.lib.rl_accel import fp_str
|
|
||||||
-from reportlab.lib.utils import asNative, isStr, rl_safe_eval
|
|
||||||
+from reportlab.lib.utils import asNative, isStr, rl_safe_eval, rl_extended_literal_eval
|
|
||||||
+from reportlab import rl_config
|
|
||||||
from ast import literal_eval
|
|
||||||
|
|
||||||
class Color:
|
|
||||||
@@ -835,6 +836,17 @@ class cssParse:
|
|
||||||
cssParse=cssParse()
|
|
||||||
|
|
||||||
class toColor:
|
|
||||||
+ """Accepot an expression returnng a Color subclass.
|
|
||||||
+
|
|
||||||
+ This used to accept arbitrary Python expressions, which resulted in increasngly devilish CVEs and
|
|
||||||
+ security holes from tie to time. In April 2023 we are creating explicit, "dumb" parsing code to
|
|
||||||
+ replace this. Acceptable patterns are
|
|
||||||
+
|
|
||||||
+ a Color instance passed in by the Python programmer
|
|
||||||
+ a named list of colours ('pink' etc')
|
|
||||||
+ list of 3 or 4 numbers
|
|
||||||
+ all CSS colour expression
|
|
||||||
+ """
|
|
||||||
_G = {} #globals we like (eventually)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
@@ -860,21 +872,58 @@ class toColor:
|
|
||||||
C = getAllNamedColors()
|
|
||||||
s = arg.lower()
|
|
||||||
if s in C: return C[s]
|
|
||||||
- G = C.copy()
|
|
||||||
- G.update(self.extraColorsNS)
|
|
||||||
- if not self._G:
|
|
||||||
- C = globals()
|
|
||||||
- self._G = {s:C[s] for s in '''Blacker CMYKColor CMYKColorSep Color ColorType HexColor PCMYKColor PCMYKColorSep Whiter
|
|
||||||
- _chooseEnforceColorSpace _enforceCMYK _enforceError _enforceRGB _enforceSEP _enforceSEP_BLACK
|
|
||||||
- _enforceSEP_CMYK _namedColors _re_css asNative cmyk2rgb cmykDistance color2bw colorDistance
|
|
||||||
- cssParse describe fade fp_str getAllNamedColors hsl2rgb hue2rgb isStr linearlyInterpolatedColor
|
|
||||||
- literal_eval obj_R_G_B opaqueColor rgb2cmyk setColors toColor toColorOrNone'''.split()}
|
|
||||||
- G.update(self._G)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ # allow expressions like 'Blacker(red, 0.5)'
|
|
||||||
+ # >>> re.compile(r"(Blacker|Whiter)\((\w+)\,\s?([0-9.]+)\)").match(msg).groups()
|
|
||||||
+ # ('Blacker', 'red', '0.5')
|
|
||||||
+ # >>>
|
|
||||||
+ pat = re.compile(r"(Blacker|Whiter)\((\w+)\,\s?([0-9.]+)\)")
|
|
||||||
+ m = pat.match(arg)
|
|
||||||
+ if m:
|
|
||||||
+ funcname, rootcolor, num = m.groups()
|
|
||||||
+ if funcname == 'Blacker':
|
|
||||||
+ return Blacker(rootcolor, float(num))
|
|
||||||
+ else:
|
|
||||||
+ return Whiter(rootcolor, float(num))
|
|
||||||
+
|
|
||||||
try:
|
|
||||||
- return toColor(rl_safe_eval(arg,g=G,l={}))
|
|
||||||
- except:
|
|
||||||
+ import ast
|
|
||||||
+ expr = ast.literal_eval(arg) #safe probably only a tuple or list of values
|
|
||||||
+ return toColor(expr)
|
|
||||||
+ except (SyntaxError, ValueError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
+ if rl_config.toColorCanUse=='rl_safe_eval':
|
|
||||||
+ #the most dangerous option
|
|
||||||
+ G = C.copy()
|
|
||||||
+ G.update(self.extraColorsNS)
|
|
||||||
+ if not self._G:
|
|
||||||
+ C = globals()
|
|
||||||
+ self._G = {s:C[s] for s in '''Blacker CMYKColor CMYKColorSep Color ColorType HexColor PCMYKColor PCMYKColorSep Whiter
|
|
||||||
+ _chooseEnforceColorSpace _enforceCMYK _enforceError _enforceRGB _enforceSEP _enforceSEP_BLACK
|
|
||||||
+ _enforceSEP_CMYK _namedColors _re_css asNative cmyk2rgb cmykDistance color2bw colorDistance
|
|
||||||
+ cssParse describe fade fp_str getAllNamedColors hsl2rgb hue2rgb isStr linearlyInterpolatedColor
|
|
||||||
+ literal_eval obj_R_G_B opaqueColor rgb2cmyk setColors toColor toColorOrNone'''.split()}
|
|
||||||
+ G.update(self._G)
|
|
||||||
+ try:
|
|
||||||
+ return toColor(rl_safe_eval(arg,g=G,l={}))
|
|
||||||
+ except:
|
|
||||||
+ pass
|
|
||||||
+ elif rl_config.toColorCanUse=='rl_extended_literal_eval':
|
|
||||||
+ C = globals()
|
|
||||||
+ S = getAllNamedColors().copy()
|
|
||||||
+ C = {k:C[k] for k in '''Blacker CMYKColor CMYKColorSep Color ColorType HexColor PCMYKColor PCMYKColorSep Whiter
|
|
||||||
+ _chooseEnforceColorSpace _enforceCMYK _enforceError _enforceRGB _enforceSEP _enforceSEP_BLACK
|
|
||||||
+ _enforceSEP_CMYK _namedColors _re_css asNative cmyk2rgb cmykDistance color2bw colorDistance
|
|
||||||
+ cssParse describe fade fp_str getAllNamedColors hsl2rgb hue2rgb linearlyInterpolatedColor
|
|
||||||
+ obj_R_G_B opaqueColor rgb2cmyk setColors toColor toColorOrNone'''.split()
|
|
||||||
+ if callable(C.get(k,None))}
|
|
||||||
+ try:
|
|
||||||
+ return rl_extended_literal_eval(arg,C,S)
|
|
||||||
+ except (ValueError, SyntaxError):
|
|
||||||
+ pass
|
|
||||||
+
|
|
||||||
try:
|
|
||||||
return HexColor(arg)
|
|
||||||
except:
|
|
||||||
diff --git a/src/reportlab/lib/rl_safe_eval.py b/src/reportlab/lib/rl_safe_eval.py
|
|
||||||
index 49828c9..50834f6 100644
|
|
||||||
--- a/src/reportlab/lib/rl_safe_eval.py
|
|
||||||
+++ b/src/reportlab/lib/rl_safe_eval.py
|
|
||||||
@@ -3,7 +3,7 @@
|
|
||||||
#https://github.com/zopefoundation/RestrictedPython
|
|
||||||
#https://github.com/danthedeckie/simpleeval
|
|
||||||
#hopefully we are standing on giants' shoulders
|
|
||||||
-import sys, os, ast, re, weakref, time, copy, math
|
|
||||||
+import sys, os, ast, re, weakref, time, copy, math, types
|
|
||||||
eval_debug = int(os.environ.get('EVAL_DEBUG','0'))
|
|
||||||
strTypes = (bytes,str)
|
|
||||||
isPy39 = sys.version_info[:2]>=(3,9)
|
|
||||||
@@ -53,7 +53,9 @@ __rl_unsafe__ = frozenset('''builtins breakpoint __annotations__ co_argcount co_
|
|
||||||
func_doc func_globals func_name gi_code gi_frame gi_running gi_yieldfrom
|
|
||||||
__globals__ im_class im_func im_self __iter__ __kwdefaults__ __module__
|
|
||||||
__name__ next __qualname__ __self__ tb_frame tb_lasti tb_lineno tb_next
|
|
||||||
- globals vars locals'''.split()
|
|
||||||
+ globals vars locals
|
|
||||||
+ type eval exec aiter anext compile open
|
|
||||||
+ dir print classmethod staticmethod __import__ super property'''.split()
|
|
||||||
)
|
|
||||||
__rl_unsafe_re__ = re.compile(r'\b(?:%s)' % '|'.join(__rl_unsafe__),re.M)
|
|
||||||
|
|
||||||
@@ -1204,5 +1206,70 @@ class __rl_safe_eval__:
|
|
||||||
class __rl_safe_exec__(__rl_safe_eval__):
|
|
||||||
mode = 'exec'
|
|
||||||
|
|
||||||
+def rl_extended_literal_eval(expr, safe_callables=None, safe_names=None):
|
|
||||||
+ if safe_callables is None:
|
|
||||||
+ safe_callables = {}
|
|
||||||
+ if safe_names is None:
|
|
||||||
+ safe_names = {}
|
|
||||||
+ safe_names = safe_names.copy()
|
|
||||||
+ safe_names.update({'None': None, 'True': True, 'False': False})
|
|
||||||
+ #make these readonly with MappingProxyType
|
|
||||||
+ safe_names = types.MappingProxyType(safe_names)
|
|
||||||
+ safe_callables = types.MappingProxyType(safe_callables)
|
|
||||||
+ if isinstance(expr, str):
|
|
||||||
+ expr = ast.parse(expr, mode='eval')
|
|
||||||
+ if isinstance(expr, ast.Expression):
|
|
||||||
+ expr = expr.body
|
|
||||||
+ try:
|
|
||||||
+ # Python 3.4 and up
|
|
||||||
+ ast.NameConstant
|
|
||||||
+ safe_test = lambda n: isinstance(n, ast.NameConstant) or isinstance(n,ast.Name) and n.id in safe_names
|
|
||||||
+ safe_extract = lambda n: n.value if isinstance(n,ast.NameConstant) else safe_names[n.id]
|
|
||||||
+ except AttributeError:
|
|
||||||
+ # Everything before
|
|
||||||
+ safe_test = lambda n: isinstance(n, ast.Name) and n.id in safe_names
|
|
||||||
+ safe_extract = lambda n: safe_names[n.id]
|
|
||||||
+ def _convert(node):
|
|
||||||
+ if isinstance(node, (ast.Str, ast.Bytes)):
|
|
||||||
+ return node.s
|
|
||||||
+ elif isinstance(node, ast.Num):
|
|
||||||
+ return node.n
|
|
||||||
+ elif isinstance(node, ast.Tuple):
|
|
||||||
+ return tuple(map(_convert, node.elts))
|
|
||||||
+ elif isinstance(node, ast.List):
|
|
||||||
+ return list(map(_convert, node.elts))
|
|
||||||
+ elif isinstance(node, ast.Dict):
|
|
||||||
+ return dict((_convert(k), _convert(v)) for k, v
|
|
||||||
+ in zip(node.keys, node.values))
|
|
||||||
+ elif safe_test(node):
|
|
||||||
+ return safe_extract(node)
|
|
||||||
+ elif isinstance(node, ast.UnaryOp) and \
|
|
||||||
+ isinstance(node.op, (ast.UAdd, ast.USub)) and \
|
|
||||||
+ isinstance(node.operand, (ast.Num, ast.UnaryOp, ast.BinOp)):
|
|
||||||
+ operand = _convert(node.operand)
|
|
||||||
+ if isinstance(node.op, ast.UAdd):
|
|
||||||
+ return + operand
|
|
||||||
+ else:
|
|
||||||
+ return - operand
|
|
||||||
+ elif isinstance(node, ast.BinOp) and \
|
|
||||||
+ isinstance(node.op, (ast.Add, ast.Sub)) and \
|
|
||||||
+ isinstance(node.right, (ast.Num, ast.UnaryOp, ast.BinOp)) and \
|
|
||||||
+ isinstance(node.right.n, complex) and \
|
|
||||||
+ isinstance(node.left, (ast.Num, ast.UnaryOp, astBinOp)):
|
|
||||||
+ left = _convert(node.left)
|
|
||||||
+ right = _convert(node.right)
|
|
||||||
+ if isinstance(node.op, ast.Add):
|
|
||||||
+ return left + right
|
|
||||||
+ else:
|
|
||||||
+ return left - right
|
|
||||||
+ elif isinstance(node, ast.Call) and \
|
|
||||||
+ isinstance(node.func, ast.Name) and \
|
|
||||||
+ node.func.id in safe_callables:
|
|
||||||
+ return safe_callables[node.func.id](
|
|
||||||
+ *[_convert(n) for n in node.args],
|
|
||||||
+ **{kw.arg: _convert(kw.value) for kw in node.keywords})
|
|
||||||
+ raise ValueError('Bad expression')
|
|
||||||
+ return _convert(expr)
|
|
||||||
+
|
|
||||||
rl_safe_exec = __rl_safe_exec__()
|
|
||||||
rl_safe_eval = __rl_safe_eval__()
|
|
||||||
diff --git a/src/reportlab/lib/utils.py b/src/reportlab/lib/utils.py
|
|
||||||
index 5a6b5d7..a53a05c 100644
|
|
||||||
--- a/src/reportlab/lib/utils.py
|
|
||||||
+++ b/src/reportlab/lib/utils.py
|
|
||||||
@@ -11,7 +11,7 @@ from io import BytesIO
|
|
||||||
from hashlib import md5
|
|
||||||
|
|
||||||
from reportlab.lib.rltempfile import get_rl_tempfile, get_rl_tempdir
|
|
||||||
-from . rl_safe_eval import rl_safe_exec, rl_safe_eval, safer_globals
|
|
||||||
+from . rl_safe_eval import rl_safe_exec, rl_safe_eval, safer_globals, rl_extended_literal_eval
|
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
class __UNSET__:
|
|
||||||
diff --git a/src/reportlab/rl_settings.py b/src/reportlab/rl_settings.py
|
|
||||||
index 30e7547..1a9e520 100644
|
|
||||||
--- a/src/reportlab/rl_settings.py
|
|
||||||
+++ b/src/reportlab/rl_settings.py
|
|
||||||
@@ -67,7 +67,8 @@ documentLang
|
|
||||||
encryptionStrength
|
|
||||||
trustedHosts
|
|
||||||
trustedSchemes
|
|
||||||
-renderPMBackend'''.split())
|
|
||||||
+renderPMBackend
|
|
||||||
+toColorCanUse'''.split())
|
|
||||||
|
|
||||||
allowTableBoundsErrors = 1 # set to 0 to die on too large elements in tables in debug (recommend 1 for production use)
|
|
||||||
shapeChecking = 1
|
|
||||||
@@ -158,6 +159,8 @@ trustedSchemes=['file', 'rml', 'data', 'https', #these url schemes are trust
|
|
||||||
'http', 'ftp']
|
|
||||||
renderPMBackend='_renderPM' #or 'rlPyCairo' if available
|
|
||||||
|
|
||||||
+toColorCanUse='rl_extended_literal_eval' #change to None or 'rl_safe_eval' depending on trust
|
|
||||||
+
|
|
||||||
# places to look for T1Font information
|
|
||||||
T1SearchPath = (
|
|
||||||
'c:/Program Files/Adobe/Acrobat 9.0/Resource/Font',
|
|
||||||
diff --git a/tests/test_lib_rl_safe_eval.py b/tests/test_lib_rl_safe_eval.py
|
|
||||||
index 84bd86f..fd556eb 100644
|
|
||||||
--- a/tests/test_lib_rl_safe_eval.py
|
|
||||||
+++ b/tests/test_lib_rl_safe_eval.py
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
#Copyright ReportLab Europe Ltd. 2000-2017
|
|
||||||
#see license.txt for license details
|
|
||||||
-"""Tests for reportlab.lib.rl_eval
|
|
||||||
+"""Tests for reportlab.lib.rl_safe_eval
|
|
||||||
"""
|
|
||||||
__version__='3.5.33'
|
|
||||||
from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, printLocation
|
|
||||||
@@ -10,7 +10,7 @@ import reportlab
|
|
||||||
from reportlab import rl_config
|
|
||||||
import unittest
|
|
||||||
from reportlab.lib import colors
|
|
||||||
-from reportlab.lib.utils import rl_safe_eval, rl_safe_exec, annotateException
|
|
||||||
+from reportlab.lib.utils import rl_safe_eval, rl_safe_exec, annotateException, rl_extended_literal_eval
|
|
||||||
from reportlab.lib.rl_safe_eval import BadCode
|
|
||||||
|
|
||||||
testObj = [1,('a','b',2),{'A':1,'B':2.0},"32"]
|
|
||||||
@@ -52,7 +52,6 @@ class SafeEvalTestSequenceMeta(type):
|
|
||||||
'dict(a=1).get("a",2)',
|
|
||||||
'dict(a=1).pop("a",2)',
|
|
||||||
'{"_":1+_ for _ in (1,2)}.pop(1,None)',
|
|
||||||
- '(type(1),type(str),type(testObj),type(TestClass))',
|
|
||||||
'1 if True else "a"',
|
|
||||||
'1 if False else "a"',
|
|
||||||
'testFunc(bad=False)',
|
|
||||||
@@ -74,6 +73,8 @@ class SafeEvalTestSequenceMeta(type):
|
|
||||||
(
|
|
||||||
'fail',
|
|
||||||
(
|
|
||||||
+ 'vars()',
|
|
||||||
+ '(type(1),type(str),type(testObj),type(TestClass))',
|
|
||||||
'open("/tmp/myfile")',
|
|
||||||
'SafeEvalTestCase.__module__',
|
|
||||||
("testInst.__class__.__bases__[0].__subclasses__()",dict(g=dict(testInst=testInst))),
|
|
||||||
@@ -97,6 +98,8 @@ class SafeEvalTestSequenceMeta(type):
|
|
||||||
'testFunc(bad=True)',
|
|
||||||
'getattr(testInst,"__class__",14)',
|
|
||||||
'"{1}{2}".format(1,2)',
|
|
||||||
+ 'builtins',
|
|
||||||
+ '[ [ [ [ ftype(ctype(0, 0, 0, 0, 3, 67, b"t\\x00d\\x01\\x83\\x01\\xa0\\x01d\\x02\\xa1\\x01\\x01\\x00d\\x00S\\x00", (None, "os", "touch /tmp/exploited"), ("__import__", "system"), (), "<stdin>", "", 1, b"\\x12\\x01"), {})() for ftype in [type(lambda: None)] ] for ctype in [type(getattr(lambda: {None}, Word("__code__")))] ] for Word in [orgTypeFun("Word", (str,), { "mutated": 1, "startswith": lambda self, x: False, "__eq__": lambda self,x: self.mutate() and self.mutated < 0 and str(self) == x, "mutate": lambda self: {setattr(self, "mutated", self.mutated - 1)}, "__hash__": lambda self: hash(str(self)) })] ] for orgTypeFun in [type(type(1))]] and "red"',
|
|
||||||
)
|
|
||||||
),
|
|
||||||
):
|
|
||||||
@@ -155,8 +158,46 @@ class SafeEvalTestBasics(unittest.TestCase):
|
|
||||||
def test_002(self):
|
|
||||||
self.assertTrue(rl_safe_eval("GA=='ga'"))
|
|
||||||
|
|
||||||
+class ExtendedLiteralEval(unittest.TestCase):
|
|
||||||
+ def test_001(self):
|
|
||||||
+ S = colors.getAllNamedColors().copy()
|
|
||||||
+ C = {s:getattr(colors,s) for s in '''Blacker CMYKColor CMYKColorSep Color ColorType HexColor PCMYKColor PCMYKColorSep Whiter
|
|
||||||
+ _chooseEnforceColorSpace _enforceCMYK _enforceError _enforceRGB _enforceSEP _enforceSEP_BLACK
|
|
||||||
+ _enforceSEP_CMYK _namedColors _re_css asNative cmyk2rgb cmykDistance color2bw colorDistance
|
|
||||||
+ cssParse describe fade fp_str getAllNamedColors hsl2rgb hue2rgb linearlyInterpolatedColor
|
|
||||||
+ obj_R_G_B opaqueColor rgb2cmyk setColors toColor toColorOrNone'''.split()
|
|
||||||
+ if callable(getattr(colors,s,None))}
|
|
||||||
+ def showVal(s):
|
|
||||||
+ try:
|
|
||||||
+ r = rl_extended_literal_eval(s,C,S)
|
|
||||||
+ except:
|
|
||||||
+ r = str(sys.exc_info()[1])
|
|
||||||
+ return r
|
|
||||||
+
|
|
||||||
+ for expr, expected in (
|
|
||||||
+ ('1.0', 1.0),
|
|
||||||
+ ('1', 1),
|
|
||||||
+ ('red', colors.red),
|
|
||||||
+ ('True', True),
|
|
||||||
+ ('False', False),
|
|
||||||
+ ('None', None),
|
|
||||||
+ ('Blacker(red,0.5)', colors.Color(.5,0,0,1)),
|
|
||||||
+ ('PCMYKColor(21,10,30,5,spotName="ABCD")', colors.PCMYKColor(21,10,30,5,spotName='ABCD',alpha=100)),
|
|
||||||
+ ('HexColor("#ffffff")', colors.Color(1,1,1,1)),
|
|
||||||
+ ('linearlyInterpolatedColor(red, blue, 0, 1, 0.5)', colors.Color(.5,0,.5,1)),
|
|
||||||
+ ('red.rgb()', 'Bad expression'),
|
|
||||||
+ ('__import__("sys")', 'Bad expression'),
|
|
||||||
+ ('globals()', 'Bad expression'),
|
|
||||||
+ ('locals()', 'Bad expression'),
|
|
||||||
+ ('vars()', 'Bad expression'),
|
|
||||||
+ ('builtins', 'Bad expression'),
|
|
||||||
+ ('__file__', 'Bad expression'),
|
|
||||||
+ ('__name__', 'Bad expression'),
|
|
||||||
+ ):
|
|
||||||
+ self.assertEqual(showVal(expr),expected,f"rl_extended_literal_eval({expr!r}) is not equal to expected {expected}")
|
|
||||||
+
|
|
||||||
def makeSuite():
|
|
||||||
- return makeSuiteForClasses(SafeEvalTestCase,SafeEvalTestBasics)
|
|
||||||
+ return makeSuiteForClasses(SafeEvalTestCase,SafeEvalTestBasics,ExtendedLiteralEval)
|
|
||||||
|
|
||||||
if __name__ == "__main__": #noruntests
|
|
||||||
unittest.TextTestRunner().run(makeSuite())
|
|
||||||
--
|
|
||||||
2.30.0.windows.2
|
|
||||||
|
|
||||||
@ -1,17 +1,14 @@
|
|||||||
%global cmapdir %(echo `rpm -qls ghostscript | grep CMap | awk '{print $2}'`)
|
%global cmapdir %(echo `rpm -qls ghostscript | grep CMap | awk '{print $2}'`)
|
||||||
|
|
||||||
%bcond_without tests
|
|
||||||
|
|
||||||
Name: python-reportlab
|
Name: python-reportlab
|
||||||
Version: 3.6.10
|
Version: 3.4.0
|
||||||
Release: 2
|
Release: 13
|
||||||
Summary: ReportLab library to create PDF documents and graphic
|
Summary: ReportLab library to create PDF documents and graphic
|
||||||
License: BSD
|
License: BSD
|
||||||
URL: https://www.reportlab.com/
|
URL: https://www.reportlab.com/
|
||||||
Source0: https://pypi.python.org/packages/source/r/reportlab/reportlab-%{version}.tar.gz
|
Source0: https://pypi.python.org/packages/source/r/reportlab/reportlab-%{version}.tar.gz
|
||||||
BuildRequires: libart_lgpl-devel freetype-devel
|
Patch0001: 0fbf25e4857423f6a38ca7f5aeee1c84acaa3fc1.patch
|
||||||
|
Patch0002: CVE-2019-17626.patch
|
||||||
Patch0: backport-CVE-2023-33733-fix-RCE-attack-via-method-eval.patch
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
The ReportLab Toolkit. An Open Source Python library for generating PDFs and graphics.
|
The ReportLab Toolkit. An Open Source Python library for generating PDFs and graphics.
|
||||||
@ -43,27 +40,16 @@ find src -name '*.py' | xargs sed -i -e '/^#!\//d'
|
|||||||
sed -i '/\~\/\.local\/share\/fonts\/CMap/i''\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '\'"%{cmapdir}"\''\,' \
|
sed -i '/\~\/\.local\/share\/fonts\/CMap/i''\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '\'"%{cmapdir}"\''\,' \
|
||||||
src/reportlab/rl_settings.py
|
src/reportlab/rl_settings.py
|
||||||
|
|
||||||
rm -rf src/reportlab.egg-info
|
|
||||||
|
|
||||||
rm -rf src/rl_addons/renderPM/libart_lgpl
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS} -Isrc/rl_addons/renderPM -I%{_includedir}/libart-2.0}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}"\
|
CFLAGS="%{optflags}" %py3_build
|
||||||
%{__python3} setup.py --use-system-libart --no-download-t1-files build --executable="%{__python3} -s"
|
|
||||||
|
PYTHONPATH="`pwd`/`ls -d build/lib*`" %{__python3} docs/genAll.py
|
||||||
|
|
||||||
%install
|
%install
|
||||||
CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS} -Isrc/rl_addons/renderPM -I%{_includedir}/libart-2.0}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}"\
|
%py3_install
|
||||||
%{__python3} setup.py --use-system-libart --no-download-t1-files install -O1 --skip-build --root ${RPM_BUILD_ROOT}
|
|
||||||
|
|
||||||
%if %{with tests}
|
|
||||||
%check
|
%check
|
||||||
# Tests need in-build compiled Python modules to be executed
|
|
||||||
# Tests pre-generate userguide PDF
|
|
||||||
cp -a build/lib.%{python3_platform}-%{python3_version}/reportlab tests/
|
|
||||||
cp -a build/lib.%{python3_platform}-%{python3_version}/reportlab docs/
|
|
||||||
cp -a build/lib.%{python3_platform}-%{python3_version}/reportlab docs/userguide/
|
|
||||||
%{__python3} setup.py tests
|
%{__python3} setup.py tests
|
||||||
%endif
|
|
||||||
|
|
||||||
%files -n python3-reportlab
|
%files -n python3-reportlab
|
||||||
%doc README.txt CHANGES.md
|
%doc README.txt CHANGES.md
|
||||||
@ -74,22 +60,13 @@ cp -a build/lib.%{python3_platform}-%{python3_version}/reportlab docs/userguide/
|
|||||||
%doc demos/ tools/
|
%doc demos/ tools/
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Wed Jun 28 2023 liningjie <liningjie@xfusion.com> - 3.6.10-2
|
|
||||||
- Fix CVE-2023-33733
|
|
||||||
|
|
||||||
* Thu Jun 23 2022 SimpleUpdate Robot <tc@openeuler.org> - 3.6.10-1
|
|
||||||
- Upgrade to version 3.6.10
|
|
||||||
|
|
||||||
* Wed Jan 12 2022 Chengshaowei <chenshaowei3@huawei.com> - 3.4.0-14
|
|
||||||
- Fix can not import error
|
|
||||||
|
|
||||||
* Wed Jul 21 2021 yaoxin <yaoxin30@huawei.com> - 3.4.0-13
|
* Wed Jul 21 2021 yaoxin <yaoxin30@huawei.com> - 3.4.0-13
|
||||||
- Fix CVE-2019-17626
|
- Fix CVE-2019-17626
|
||||||
|
|
||||||
* Mon May 31 2021 huanghaitao <huanghaitao8@huawei.com> - 3.4.0-12
|
* Mon May 31 2021 huanghaitao <huanghaitao8@huawei.com> - 3.4.0-12
|
||||||
- Completing build dependencies
|
- Completing build dependencies
|
||||||
|
|
||||||
* Fri Sep 11 2020 wangyue<wangyue92@huawei.com> - 3.4.0-11
|
* Fri 11 Sep 2020 wangyue<wangyue92@huawei.com> - 3.4.0-11
|
||||||
- Remove python2-reportlab
|
- Remove python2-reportlab
|
||||||
|
|
||||||
* Mon Mar 02 2020 Jiangping Hu <hujp1985@foxmail.com> - 3.4.0-10
|
* Mon Mar 02 2020 Jiangping Hu <hujp1985@foxmail.com> - 3.4.0-10
|
||||||
|
|||||||
BIN
reportlab-3.4.0.tar.gz
Normal file
BIN
reportlab-3.4.0.tar.gz
Normal file
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user