You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bring swapAt example forward and talk through why the annotations exist
The code examples early in the presentation are fairly short because
they illustrate narrow points. Bring forward the `swapAt` example and
talk through why the various `unsafe` expressions make sense. Also
note why the function itself still needs to be `@unsafe` even though
it's trying to be safe.
Copy file name to clipboardExpand all lines: proposals/nnnn-strict-memory-safety.md
+36-10Lines changed: 36 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@
10
10
11
11
## Introduction
12
12
13
-
[Memory safety](https://en.wikipedia.org/wiki/Memory_safety) is a property of programming languages and their implementations that prevents programmer errors from manifesting as [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior) at runtime. Undefined behavior effectively breaks the semantic model of a language, with unpredictable results including crashes, data corruption, and otherwise-impossible program states. Such behavior can lead to hard-to-reproduce bugs as well as introduce security vulnerabilities. Various studies have shown that memory safety problems in C and C++ account for around [70% of security vulnerabilities in software](https://www.cisa.gov/sites/default/files/2023-12/The-Case-for-Memory-Safe-Roadmaps-508c.pdf).
13
+
[Memory safety](https://en.wikipedia.org/wiki/Memory_safety) is a property of programming languages and their implementations that prevents programmer errors from manifesting as [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior) at runtime. Undefined behavior effectively breaks the semantic model of a language, with unpredictable results including crashes, data corruption, and otherwise-impossible program states. Such behavior can lead to hard-to-reproduce bugs as well as introduce security vulnerabilities.
14
14
15
15
Swift provides memory safety with a combination of language affordances and runtime checking. However, Swift also deliberately includes some unsafe constructs, such as the `Unsafe` pointer types in the standard library, language features like `nonisolated(unsafe)`, and interoperability with unsafe languages like C. For most Swift developers, this is a pragmatic solution that provides an appropriate level of memory safety while not getting in the way.
16
16
@@ -106,9 +106,35 @@ extension Array<Int> {
106
106
}
107
107
```
108
108
109
-
The `unsafe` keyword here indicates the presence of unsafe code within that expression. As with `try` and `await`, it can cover multiple sources of unsafety within that expression: the call to `c_library_sum_function` is unsafe, as is the use of `buffer` and `buffer.baseAddress`, yet they are all covered by one `unsafe`.
109
+
The `unsafe` keyword here indicates the presence of unsafe code within that expression. As with `try` and `await`, it can cover multiple sources of unsafety within that expression: the call to `c_library_sum_function` is unsafe, as is the use of `buffer` and `buffer.baseAddress`, yet they are all covered by one `unsafe`.
110
110
111
-
Note that we do *not* require that the `sum` function be marked `@unsafe` just because it has unsafe code in it. The programmer may choose to indicate that `sum` is unsafe, but the assumption is that unsafe behavior is properly encapsulated when using `unsafe`. Additionally, the `@unsafe` attribute is available for all Swift code, even if it doesn't itself enable the strict safety checking described in this proposal.
111
+
Unlike `try`, `unsafe` doesn't propagate outward: we do *not* require that the `sum` function be marked `@unsafe` just because it has unsafe code in it. Similarly, the call to `withUnsafeBufferPointerSimplified` is unsafe because it involves the `UnsafeBufferPointer` type, not because it was passed a closure containing `unsafe` behavior. The programmer may choose to indicate that `sum` is unsafe, but the assumption is that unsafe behavior is properly encapsulated when using `unsafe` if the signature doesn't contain any unsafe types. Additionally, the `@unsafe` attribute and `unsafe` expression is available for all Swift code, even if it doesn't itself enable the strict safety checking described in this proposal.
112
+
113
+
### A larger example: `swapAt` on unsafe pointers
114
+
115
+
The operation `UnsafeMutableBufferPointer.swapAt` swaps the values at the given two indices in the buffer. Under the proposed strict safety mode, it would look like this:
The `swapAt` implementation uses a mix of safe and unsafe code. The code marked with `unsafe` identifies operations that Swift cannot verify memory safety for:
133
+
134
+
* Performing pointer arithmetic on `baseAddress`: Swift cannot reason about the lifetime of that underlying pointer, nor whether the resulting pointer is still within the bounds of the allocation.
135
+
* Moving and initializing the actual elements. The elements need to already be initialized.
136
+
137
+
The code itself has preconditions to ensure that the provided indices aren't out of bounds before performing the pointer arithmetic. However, there are other safety properties that cannot be checked with preconditions: that the memory associated with the pointer has been properly initialized, has a lifetime that spans the whole call, and is not being used simultaneously by any other part of the code. These safety properties are something that must be established by the *caller* of `swapAt`. Therefore, `swapAt` is marked `@unsafe` because callers of it need to reason about these properties.
112
138
113
139
### Incremental adoption
114
140
@@ -435,13 +461,13 @@ A function marked `@unsafe` is unsafe to use, so any clients that have enabled s
0 commit comments