Skip to content

[cxx-interop] Fix infinite recursion of PackExpansion type. #34427

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 1 commit into from
Nov 2, 2020

Conversation

zoecarver
Copy link
Contributor

Fix infinite recursion issue in the SwiftTypeConverter. At some point, we should support variadic types properly but this patch is purely to prevent crashes.

@@ -832,6 +832,8 @@ namespace {

#define SUGAR_TYPE(KIND) \
ImportResult Visit##KIND##Type(const clang::KIND##Type *type) { \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When importing large C++ libraries I've noticed other types cause infinite recursion here too (not just PackExpansion). I don't remember off the top of my head which types, but I can try to find some more test cases. Anyway, I think this is a good check for all "sugar types".

Copy link
Contributor

@varungandhi-apple varungandhi-apple Oct 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand this fix. Is PackExpansion sometimes a sugared type and sometimes isn't? If so, shouldn't it have a hand-written Visit method instead of returning a bogus Type() when it is in canonical form?

Copy link
Contributor Author

@zoecarver zoecarver Oct 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Some of (all of?) these types sometimes are sugared and sometimes aren't. We should probably have custom visitors for most if not all of them. But until then, we really shouldn't create an infinite loop by visiting the same type over and over again.

The test I created is for PackExpansion but I suspect we could find test cases for all the below types that have an isSugared method. If you'd like, I can add a few more test cases.

That makes me think, I wonder if I could replace the .getTypePtr() == type with .isSugared(). I'll give that a try later today.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to sound greedy, but ideally we would get a test case for each sugared type (I don't think I'd be able to come up with test cases for all of them TBH :) If all of them are susceptible to the infinite recursion, it's fine to have the guard where you have it currently. If it's only some of them, let's only guard those, wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably have custom visitors for most if not all of them. But until then, we really shouldn't create an infinite loop by visiting the same type over and over again.

Ah OK, so this is intended as a stop-gap fix, not as a full solution. That's fine by me. 👍🏼 (Having an inline FIXME stating that the custom visitors need to be written would be nice though.)

+1 to Martin's idea of having test cases for the different potentially-sugared types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah OK, so this is intended as a stop-gap fix, not as a full solution. That's fine by me. 👍🏼 (Having an inline FIXME stating that the custom visitors need to be written would be nice though.)

I'll add a TODO. Good suggestion.

I don't want to sound greedy, but ideally we would get a test case for each sugared type (I don't think I'd be able to come up with test cases for all of them TBH :) If all of them are susceptible to the infinite recursion, it's fine to have the guard where you have it currently. If it's only some of them, let's only guard those, wdyt?

I'll add some more test cases. I'll add as many as I can come up with but some of these, I'm not sure I can find a test case for. In that case, I still think we should bail here. Even if I can't find a test case, it's conceivable that a user will. Instead of crashing when attempting to import a huge library that contains some super weird type that I user figured out how to make, we should just fail to import that type. We never want to visit the desugared version of a non-sugared type. Even if we can't find a case where that type would exist, I still think we should keep the condition.

@zoecarver zoecarver added the c++ interop Feature: Interoperability with C++ label Oct 25, 2020
@zoecarver
Copy link
Contributor Author

Updates:

  • Added a MAYBE_SUGAR_TYPE macro and used it for the types that could cause problems.
  • Added tests that don't require support for other features (dependent types or class templates).
  • Added TODOs for both MAYBE_SUGAR_TYPE visitors and tests for types I couldn't create tests for (because of reasons stated above).

Fix infinite recursion issue in the SwiftTypeConverter. This patch is
purely to prevent crashes.
Copy link
Contributor

@hlopko hlopko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! :)

@zoecarver
Copy link
Contributor Author

@swift-ci please smoke test and merge.

1 similar comment
@zoecarver
Copy link
Contributor Author

@swift-ci please smoke test and merge.

@swift-ci swift-ci merged commit ee9b12f into swiftlang:main Nov 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ interop Feature: Interoperability with C++
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants