Skip to content

OpenBSD support. #349

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 6 commits into from
Apr 17, 2025
Merged

OpenBSD support. #349

merged 6 commits into from
Apr 17, 2025

Conversation

3405691582
Copy link
Contributor

@3405691582 3405691582 commented Apr 5, 2025

OpenBSD support.

Checklist

  • I've run tests to see all new and existing tests pass
  • I've followed the code style of the rest of the project
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary (not necessary)

If you've made changes to gyb files

  • I've run .script/generate_boilerplate_files_with_gyb and included updated generated files in a commit of this pull request (not applicable)

Motivation:

swift-crypto is a required dependency for swift-package-manager, and must build and run on OpenBSD.

Modifications:

OpenBSD support for cmake/swiftpm.

* Add to patterns for CMakeLists. Also provide a helpful error so future
  porters have a slightly better idea of what might need to be updated.

* Proactively reverse sense in some system name checks so they read as
  "if not Darwin". This is likely safer to do here than elsewhere since
  there are likely not going to be other platforms for which swift-crypto
  already exists.

* Add to Package.swift

ManagedBuffer.capacity is unavailable on OpenBSD.

ManagedBuffer.capacity depends on malloc introspection (e.g.,
`malloc_size`), which is not available on this platform -- and is thus
marked as such.

Here, SecureBytes uses a ManagedBuffer in Backing. We have capacity
tracked in the BackingHeader, and most of the references to the
ManagedBuffer.capacity property can be replaced with references to the
capacity in the header. However, since capacity in the header is marked
as internal which conflicts with some of the @inline functions, so we
must change those to @usableFromInline for the platform as well.

Add conditional for RandomBytes.

Required for tests to build on OpenBSD.

Result:

swift-crypto builds and runs on OpenBSD.

* Add to patterns for CMakeLists. Also provide a helpful error so future
  porters have a slightly better idea of what might need to be updated.

* Proactively reverse sense in some system name checks so they read as
  "if not Darwin". This is likely safer to do here than elsewhere since
  there are likely not going to be other platforms for which swift-crypto
  already exists.

* Add to Package.swift.
ManagedBuffer.capacity depends on malloc introspection (e.g.,
`malloc_size`), which is not available on this platform -- and is thus
marked as such.

Here, SecureBytes uses a ManagedBuffer in Backing. We have capacity
tracked in the BackingHeader, and most of the references to the
ManagedBuffer.capacity property can be replaced with references to the
capacity in the header. However, since capacity in the header is marked
as internal which conflicts with some of the @inline functions, so we
must change those to @usableFromInline for the platform as well.
As in the prior commit, ManagedBuffer.capacity is unavailable, therefore
to get the capacity here, we need to inspect the header, which is
marked as internal.
@@ -334,6 +334,8 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Linux|Android|FreeBSD" AND CMAKE_SYSTEM_PROCES
gen/bcm/vpaes-armv8-linux.S
gen/crypto/chacha-armv8-linux.S
gen/crypto/chacha20_poly1305_armv8-linux.S)
else()
Copy link
Contributor

Choose a reason for hiding this comment

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

These cmakelists.txt files are autogenerated, so you'll need to modify the generation script and then re-run it to produce this output.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't understand. The scripts don't seem to modify the CMakeLists, only the underlying source, which I'm not touching. If it helps, I can leave off the extra helpful error here. Could you elaborate a bit more?

