Skip to content

Avoid crash when handling unbounded conditions during designspace splitting #2797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 1, 2022

Conversation

Hoolean
Copy link
Contributor

@Hoolean Hoolean commented Sep 1, 2022

Context

Designspace documents can contain unbounded conditions, which omit one of "minimum" or "maximum". In fontTools, the absence of either is represented with None, both when designspace files are parsed, and when designspace objects are processed in varLib.

Problem

For unbounded conditions, the splitting functions expect "minimum" or "maximum" to be absent, instead of present with a value of None. This means that the None values are never substituted by an appropriate value, and so propagate further until the program crashes.

ufo2ft uses splitting as part of its build pipeline, and so unbounded conditions break the build process downstream.

Fix

This PR changes the splitting code to expect "minimum" and "maximum" to always be present, with potential values of None. This makes the behaviour consistent with the rest of the library, and fixes the crash.

In addition, a test has been added to check for regressions.

Caveat

At least one area of the existing code accounts for the values being None AND the keys being absent. This is probably overkill, as the codebase is already heavily dependent on both keys always being present. For this reason, checking for both cases was avoided here.

Future work

We could type the conditions in DesignSpaceDocument to avoid issues like this in the future. In addition, we could add tests downstream that compile projects with unbounded conditions, as this would have highlighted the issue sooner.

Conditions with unbounded values have a "minimum" or "maximum" value of
None.

These tests check that:
a) The public-facing split functions can receive None values without
     crashing; and
b) That their internal helper functions correctly translate the None
     values to math.inf and -math.inf to express them.

These tests are expected to fail, indicating where a fix is required.
For unbounded conditions, the previous code expects "minimum" or
"maximum" to be entirely absent, whereas actually they will be
consistently present with one having a value of None.

This means that math.inf and -math.inf are never substituted in for the
absent bound, and a crash occurs when the None value propagates.

This commit corrects the behaviour by checking for a value of None,
instead of checking for the presence of the keys, bringing the
behaviour inline with the rest of the library.
Some areas of the library check for both representations, and so doing
this here too means we are less likely to break existing code.

Despite this, flexibility introduces ambiguity, and so if typing gives
us confidence that such an input is unlikely, we could re-review this;
conditions with missing keys are not safe to use across the entire code-
base.
As we make an effort to support conditions with "minimum" or "maximum"
absent, as well as with "minimum" or "maximum" None, this commit
confirms that the split functions can handle these to some degree also.
@anthrotype anthrotype merged commit 876f87e into fonttools:main Sep 1, 2022
@Hoolean Hoolean deleted the fix-unbounded-conditions branch September 15, 2022 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants