1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
Description: Fix CVE-2019-17626: remote code execution in colors.py
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.
Origin: vendor, https://bitbucket.org/rptlab/reportlab/issues/199/eval-in-colorspy-leads-to-remote-code#comment-55887892
Bug: https://bitbucket.org/rptlab/reportlab/issues/199/eval-in-colorspy-leads-to-remote-code
Bug-Debian: https://bugs.debian.org/942763
Forwarded: no
Author: Marek Kasik <mkasik@redhat.com>
Reviewed-by: Salvatore Bonaccorso <carnil@debian.org>
Last-Update: 2020-04-24
diff -r 9bb6ebf1b847 -r b47055e78d8b src/reportlab/lib/colors.py
--- a/src/reportlab/lib/colors.py Fri Sep 20 14:12:39 2019 +0100
+++ b/src/reportlab/lib/colors.py Mon Jan 27 14:46:08 2020 +0100
@@ -838,6 +838,53 @@
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):
@@ -863,10 +910,8 @@
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)
|