[cffLib.specializer] Fix CFF argument stack overflow

The code was always merging at least two blends, which was causing
stack-overflow with a test font of ours. Move the overflow check
earlier to catch that.

Fixes https://github.com/fonttools/fonttools/issues/3676
This commit is contained in:
Behdad Esfahbod 2024-11-04 14:08:07 -05:00
parent 614d9ebf6b
commit 776e1ce132

View File

@ -459,11 +459,7 @@ def _convertToBlendCmds(args):
num_sources = len(arg) - 1
blendlist = [arg]
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
@ -471,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)