Skip to content

Conversation

grynspan
Copy link
Contributor

@grynspan grynspan commented Feb 4, 2025

We access the test content record section directly instead of using some (non-existent) type-safe Swift API. On some platforms (Darwin in particular), it is possible for two copies of the testing library to be loaded at runtime, and for them to have incompatible definitions of types like Test. That means one library's @Test macro could produce a test content record that is then read by the other library's discovery logic, resulting in a stack smash or worse.

We can resolve this issue by adding a type argument to the accessor function we define for test content records; the body of the accessor can then compare the value of this argument against the expected Swift type of its result and, if they don't match, bail early.

The new argument is defined as a pointer to a Swift type rather than as a Swift type directly because @convention(c) functions cannot directly reference Swift types. The value of the new argument can be safely ignored if the type of the test content record's value is and always has been @frozen.

Checklist:

  • Code and documentation should follow the style of the Style Guide.
  • If public symbols are renamed or modified, DocC references should be updated.

@grynspan grynspan added bug 🪲 Something isn't working tools integration 🛠️ Integration of swift-testing into tools/IDEs labels Feb 4, 2025
@grynspan grynspan added this to the Swift 6.x milestone Feb 4, 2025
@grynspan grynspan self-assigned this Feb 4, 2025
We access the test content record section directly instead of using some
(non-existent) type-safe Swift API. On some platforms (Darwin in particular), it
is possible for two copies of the testing library to be loaded at runtime, and
for them to have incompatible definitions of types like `Test`. That means one
library's `@Test` macro could produce a test content record that is then read by
the other library's discovery logic, resulting in a stack smash or worse.

We can resolve this issue by adding a `type` argument to the accessor function
we define for test content records; the body of the accessor can then compare
the value of this argument against the expected Swift type of its result and, if
they don't match, bail early.

The new argument is defined as a pointer _to_ a Swift type rather than as a
Swift type directly because `@convention(c)` functions cannot directly reference
Swift types. The value of the new argument can be safely ignored if the type of
the test content record's value is and always has been `@frozen`.
@grynspan grynspan force-pushed the jgrynspan/add-type-arg-to-abi-accessor branch from 78d9fee to d87c257 Compare February 4, 2025 16:36
value at `type` does not match the test content record's expected type, the
accessor function must return `false` and must not modify `outValue`.

<!-- TODO: discuss this argument's value in Embedded Swift (no metatypes) -->
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In Embedded Swift, we can just say "the value of this argument is unspecified."

@grynspan
Copy link
Contributor Author

grynspan commented Feb 4, 2025

@swift-ci test

@grynspan
Copy link
Contributor Author

grynspan commented Feb 4, 2025

@swift-ci test

@grynspan
Copy link
Contributor Author

grynspan commented Feb 4, 2025

@swift-ci test Windows

Copy link
Contributor

@stmontgomery stmontgomery left a comment

Choose a reason for hiding this comment

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

LGTM. Is it important that the mechanism to distinguish records be the type of outValue, in particular? Or could it be something else? Just curious what led to that choice

@grynspan
Copy link
Contributor Author

grynspan commented Feb 4, 2025

LGTM. Is it important that the mechanism to distinguish records be the type of outValue, in particular? Or could it be something else? Just curious what led to that choice

The implementation actually does use a different type for Test for technical reasons (non-nominal types). Making it the same type by default simplifies the discovery machinery, because it means it has a reasonable default value to pass for the argument.

If/when we make the TestContent protocol public, I don't know if we'll want to expose that bit too, but we'll see.

@grynspan grynspan merged commit 900bf8c into main Feb 4, 2025
3 checks passed
@grynspan grynspan deleted the jgrynspan/add-type-arg-to-abi-accessor branch February 4, 2025 18:04
@grynspan grynspan added the discovery 🔎 test content discovery label Mar 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug 🪲 Something isn't working discovery 🔎 test content discovery tools integration 🛠️ Integration of swift-testing into tools/IDEs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants