Merge pull request #3679 from fonttools/cff2-specializer-maxStack
[CFF2] specializer fix stack overflow
This commit is contained in:
commit
dafb6d26a0
@ -446,9 +446,9 @@ def _convertToBlendCmds(args):
|
||||
i = 0
|
||||
while i < num_args:
|
||||
arg = args[i]
|
||||
i += 1
|
||||
if not isinstance(arg, list):
|
||||
new_args.append(arg)
|
||||
i += 1
|
||||
stack_use += 1
|
||||
else:
|
||||
prev_stack_use = stack_use
|
||||
@ -458,13 +458,8 @@ def _convertToBlendCmds(args):
|
||||
# up to the max stack limit.
|
||||
num_sources = len(arg) - 1
|
||||
blendlist = [arg]
|
||||
i += 1
|
||||
stack_use += 1 + num_sources # 1 for the num_blends arg
|
||||
while (i < num_args) and isinstance(args[i], list):
|
||||
blendlist.append(args[i])
|
||||
i += 1
|
||||
stack_use += num_sources
|
||||
if stack_use + num_sources > maxStackLimit:
|
||||
|
||||
# if we are here, max stack is the CFF2 max stack.
|
||||
# I use the CFF2 max stack limit here rather than
|
||||
# the 'maxstack' chosen by the client, as the default
|
||||
@ -472,7 +467,17 @@ def _convertToBlendCmds(args):
|
||||
# the other operators, this just produces a little less
|
||||
# optimization, but here it puts a hard (and low) limit
|
||||
# on the number of source fonts that can be used.
|
||||
break
|
||||
#
|
||||
# Make sure the stack depth does not exceed (maxstack - 1), so
|
||||
# that subroutinizer can insert subroutine calls at any point.
|
||||
while (
|
||||
(i < num_args)
|
||||
and isinstance(args[i], list)
|
||||
and stack_use + num_sources < maxStackLimit
|
||||
):
|
||||
blendlist.append(args[i])
|
||||
i += 1
|
||||
stack_use += num_sources
|
||||
# blendList now contains as many single blend tuples as can be
|
||||
# combined without exceeding the CFF2 stack limit.
|
||||
num_blends = len(blendlist)
|
||||
@ -504,6 +509,19 @@ def _addArgs(a, b):
|
||||
return a + b
|
||||
|
||||
|
||||
def _argsStackUse(args):
|
||||
stackLen = 0
|
||||
maxLen = 0
|
||||
for arg in args:
|
||||
if type(arg) is list:
|
||||
# Blended arg
|
||||
maxLen = max(maxLen, stackLen + _argsStackUse(arg))
|
||||
stackLen += arg[-1]
|
||||
else:
|
||||
stackLen += 1
|
||||
return max(stackLen, maxLen)
|
||||
|
||||
|
||||
def specializeCommands(
|
||||
commands,
|
||||
ignoreErrors=False,
|
||||
@ -746,7 +764,7 @@ def specializeCommands(
|
||||
|
||||
# Make sure the stack depth does not exceed (maxstack - 1), so
|
||||
# that subroutinizer can insert subroutine calls at any point.
|
||||
if new_op and len(args1) + len(args2) < maxstack:
|
||||
if new_op and _argsStackUse(args1) + _argsStackUse(args2) < maxstack:
|
||||
commands[i - 1] = (new_op, args1 + args2)
|
||||
del commands[i]
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user