From 776e1ce13207f068d468c070e1389a3ca70e33c2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 4 Nov 2024 14:08:07 -0500 Subject: [PATCH] [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 --- Lib/fontTools/cffLib/specializer.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Lib/fontTools/cffLib/specializer.py b/Lib/fontTools/cffLib/specializer.py index 87da279af..3db5b3882 100644 --- a/Lib/fontTools/cffLib/specializer.py +++ b/Lib/fontTools/cffLib/specializer.py @@ -459,19 +459,25 @@ 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): + + # 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 + # maxstack may have been used unintentionally. For all + # 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. + # + # 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 - 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 - # maxstack may have been used unintentionally. For all - # 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 # blendList now contains as many single blend tuples as can be # combined without exceeding the CFF2 stack limit. num_blends = len(blendlist)