@inlinable
/* private but inlinable */ func _withVeryUnsafeMutableBytes<T>(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T {
let capacity = self.capacity
@usableFromInline
Copy link
Contributor

Choose a reason for hiding this comment

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

Why were these dropped from @inlinable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to change these from @inlinable to @usableFromInline because the new allocatedCapacity computed property refers to BackingHeader which is internal; otherwise I would get a compiler error. If you mean the comments, then I missed there was a similar commenting convention for "private but usableFromInline" and added that back in now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, so let's push the computed property one layer out. We'd like the body of this method to be inlinable, so we can add another computed property in the outer type that is @usableFromInline, which can keep this method accessible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure I follow, sorry. _withVeryUnsafeMutableBytes and _copyBytes are extensions on SecureBytes.Backing and right now allocatedCapacity is defined on SecureBytes.Backing. If I set _copyBytes and _withVeryUnsafeMutableBytes back to @inlinable and add an extra computed property on SecureBacking, I still get errors, so I think I'm misunderstanding something.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hrm, if the two methods are on SecureBytes.Backing and allocatedCapacity is also on SecureBytes.Backing, merely making allocatedCapacity @usableFromInline should be enough to flip these back to @inlinable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The error specifically reads something like this (same for _withVeryUnsafeMutableBytes):

/tmp/swift-crypto/Sources/Crypto/Util/SecureBytes.swift:443:51: error: property 'allocatedCapacity' is internal and cannot be referenced from an '@inlinable' function
332 | 
333 |         @usableFromInline
334 |         var allocatedCapacity: Int {
    |             `- note: property 'allocatedCapacity' is not '@usableFromInline' or public
335 | #if os(OpenBSD)
336 |                 return self.header.capacity
    :
441 |     /* private but inlinable */ func _copyBytes<C: Collection>(_ bytes: C, at offset: Int) where C.Element == UInt8 {
442 |         precondition(offset >= 0)
443 |         precondition(offset + bytes.count <= self.allocatedCapacity)
    |                                                   `- error: property 'allocatedCapacity' is internal and cannot be referenced from an '@inlinable' function
444 | 
445 |         let byteRange = offset..<(offset + bytes.count)

Copy link
Contributor

Choose a reason for hiding this comment

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

That error seems...entirely wrong. It's @usableFromInline, the annotation is right here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I found an apparent workaround: adding the property to the same section that _copyBytes is in makes this work somehow.

It may be slightly more performant to special-case but select for
readability here.
Required for tests to build on OpenBSD.
@Lukasa Lukasa added the 🆕 semver/minor Adds new public API. label Apr 17, 2025
Copy link
Contributor

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

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

Nice one, this is looking good. Thanks!

@Lukasa Lukasa merged commit 0411996 into apple:main Apr 17, 2025
32 checks passed
@3405691582
Copy link
Contributor Author

As a heads-up, I think this works fine with swiftpm/swift build but not with CMake (e.g. during swiftpm bootstrap). I'll send a followup pr if I can untangle the knot.

3405691582 added a commit to 3405691582/swift-crypto that referenced this pull request Apr 18, 2025
In apple#349 we added a new computed property to handle the fact that
ManagedBuffer.capacity is unavailable on OpenBSD. In doing this, however
we encountered some strange errors about this property being `internal
and cannot be referenced from an '@inlinable' function` despite the fact
we marked it `@usableFromInline`. Moving the computed property to the
nested class extension seemed to help, but in recent versions of swift
this caused a different strange compiler error about the computed
property having the `wrong linkage`.

While I don't really understand what is happening here enough to say
whether this is a compiler bug or not, this only seems to be triggering
from `_copyBytes` and `_withVeryUnsafeMutableBytes` still. We want these
to be inlinable, so the next natural workaround seems to be to plumb the
capacity references in by argument instead of referencing `self`. This
makes the callsites a bit wordy, but it seems to work.
3405691582 added a commit to 3405691582/swift-crypto that referenced this pull request Apr 18, 2025
In apple#349 we added a new computed property to handle the fact that
ManagedBuffer.capacity is unavailable on OpenBSD. In doing this, however
we encountered some strange errors about this property being `internal
and cannot be referenced from an '@inlinable' function` despite the fact
we marked it `@usableFromInline`. Moving the computed property to the
nested class extension seemed to help, but in recent versions of swift
this caused a different strange compiler error about the computed
property having the `wrong linkage`.

While I don't really understand what is happening here enough to say
whether this is a compiler bug or not, this only seems to be triggering
from `_copyBytes` and `_withVeryUnsafeMutableBytes` still. We want these
to be inlinable, so the next natural workaround seems to be to plumb the
capacity references in by argument instead of referencing `self`. This
makes the callsites a bit wordy, but it seems to work.
@3405691582 3405691582 mentioned this pull request Apr 18, 2025
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🆕 semver/minor Adds new public API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants