<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://saagarjha.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://saagarjha.com/" rel="alternate" type="text/html" /><updated>2026-10-09T08:45:08+00:00</updated><id>https://saagarjha.com/feed.xml</id><title type="html">Saagar Jha</title><subtitle>Saagar Jha&apos;s website.</subtitle><entry><title type="html">Wiring Your House for Networking</title><link href="https://saagarjha.com/blog/2024/04/12/wiring-your-house-for-networking/" rel="alternate" type="text/html" title="Wiring Your House for Networking" /><published>2024-04-12T00:00:00+00:00</published><updated>2024-04-12T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2024/04/12/wiring-your-house-for-networking</id><content type="html" xml:base="https://saagarjha.com/blog/2024/04/12/wiring-your-house-for-networking/"><![CDATA[<p>You won’t know it from reading my <a href="https://saagarjha.com/">about page</a>, but I no longer live in Cupertino. I haven’t updated that for years–I don’t spend much time in Southern California anymore either. I should probably get around to changing it someday.</p>

<p>Of course, where I live now isn’t the topic of this blog post–it’s San Jose by the way–but rather that I’ve moved to a new house, where I can set up my home network the right way™. There’s not too much I can do about my ISP (though I do have fiber now, which is nice except for the part where I sell my soul to AT&amp;T). However, everything between the modem box and my computer <em>is</em> something I control, and I’ll be damned if I fail to take advantage of any of the symmetric gigabit I’m paying for. So I did what tech nerds with too much free time on their hands do: I paid to make the problem go away. In this case, this took the form of putting <a href="https://en.wikipedia.org/wiki/Category_6_cable">Category 6 cables</a> in the walls. Think of this as the dummies guide to home networking, from someone who was a dummy when he started and ended up as a dummy with some 10 gigabit backbone.</p>

<h2 id="background">Background</h2>

<p>A general rule of thumb for networking is that wires are always better than wireless. There are exceptions–which we’ll get to–but if you want something to be fast, then you should generally run a direct line as far as you can. Of course, you’re not going to plug a Lightning-to-Ethernet into your iPhone (you can literally buy anything on the internet). But if you’re sitting at your desk, as I do for most of my day, you can deal with a few wires. And you generally want wires to go between your networking equipment too. Those sleek plug-and-play wireless mesh APs? Those are basically always a scam. Seriously, don’t buy them unless you really don’t care about your networking speeds. You’ll get much better performance if you run a direct line between them.</p>

<aside>

  <p class="aside-type">Note</p>

  <p class="aside-content">We’re getting to dedicated backhaul antennas, hold your horses.</p>

</aside>

<p>At the time of writing this, networking is on a precipice where things are going to get a little strange really soon. But historically, things have been very clear, and since that’s mostly still true today we can start there.</p>

<p>When it comes to networking, wires are <em>fast</em> and <em>cheap</em>. Today you can get copper Cat6 cable, which does 10 gigabits/s for any reasonable length you’d have in your house, for pennies per meter. You can even splurge on Cat6a or Cat7 (I have a vague feeling that these are like not standard, so I kind of avoid them?) for maybe twice the price. Cat8 has a shorter length limit (but still probably good enough for most houses) and is supposed to do 40 Gbps or something and you can find it for just a tiny bit more.</p>

<p>Wireless, on the flip side, has basically always been slower than wires, more expensive, and definitely more temperamental. Wi-Fi 6, which is starting to get solid adoption on good hardware (think laptops, tablets: your IoT is going to be cursed to 802.11b/g forever…) has some insane “theoretical” speed but on a good day might give you several hundred megabits if you are within a room or two of your AP. Of course, if you move further away or the phase of the moon isn’t right you might see much less than that. If you want to go for Wi-Fi 6e or Wi-Fi 7 (which is just starting to enter the market) you’re going to be paying a pretty penny and be restricted to exclusively picking from the high end of everything.</p>

<p>This has basically been the case for the last several decades, so what’s going on <em>today</em>, in 2024?</p>

<h3 id="new-updates">New updates</h3>

<p>For years, networking basically just got better, and everyone used the same wires. We went from 10BASE-T to 100BASE-TX to 1000BASE-T and all of it worked on <a href="https://en.wikipedia.org/w/index.php?title=Category_5_cable">Cat5</a> cable if you were careful. If you wanted to play it safe or do a long run then you could go for Cat5e, which for a lot of cables is just “sike! We actually made the Cat5 cable a little better than required and it happens to be Cat5e!”. Cat6 pushes you from 2.5 Gbps to 10 Gbps carrying 10GBASE-T, and so on. All of these were typically pure copper cables that you could get for basically nothing.</p>

<p>This is not how high-speed networking is done these days. People who care (think Google, or your local crazy networking nerd) are all on fiber. They don’t use <del><a href="https://en.wikipedia.org/wiki/Registered_jack">RJ45</a></del> <a href="https://en.wikipedia.org/wiki/Modular_connector">8P8C</a>, they have SFP+ adapters that can do 100 Gbps. I don’t <em>fully</em> understand the history here, but it turns out all the hardware that works directly with copper gets really hot or something. Or maybe nobody bothered to make good ASICs for this stuff yet? But what it means is that switches are typically massive, run hot, and are at least 2-3x more expensive if you go for 2.5 Gbps and 5x more expensive at 10 Gbps. Similarly, everyone puts 1 GbE ports on their hardware but very few things will come with 2.5 Gbps or 10 Gbps Ethernet ports. Sometimes this means you get very silly products like <a href="https://store.google.com/product/nest_wifi_pro_specs">this</a> that advertise networking speeds based on their wireless capabilities that it is <em>literally impossible to feed into the device</em> because their wired ports don’t go fast enough. But you have to be careful with even “prosumer” hardware these days: many of them will still offer just a gigabit interface.</p>

<p>Overall, this actually means that if you want a network that regularly goes over a gigabit <em>now</em>, you should probably start looking at fiber. The costs actually start to become comparable as you up your speeds. On the flip side, I think unless we see major changes in copper wireless is actually going to cross it in a few years, as annoying as that will be. Most of the other problems with it with regards to reliability will stay, but it will actually probably be cheaper to just beam your network connections over a Wi-Fi 8 backhaul or something rather than upgrade all your hardware to 10 Gbps. Early wireless mesh systems would cut into your bandwidth to relay your data, but new ones almost invariably keep a high-quality dedicated antenna for this purpose. So maybe those will be the strategy for casual prosumers moving forward.</p>

<h2 id="my-plan">My plan</h2>

<p>So with that said, why did I go for Cat6 in my house? Well, for one, I don’t have hardware that does better than gigabit speeds. Almost everything just doesn’t have 2.5 or 10 GbE ports, or uses a Wi-Fi standard that can’t push beyond that. While my old house didn’t have Ethernet wired in the walls, I was actually fortunate enough to have a <a href="https://en.wikipedia.org/wiki/Multimedia_over_Coax_Alliance">MoCA</a> setup that gave me a 2.5 Gbps backbone that I had a bunch of gigabit switches set up on top of. So I am just reusing all of those in the new house too. Plus, while I can get faster internet now from my ISP (up to 5 Gbps!) I don’t really want to pay for it yet ($$$!).</p>

<p>However, the real reason–and one I don’t actually hear very often–is that my wires are actually explicitly not meant to be “future-proof”. Of course they are to some extent–I went for Cat6 instead of Cat5e because it was barely any more expensive, and provided plenty of headroom if I ever <em>do</em> update my switches and hardware over the next several years–but it’s a little more complicated than that. But it’s not actually the only thing I’m thinking of here, and for that it’s important to go over the actual installation process.</p>

<h3 id="installation-details">Installation details</h3>

<p>Going into this projct, I had basically no idea how people put wires in walls. It turned out a lot simpler than I expected, though. At a high level, you need to do the following:</p>

<ol>
  <li>Plan where you want your cables to go. Make sure you have good coverage of your house. Keep in mind that just because you have Ethernet in a room doesn’t necessarily mean it is where you want it to be: unless you want an unsightly cable running across your room, you may need to think about where specifically to place the drop in the room. Depending on your house, you might run your cables through the crawlspace, attic, or outside the house. Try to avoid super long runs for no reason.</li>
  <li>Buy supplies. Namely:
    <ul>
      <li>Your Ethernet cable. In my house I ran it through the crawlspace. If you want to pay a bunch extra you can go for “plenum” (roughly, if you run the cable through a place with airflow, it is not supposed to poison you with toxic gas when it catches fire, but you probably aren’t running your cables in ducts) or “shielded” (what it sounds like but I don’t think I need it) but to my knowledge it doesn’t really matter here and it will double your price so I saw no need to go for it.</li>
      <li>Keystones. If you aren’t familiar with these (as I was) think “Framework laptop ports, but for your walls”. You get an Ethernet female jack and it will go into a mounting slot that can fit any keystone adapter. They’re really neat actually, and look clean and professional.</li>
      <li>A wall plate with keystone holes in it. The most cost-effective way to wire your house is likely to have one central point where all the wires meet and then run a line to each room, so you probably want say one 6/12 port plate and 1-2 port plates everywhere else. Grab a couple of “blank” keystones while you’re at it to fill in the holes you’re not using.</li>
      <li>Low-voltage boxes. These go into the holes you cut in the walls and basically give the wall plate something to attach to instead of the empty space behind the drywall.</li>
      <li>Wire cutters/strippers. You’ll need this for the cables, obviously.</li>
      <li>Punch-down tool. When you wire the cable you need to basically take each twisted pair in the wire and thread it into the keystone jack in a specific order (in a certain order, of course. I picked T568B for what it’s worth, but it literally does not matter). You should watch a video on how to do this but the punch-down tool makes it far, far easier. Also grab a keystone jack holder while you’re at it.</li>
      <li>Cable tester. You can find a cheap one for like $10. You don’t <em>need</em> this but it will make you feel better that each contact is solid.</li>
    </ul>
  </li>
  <li>Figure out if you want someone to do the dirty work for you. I just paid someone to run the cables, because we already had someone in the crawlspace wiring up the car charger, which I absolutely will not touch. If not, you probably need to buy supplies and learn how to make holes in your walls, apply patch-up paint, overcome your fear of spiders under the house, etc.</li>
  <li>Run all the cable. Leave a couple feet on each end so you can terminate the wires. Especially if you mess up you want extra length cut your losses (literally, just snip off the failed try) and do it again. You’ll push the extra into the walls anyways.</li>
  <li>Terminate everything and test it before closing things up. At the central point where you have all the wires coming in you probably want to label all the wires :)</li>
  <li>Once everything works, put all the plates in and clean up.</li>
</ol>

<p>This is a decent amount of work (it took the better part of a day) but surprisingly it’s not <em>that</em> expensive, comparatively. You can get all these supplies for like $100. You can pay someone to run the cables for a few hundred dollars. This actually means that you don’t have to future-proof as hard as people tell you! Sure, it’s a little more work than clicking a button on Amazon and setting up an app, but cost-wise it’s comparable to replacing any other part of your networking hardware. I’ve spent more over the last few years on routers, adapters, and the like.</p>

<h2 id="looking-forward">Looking forward</h2>

<p>With all that, I get what I wanted: gigabit speed from basically anywhere in the house if I plug in. And I’ve placed the ports in choice locations so that I can directly wire some extra APs into the backbone to get good wireless coverage, which I’m really pleased with. For now, and the forseeable future, I think this is more than enough for my needs.</p>

<p>After that, though, it’s more complicated. The lines I put in are Cat6 so they can do 10 Gbps, assuming the right hardware on both ends. As I mentioned earlier, that hardware doesn’t seem to exist today, and it’s not clear if it will be forthcoming. If it does start rolling out, I can upgrade piecemeal–starting with the most critical equipment first, like my router and core switches–and the new wiring will truly be “future proof” for probably a decade or two.</p>

<p>Another option is that high-speed wired networking over copper never really takes off. It remains expensive and unpopular, and consumers basically all vote for faster wireless instead. In that case I think I’ll just keep using the wires for as long as feasible and then update to wireless, as unpleasant as it will feel. To that end, I’ll probably get less than a decade of use out the cabling–but that’s basically on par with the rate at which I spend on networking anyways, so I don’t feel too bad about it.</p>

<p>Finally, it might be that the future is still wired (over fiber, or something else…), which still means my Cat6 wasn’t the best decision. I definitely could have put in fiber right now, but it’s a bit more fiddly to work with and I just wasn’t comfortable with it yet. I see nothing wrong with going back in 10 years from now and putting in fiber, though. I’ll definitely be more confident about doing something like that, now that I know how to e.g. make holes in my walls and can focus on the <em>fiber</em> part specifically. Or, depending on the circumstances, the Cat6 might see a new life as a convenient transport that I equip with adapters on both ends for whatever the new technology is. Those MoCA adapters I was using in the old house? That’s basically what those are, except they run data over coaxial cable I have no use for but happens to be convenient to reuse because it’s just there. And they’re still in use, because they go to one part of my house hard to lay Ethernet cable to, which means there will always probably be some sort of conversion somewhere regardless of what new wiring I do.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[You won’t know it from reading my about page, but I no longer live in Cupertino. I haven’t updated that for years–I don’t spend much time in Southern California anymore either. I should probably get around to changing it someday.]]></summary></entry><entry><title type="html">Making Friends with AttributeGraph</title><link href="https://saagarjha.com/blog/2024/02/27/making-friends-with-attributegraph/" rel="alternate" type="text/html" title="Making Friends with AttributeGraph" /><published>2024-02-27T00:00:00+00:00</published><updated>2024-02-27T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2024/02/27/making-friends-with-attributegraph</id><content type="html" xml:base="https://saagarjha.com/blog/2024/02/27/making-friends-with-attributegraph/"><![CDATA[<p>If you’ve used <a href="https://developer.apple.com/xcode/swiftui/">SwiftUI</a> for long enough, you’ve probably noticed that the public Swift APIs it provides are really only half the story. Normally inconspicuous unless something goes <em>exceedingly</em> wrong, the private framework called AttributeGraph tracks almost every single aspect of your app from behind the scenes to make decisions on when things need to be updated. It would not be much of an exaggeration to suggest that this C++ library is actually what runs the show, with SwiftUI just being a thin veneer on top to draw some platform-appropriate controls and provide a stable interface to program against. True to its name, AttributeGraph provides the foundation of what a declarative UI framework needs: a graph of attributes that tracks data dependencies.</p>

<p>Mastering how these dependencies work is crucial to writing advanced SwiftUI code. Unfortunately, being a private implementation detail of a closed-source framework means that searching for AttributeGraph online usually only yields results from people desperate for help with their crashes. (Being deeply unpleasant to reverse-engineer definitely doesn’t help things, though <a href="https://www.fivestars.blog/articles/lets-build-state/">some</a> <a href="https://medium.com/@kateinoigakukun/inside-swiftui-how-state-implemented-92a51c0cb5f6">have</a> <a href="https://kyleye.top/posts/demystify-attributegraph-1/">tried</a>.) Apple <a href="https://developer.apple.com/videos/play/wwdc2020/10040">has</a> <a href="https://developer.apple.com/videos/play/wwdc2021/10022">several</a> <a href="https://developer.apple.com/videos/play/wwdc2023/10160/">videos</a> that go over the high-level design, but unsurprisingly they shy away from mentioning the existence of AttributeGraph itself. Other developers do, but <a href="https://chris.eidhof.nl/presentations/day-in-the-life/">only fleetingly</a>.</p>

<p>This puts us in a real bind! We can <code class="language-plaintext highlighter-rouge">Self._printChanges()</code> all day and still not understand what is going on, especially if problems we have relate to <em>missing</em> updates rather than too many of them. To be honest, figuring out what AttributeGraph is doing internally is not all that useful unless it is not working correctly. We aren’t going to be calling those private APIs anyways, at least not easily, so there’s not much point exploring them. What’s more important is understanding what SwiftUI does and how the dependencies need to be set up to support that. We can take a leaf out of the generative AI playbook and go with the approach of just making guesses as how things are implemented. Unlike AI, we can also test our theories. We won’t know whether our speculation is right, but we can definitely check to make sure we’re not wrong!</p>

<aside class="aside-warning">

  <p class="aside-type">Warning</p>

  <p class="aside-content">If it isn’t clear already, what follows is conjecture about how a private implementation detail of SwiftUI works. It is, to my knowledge, accurate; however, it is extremely susceptible to deducing implementation details. Be cautious before relying on any of this information!</p>

</aside>

<h2 id="introducing-setting">Introducing <code class="language-plaintext highlighter-rouge">Setting</code></h2>

<p>As we explore how SwiftUI propagates changes, it will be very helpful to have an real example to work with. Say hello to <code class="language-plaintext highlighter-rouge">Setting</code>, a simple <code class="language-plaintext highlighter-rouge">UserDefaults</code> wrapper similar to <a href="https://developer.apple.com/documentation/swiftui/appstorage"><code class="language-plaintext highlighter-rouge">AppStorage</code></a>:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@propertyWrapper</span>
<span class="kd">struct</span> <span class="kt">Setting</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span> <span class="p">{</span>
	<span class="nf">init</span><span class="p">(</span><span class="n">_</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span>
	<span class="k">var</span> <span class="nv">wrappedValue</span><span class="p">:</span> <span class="kt">T</span> <span class="p">{</span> <span class="k">get</span> <span class="k">set</span> <span class="p">}</span>
	<span class="k">var</span> <span class="nv">projectedValue</span><span class="p">:</span> <span class="kt">Binding</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span> <span class="p">{</span> <span class="k">get</span> <span class="p">}</span>
	<span class="k">var</span> <span class="nv">isSet</span><span class="p">:</span> <span class="kt">Bool</span> <span class="p">{</span> <span class="k">get</span> <span class="p">}</span>
	<span class="kd">func</span> <span class="nf">reset</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We haven’t implemented it yet, but it should be fairly straightforward to see how you might use this:</p>

<!-- I should really send a PR to Rouge shouldn't I -->

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@Setting</span><span class="p">(</span><span class="s">"favoriteNumber"</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="mi">42</span><span class="p">)</span>
<span class="k">var</span> <span class="nv">favoriteNumber</span>

<span class="n">favoriteNumber</span> <span class="o">=</span> <span class="mi">69</span>
<span class="nf">print</span><span class="p">(</span><span class="n">favoriteNumber</span><span class="p">)</span> <span class="c1">// 69</span>
<span class="nf">print</span><span class="p">(</span><span class="err">$</span><span class="n">favoriteNumber</span><span class="o">.</span><span class="n">isSet</span><span class="p">)</span> <span class="c1">// true</span>
<span class="err">$</span><span class="n">favoriteNumber</span><span class="o">.</span><span class="nf">reset</span><span class="p">()</span>
<span class="nf">print</span><span class="p">(</span><span class="err">$</span><span class="n">favoriteNumber</span><span class="o">.</span><span class="n">isSet</span><span class="p">)</span> <span class="c1">// false</span>
<span class="nf">print</span><span class="p">(</span><span class="n">favoriteNumber</span><span class="p">)</span> <span class="c1">// 42</span>
</code></pre></div></div>

<p>Our API is slightly more explicit about how unset values should work, but it is otherwise almost identical to Apple’s: we even expose a <code class="language-plaintext highlighter-rouge">Binding</code> as the <code class="language-plaintext highlighter-rouge">projectedValue</code> so <code class="language-plaintext highlighter-rouge">Setting</code> can be used directly with SwiftUI controls. Here’s what a preliminary implementation might look like. None of it should be particularly surprising:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@propertyWrapper</span>
<span class="kd">struct</span> <span class="kt">Setting</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span> <span class="p">{</span>
	<span class="k">let</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span>
	<span class="k">let</span> <span class="nv">defaultValue</span><span class="p">:</span> <span class="kt">T</span>

	<span class="nf">init</span><span class="p">(</span><span class="n">_</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
		<span class="k">self</span><span class="o">.</span><span class="n">defaultValue</span> <span class="o">=</span> <span class="n">defaultValue</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="nv">wrappedValue</span><span class="p">:</span> <span class="kt">T</span> <span class="p">{</span>
		<span class="k">get</span> <span class="p">{</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">object</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="k">as?</span> <span class="kt">T</span> <span class="p">??</span> <span class="n">defaultValue</span>
		<span class="p">}</span>
		<span class="k">set</span> <span class="p">{</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">setValue</span><span class="p">(</span><span class="n">newValue</span><span class="p">,</span> <span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="nv">projectedValue</span><span class="p">:</span> <span class="kt">Binding</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span> <span class="p">{</span>
		<span class="kt">Binding</span><span class="p">(</span>
			<span class="nv">get</span><span class="p">:</span> <span class="p">{</span>
				<span class="n">wrappedValue</span>
			<span class="p">},</span>
			<span class="nv">set</span><span class="p">:</span> <span class="p">{</span>
				<span class="n">wrappedValue</span> <span class="o">=</span> <span class="nv">$0</span>
			<span class="p">}</span>
		<span class="p">)</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="nv">isSet</span><span class="p">:</span> <span class="kt">Bool</span> <span class="p">{</span>
		<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">value</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="o">!=</span> <span class="kc">nil</span>
	<span class="p">}</span>

	<span class="kd">func</span> <span class="nf">reset</span><span class="p">()</span> <span class="p">{</span>
		<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">removeObject</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This <em>almost</em> works. However, we have a compiler error in our implementation for <code class="language-plaintext highlighter-rouge">projectedValue</code>–it captures <code class="language-plaintext highlighter-rouge">self</code>, and when the <code class="language-plaintext highlighter-rouge">Binding</code> updates it tries to call <code class="language-plaintext highlighter-rouge">wrappedValue</code>’s setter. But since <code class="language-plaintext highlighter-rouge">self</code> is immutable, the compiler will not let us modify <code class="language-plaintext highlighter-rouge">wrappedValue</code>. Or will it?</p>

<p>We’re not really modifying <code class="language-plaintext highlighter-rouge">self</code> here: the setter just writes to user defaults. In particular, it doesn’t touch any members of the struct at all, so <code class="language-plaintext highlighter-rouge">self</code> doesn’t change. Swift has a special way to accommodate this: a <code class="language-plaintext highlighter-rouge">nonmutating</code> setter. This is actually what <code class="language-plaintext highlighter-rouge">State</code> uses itself to let you assign to it, even in contexts where the view that owns it is not mutable: it stores its state outside of itself, just like we do. Let’s update our implementation of <code class="language-plaintext highlighter-rouge">wrappedValue</code> to use this.</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="nv">wrappedValue</span><span class="p">:</span> <span class="kt">T</span> <span class="p">{</span>
	<span class="k">get</span> <span class="p">{</span>
		<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">object</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="k">as?</span> <span class="kt">T</span> <span class="p">??</span> <span class="n">defaultValue</span>
	<span class="p">}</span>
	<span class="k">nonmutating</span> <span class="k">set</span> <span class="p">{</span>
		<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">setValue</span><span class="p">(</span><span class="n">newValue</span><span class="p">,</span> <span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>With that, the code compiles, so let’s take it for a spin:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">struct</span> <span class="kt">ContentView</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
	<span class="kd">@Setting</span><span class="p">(</span><span class="s">"enabled"</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="kc">false</span><span class="p">)</span>
	<span class="k">var</span> <span class="nv">enabled</span>

	<span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
		<span class="kt">Toggle</span><span class="p">(</span><span class="s">"Item"</span><span class="p">,</span> <span class="nv">isOn</span><span class="p">:</span> <span class="err">$</span><span class="n">enabled</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="handling-updates">Handling updates</h2>

<p>If you copied the code above into a test project of your own, you might have noticed that it doesn’t exactly seem to work as we’d hope. You can toggle the switch all you want, but the UI doesn’t update. What’s going on? We made a <code class="language-plaintext highlighter-rouge">Binding</code> and everything!</p>

<p>With a debugger, it’s easy to verify that the <code class="language-plaintext highlighter-rouge">Toggle</code> <em>is</em> actually invoking the <code class="language-plaintext highlighter-rouge">Binding</code> callback as it should. When we flip the switch, it calls through the set implementation, and from there to our <code class="language-plaintext highlighter-rouge">wrappedValue</code> setter, which writes to user defaults. In fact if we relaunch the app the UI will read the correct state that has been being saved in user defaults all this time, so the problem is in how SwiftUI updates the view rather than the backing store for the value. Since we have a debugger attached, we can see that the getter does get called a few times, which must be how the framework sets the initial state of the view. After that, though, the UI does not update, even though the getter returns the new value. Notably, <code class="language-plaintext highlighter-rouge">ContentView</code>’s body is not evaluated again, even though it should because of the new state.</p>

<h3 id="examining-state">Examining <code class="language-plaintext highlighter-rouge">State</code></h3>

<p>If we replace <code class="language-plaintext highlighter-rouge">Setting</code> in our sample code with <code class="language-plaintext highlighter-rouge">State</code>, things work as expected. This is entirely unsurprising, because this is how we’re <em>supposed</em> to do things. Somehow SwiftUI knows when <code class="language-plaintext highlighter-rouge">State</code>s change and triggers a view update in response. To do this, it must somehow be instrumenting stores to the underlying value…wait, this is exactly what property wrappers are for! When you call the setter you get a chance to run your own code, and <code class="language-plaintext highlighter-rouge">State</code> must use it to tell SwiftUI about the change. Putting aside our earlier conversation about <code class="language-plaintext highlighter-rouge">nonmutating</code>, <code class="language-plaintext highlighter-rouge">State</code> probably looks something like this:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">struct</span> <span class="kt">State</span><span class="o">&lt;</span><span class="kt">Value</span><span class="o">&gt;</span> <span class="p">{</span>
	<span class="k">var</span> <span class="nv">_value</span><span class="p">:</span> <span class="kt">Value</span>

	<span class="k">var</span> <span class="nv">wrappedValue</span><span class="p">:</span> <span class="kt">Value</span> <span class="p">{</span>
		<span class="k">get</span> <span class="p">{</span>
			<span class="n">_value</span>
		<span class="p">}</span>
		<span class="k">set</span> <span class="p">{</span>
			<span class="n">_value</span> <span class="o">=</span> <span class="n">newValue</span>
			<span class="kt">SwiftUI</span><span class="o">.</span><span class="nf">_noteChanges</span><span class="p">(</span><span class="k">self</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Even though this explains why our code doesn’t work, this is still a problem for us, because <em>we</em> can’t call this method ourselves. It’s internal to SwiftUI, and only <code class="language-plaintext highlighter-rouge">State</code> (and the other built-in types) know how to do it. However, we don’t have to. The framework provides an affordance to let solve our issue: composing property wrappers.</p>

<h3 id="composition-with-dynamicproperty">Composition with <code class="language-plaintext highlighter-rouge">DynamicProperty</code></h3>

<p>Since only built-in types know how to update the UI, SwiftUI allows us to extend this system with <em>composition</em>. If a property wrapper contains a <code class="language-plaintext highlighter-rouge">State</code> inside of itself, then mutating it can initiate a refresh. Let’s make a few changes to the property wrapper (and skip the parts that remain unmodified):</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@propertyWrapper</span>
<span class="kd">struct</span> <span class="kt">Setting</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span> <span class="p">{</span>
	<span class="k">let</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span>
	<span class="k">let</span> <span class="nv">defaultValue</span><span class="p">:</span> <span class="kt">T</span>
	
	<span class="kd">@State</span>
	<span class="k">var</span> <span class="nv">value</span><span class="p">:</span> <span class="kt">T</span><span class="p">?</span>

	<span class="nf">init</span><span class="p">(</span><span class="n">_</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
		<span class="k">self</span><span class="o">.</span><span class="n">defaultValue</span> <span class="o">=</span> <span class="n">defaultValue</span>
		<span class="k">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">object</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="k">as?</span> <span class="kt">T</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="nv">wrappedValue</span><span class="p">:</span> <span class="kt">T</span> <span class="p">{</span>
		<span class="k">get</span> <span class="p">{</span>
			<span class="n">value</span> <span class="p">??</span> <span class="n">defaultValue</span>
		<span class="p">}</span>
		<span class="k">nonmutating</span> <span class="k">set</span> <span class="p">{</span>
			<span class="n">value</span> <span class="o">=</span> <span class="n">newValue</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">setValue</span><span class="p">(</span><span class="n">newValue</span><span class="p">,</span> <span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Note the addition of <code class="language-plaintext highlighter-rouge">value</code>, the new <code class="language-plaintext highlighter-rouge">State&lt;T&gt;</code> variable that we return instead. In the <code class="language-plaintext highlighter-rouge">wrappedValue</code> setter, we write to user defaults as before, but we also update <code class="language-plaintext highlighter-rouge">value</code>, which (as a <code class="language-plaintext highlighter-rouge">State</code>) can go and trigger a view refresh. Or, it would, but we’re not quite done yet. SwiftUI doesn’t know about the <code class="language-plaintext highlighter-rouge">State</code> we put inside our property wrapper yet: to let it peer inside and hook things up we need to conform <code class="language-plaintext highlighter-rouge">Setting</code> to the <code class="language-plaintext highlighter-rouge">DynamicProperty</code> protocol. We’ll look into why this needs to be the case a little later, but with the change this code finally works. Toggling the switch updates the UI and it also writes to defaults, and this value persists across launches. Success!</p>

<h3 id="abusing-dependencies">Abusing dependencies</h3>

<p>Even though our design works, it’s a little…unpleasant? The “source of truth” is in two places: in the <code class="language-plaintext highlighter-rouge">State</code> variable <code class="language-plaintext highlighter-rouge">value</code>, and in user defaults. <code class="language-plaintext highlighter-rouge">UserDefaults</code> is plenty fast and doesn’t need us to cache values on its behalf. The old design we had, where defaults was the backing store and we talked to it directly, was definitely cleaner. If the <code class="language-plaintext highlighter-rouge">State</code> setter’s side effects are all we need, can we clean the code up a little bit? What if we did this?</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@propertyWrapper</span>
<span class="kd">struct</span> <span class="kt">Setting</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span><span class="p">:</span> <span class="kt">DynamicProperty</span> <span class="p">{</span>
	<span class="k">let</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span>
	<span class="k">let</span> <span class="nv">defaultValue</span><span class="p">:</span> <span class="kt">T</span>
	
	<span class="kd">@State</span>
	<span class="k">var</span> <span class="nv">value</span><span class="p">:</span> <span class="kt">T</span><span class="p">?</span> <span class="o">=</span> <span class="kc">nil</span>

	<span class="nf">init</span><span class="p">(</span><span class="n">_</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
		<span class="k">self</span><span class="o">.</span><span class="n">defaultValue</span> <span class="o">=</span> <span class="n">defaultValue</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="nv">wrappedValue</span><span class="p">:</span> <span class="kt">T</span> <span class="p">{</span>
		<span class="k">get</span> <span class="p">{</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">object</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="k">as?</span> <span class="kt">T</span> <span class="p">??</span> <span class="n">defaultValue</span>
		<span class="p">}</span>
		<span class="k">nonmutating</span> <span class="k">set</span> <span class="p">{</span>
			<span class="n">value</span> <span class="o">=</span> <span class="n">newValue</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">setValue</span><span class="p">(</span><span class="n">newValue</span><span class="p">,</span> <span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Even though we store things in <code class="language-plaintext highlighter-rouge">value</code> to trigger updates, we don’t use it as the source of truth anymore. Instead, we just return whatever user defaults has in it. In the last version we were careful to have it match <code class="language-plaintext highlighter-rouge">value</code> at all times, so this should produce the same value.</p>

<p>If you try out this version, you’ll find that it doesn’t work anymore! The reason for this is actually quite subtle. If you’ve been following along so far and want a quick puzzle, see if you can debug what is going on before moving on to the next section. Hint: try printing <code class="language-plaintext highlighter-rouge">value</code> in <code class="language-plaintext highlighter-rouge">wrappedValue</code>’s getter.</p>

<hr />

<p>The hint I gave was slightly misleading. Yes, printing <code class="language-plaintext highlighter-rouge">value</code> in <code class="language-plaintext highlighter-rouge">wrappedValue</code>’s getter does tell you that its value matches what is in user defaults (well, except until it is set for the first time, but you can add that code back in and check that it doesn’t matter). But more importantly, <strong>adding the print statement makes it work again!</strong> If you remove the print statement, it stops working, and if you add it back, it works again.</p>

<p>If you test a little bit more, you’ll see that it’s not the print statement that’s important, but the access of <code class="language-plaintext highlighter-rouge">value</code> itself. Even this code works:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">get</span> <span class="p">{</span>
	<span class="n">_</span> <span class="o">=</span> <span class="n">value</span>
	<span class="k">return</span> <span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">object</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="k">as?</span> <span class="kt">T</span> <span class="p">??</span> <span class="n">defaultValue</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This is not a fluke of the optimizer. <code class="language-plaintext highlighter-rouge">State.wrappedValue</code>’s getter actually does something special: it returns the value, but it also notes to SwiftUI that the value has been “read”. This is actually how SwiftUI optimizes view updates to only change parts of the UI that matter. When invoking a view’s body, it must keep a list of all the state that is read during the pass. If any of the state changes in the future, it knows which views to update based on which ones access that state, and it will skip redrawing views that are unrelated. For us, this means that we cannot just set <code class="language-plaintext highlighter-rouge">value</code> in our setter: we also have to access it in the getter, to indicate to SwiftUI that we depend on it.</p>

<p>It’s important to note at this point that this mechanism, while clever, is also somewhat crude. SwiftUI has no idea <em>what</em> we are doing with the value, only that we have accessed it. It cannot, because we can perform arbitrary computation with it to generate all of our “derived” properties. In fact the type of the <code class="language-plaintext highlighter-rouge">State</code> we update does not have to match the eventual dependent value (you can imagine a legitimate case where the <code class="language-plaintext highlighter-rouge">wrappedValue</code> was, say, the <code class="language-plaintext highlighter-rouge">description</code> of the <code class="language-plaintext highlighter-rouge">State</code>’s value). And we don’t even have to do anything with the value we access. It’s an access for the side effects of the access, and an update for the side effects of the update. This, you could argue, is a lot worse than our proper <code class="language-plaintext highlighter-rouge">State</code>-based solution, but it’s far more flexible. Here’s what it looks like (again, skipping redundant parts):</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@propertyWrapper</span>
<span class="kd">struct</span> <span class="kt">Setting</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span><span class="p">:</span> <span class="kt">DynamicProperty</span> <span class="p">{</span>
	<span class="c1">// Dummy state that SwiftUI thinks we depend on</span>
	<span class="kd">@State</span>
	<span class="k">var</span> <span class="nv">_update</span> <span class="o">=</span> <span class="kc">false</span>

	<span class="k">var</span> <span class="nv">wrappedValue</span><span class="p">:</span> <span class="kt">T</span> <span class="p">{</span>
		<span class="k">get</span> <span class="p">{</span>
			<span class="n">_</span> <span class="o">=</span> <span class="n">_update</span>
			<span class="k">return</span> <span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">object</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="k">as?</span> <span class="kt">T</span> <span class="p">??</span> <span class="n">defaultValue</span>
		<span class="p">}</span>
		<span class="k">nonmutating</span> <span class="k">set</span> <span class="p">{</span>
			<span class="n">_update</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">setValue</span><span class="p">(</span><span class="n">newValue</span><span class="p">,</span> <span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<aside>

  <p class="aside-type">Note</p>

  <p class="aside-content">We chose a <code class="language-plaintext highlighter-rouge">State&lt;Bool&gt;</code> to update because it is small and easy to update. We do have to be a little careful here, though: if we try to be even cleverer by using <code class="language-plaintext highlighter-rouge">Void</code>, then SwiftUI actually gets out ahead of us and ignores our set because the new value we use (<code class="language-plaintext highlighter-rouge">()</code>) is equal to the old one and discards the update. In theory SwiftUI could get more “memory” and cache both the <code class="language-plaintext highlighter-rouge">true</code> and <code class="language-plaintext highlighter-rouge">false</code> states for <code class="language-plaintext highlighter-rouge">Bool</code> and prevent future updates, but we can work around this by using an <code class="language-plaintext highlighter-rouge">Int</code> and incrementing it each time instead (like a sequence number).</p>

</aside>

<h2 id="state-lifecycle"><code class="language-plaintext highlighter-rouge">State</code> lifecycle</h2>

<p>Our <code class="language-plaintext highlighter-rouge">Setting</code> is pretty neat, but it’s missing an important feature: user defaults can be updated externally, not just from the changes we make in the app. <code class="language-plaintext highlighter-rouge">UserDefaults</code> is <a href="https://developer.apple.com/documentation/foundation/userdefaults#2926902">KVO compliant</a> to allow us to respond to these changes. Since we know how to set up dependencies ourselves, updating our code to handle this isn’t too hard:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@propertyWrapper</span>
<span class="kd">struct</span> <span class="kt">Setting</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span><span class="p">:</span> <span class="kt">DynamicProperty</span> <span class="p">{</span>
	<span class="kd">class</span> <span class="kt">Observer</span><span class="p">:</span> <span class="kt">NSObject</span> <span class="p">{</span>
		<span class="k">let</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span>
		<span class="k">let</span> <span class="nv">_update</span><span class="p">:</span> <span class="kt">State</span><span class="o">&lt;</span><span class="kt">Bool</span><span class="o">&gt;</span>

		<span class="nf">init</span><span class="p">(</span><span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="nv">_update</span><span class="p">:</span> <span class="kt">State</span><span class="o">&lt;</span><span class="kt">Bool</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
			<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
			<span class="k">self</span><span class="o">.</span><span class="n">_update</span> <span class="o">=</span> <span class="n">_update</span>
			<span class="k">super</span><span class="o">.</span><span class="nf">init</span><span class="p">()</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">addObserver</span><span class="p">(</span><span class="k">self</span><span class="p">,</span> <span class="nv">forKeyPath</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span> <span class="nv">context</span><span class="p">:</span> <span class="kc">nil</span><span class="p">)</span>
		<span class="p">}</span>
		
		<span class="kd">deinit</span> <span class="p">{</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">removeObserver</span><span class="p">(</span><span class="k">self</span><span class="p">,</span> <span class="nv">forKeyPath</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
		<span class="p">}</span>

		<span class="k">override</span> <span class="kd">func</span> <span class="nf">observeValue</span><span class="p">(</span><span class="n">forKeyPath</span> <span class="nv">keyPath</span><span class="p">:</span> <span class="kt">String</span><span class="p">?,</span> <span class="n">of</span> <span class="nv">object</span><span class="p">:</span> <span class="kt">Any</span><span class="p">?,</span> <span class="nv">change</span><span class="p">:</span> <span class="p">[</span><span class="kt">NSKeyValueChangeKey</span><span class="p">:</span> <span class="kt">Any</span><span class="p">]?,</span> <span class="nv">context</span><span class="p">:</span> <span class="kt">UnsafeMutableRawPointer</span><span class="p">?)</span> <span class="p">{</span>
			<span class="n">_update</span><span class="o">.</span><span class="n">wrappedValue</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
		<span class="p">}</span>
	<span class="p">}</span>
	
	<span class="k">let</span> <span class="nv">observer</span><span class="p">:</span> <span class="kt">Observer</span>

	<span class="nf">init</span><span class="p">(</span><span class="n">_</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
		<span class="k">self</span><span class="o">.</span><span class="n">defaultValue</span> <span class="o">=</span> <span class="n">defaultValue</span>
		<span class="k">self</span><span class="o">.</span><span class="n">observer</span> <span class="o">=</span> <span class="kt">Observer</span><span class="p">(</span><span class="nv">key</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span> <span class="nv">_update</span><span class="p">:</span> <span class="n">__update</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Unfortunately, we can’t use Swift’s type-safe <code class="language-plaintext highlighter-rouge">KeyPath</code>-based callback API because <code class="language-plaintext highlighter-rouge">key</code> is a string, so we need a bit more boilerplate involving a <code class="language-plaintext highlighter-rouge">NSObject</code> subclass. We can pass it the <code class="language-plaintext highlighter-rouge">State</code> that we’re using to manage updates and it can inform SwiftUI using that when the value changes. Otherwise, everything else can stay the same.</p>

<p>As you’ve probably guessed by now, this doesn’t work. At least it doesn’t break in-app behavior this time: it just doesn’t update when changes happen externally. While the KVO callback does get invoked, poking <code class="language-plaintext highlighter-rouge">_update</code> from inside it does not have any visible effects.</p>

<h3 id="reflection-introspection">Reflection introspection</h3>

<p>Even though <code class="language-plaintext highlighter-rouge">State</code> looks opaque to us, it must maintain some private data inside of itself. At the very least, it must have some sort of identity: even though it’s a struct, it manages data that has a lifetime longer than any particular <code class="language-plaintext highlighter-rouge">State</code> instance. This state (pun unintended) is not accessible to us, but holds the key to the behavior we are seeing. Even though we are trying to update the “same” <code class="language-plaintext highlighter-rouge">State</code> in our code, something must be different about the two for one change to go through and another to get dropped.</p>

<p>Fortunately, Swift binaries typically contain fairly rich metadata that can help expose these internals for us. <code class="language-plaintext highlighter-rouge">Mirror</code> uses this to back its reflection APIs, but the debugger also knows how to read it, allowing us to poke around at the innards of types we don’t own. Let’s try that by printing <code class="language-plaintext highlighter-rouge">__update</code> (note the extra leading underscore to refer to the property wrapper itself) in <code class="language-plaintext highlighter-rouge">wrappedValue</code>, where we know it is ready to publish our changes:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="go">(lldb) po __update
</span><span class="gp">▿ State&lt;Bool&gt;</span><span class="w">
</span><span class="go">- _value : false
</span><span class="gp">▿ _location : Optional&lt;AnyLocation&lt;Bool&gt;</span><span class="o">&gt;</span>
<span class="gp">  ▿ some : &lt;StoredLocation&lt;Bool&gt;</span>: 0x600002f88c00&gt;
</code></pre></div></div>

<p>As expected, <code class="language-plaintext highlighter-rouge">State</code> is a composite of several properties. <code class="language-plaintext highlighter-rouge">_value</code> is fairly self-explanatory, and we guessed its existence earlier. However, the other property, <code class="language-plaintext highlighter-rouge">_location</code>, is a little more enigmatic. We can drill down into it further using LLDB (for example, we can see that there is a flag called <code class="language-plaintext highlighter-rouge">_wasRead</code>, as well as a connection to AttributeGraph), but before dive too deeply let’s do the same dump in <code class="language-plaintext highlighter-rouge">Observer.observeValue(forKeyPath:of:change:context:)</code>:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="go">(lldb) po _update
</span><span class="gp">▿ State&lt;Bool&gt;</span><span class="w">
</span><span class="go">  - _value : false
  - _location : nil
</span></code></pre></div></div>

<p>Aha! This time, <code class="language-plaintext highlighter-rouge">_location</code> is <code class="language-plaintext highlighter-rouge">nil</code>. This <code class="language-plaintext highlighter-rouge">_location</code> must (among other things) contain the connection back to SwiftUI used when notifying it of changes. Since it’s not set at this point, there’s nobody there to listen to our updates.</p>

<p>It’s worth thinking about how this might happen. Even though both <code class="language-plaintext highlighter-rouge">Setting</code> and <code class="language-plaintext highlighter-rouge">Observer</code> are using the “same” <code class="language-plaintext highlighter-rouge">State</code>, they actually don’t get a coherent view of <code class="language-plaintext highlighter-rouge">_update</code>. <code class="language-plaintext highlighter-rouge">State</code>s are structs as mentioned earlier, so the <code class="language-plaintext highlighter-rouge">Observer</code> gets a <em>copy</em> of the state when it is initialized, which is when <code class="language-plaintext highlighter-rouge">Setting</code> is initialized. If we put a breakpoint in that initializer, we can see that <code class="language-plaintext highlighter-rouge">_location</code> <em>is</em> <code class="language-plaintext highlighter-rouge">nil</code> at that point. <code class="language-plaintext highlighter-rouge">Observer</code>’s own local copy is made then, and never sees any changes. On the other hand, <code class="language-plaintext highlighter-rouge">Setting</code>’s <code class="language-plaintext highlighter-rouge">_update</code> also has a <code class="language-plaintext highlighter-rouge">nil</code> <code class="language-plaintext highlighter-rouge">_location</code> at this point, but sometime in the future this changes to something valid. Who is doing it? When, and how?</p>

<p>The answer, of course, is that SwiftUI does it for us. Shortly before a view’s body is computed, it goes through and sets the <code class="language-plaintext highlighter-rouge">_location</code> on all relevant <code class="language-plaintext highlighter-rouge">State</code> variables, so that they are ready for dependency tracking. Typically, a property wrapper does not have the ability to grab context from outside of itself (for example, by looking up who owns it). SwiftUI can use reflection much like we did to discover <code class="language-plaintext highlighter-rouge">State</code> members that it needs to install <code class="language-plaintext highlighter-rouge">_location</code> on, sidestepping this issue. To discover <code class="language-plaintext highlighter-rouge">State</code> in nested types, it needs a little bit of help: this is why we had to add a <code class="language-plaintext highlighter-rouge">DynamicProperty</code> conformance earlier. In that case, it uses reflection to look for <code class="language-plaintext highlighter-rouge">DynamicProperty</code> members instead and then does a search for <code class="language-plaintext highlighter-rouge">State</code> inside of those.</p>

<p>SwiftUI does the same inside of our <code class="language-plaintext highlighter-rouge">Setting</code> property wrapper when the view that owns it goes for an update. This means that we need <code class="language-plaintext highlighter-rouge">Observer._update</code> to be set then, rather than in the initializer. Fortunately, the framework calls <a href="https://developer.apple.com/documentation/swiftui/dynamicproperty/update()-29hjo"><code class="language-plaintext highlighter-rouge">DynamicProperty.update()</code></a> at exactly the right point in time to let us do this. Let’s update <code class="language-plaintext highlighter-rouge">Setting</code> to use it:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@propertyWrapper</span>
<span class="kd">struct</span> <span class="kt">Setting</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span><span class="p">:</span> <span class="kt">DynamicProperty</span> <span class="p">{</span>
	<span class="k">let</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span>
	<span class="k">let</span> <span class="nv">defaultValue</span><span class="p">:</span> <span class="kt">T</span>

	<span class="kd">@State</span>
	<span class="k">var</span> <span class="nv">_update</span> <span class="o">=</span> <span class="kc">false</span>

	<span class="kd">class</span> <span class="kt">Observer</span><span class="p">:</span> <span class="kt">NSObject</span> <span class="p">{</span>
		<span class="k">let</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span>
		<span class="k">var</span> <span class="nv">_update</span><span class="p">:</span> <span class="kt">State</span><span class="o">&lt;</span><span class="kt">Bool</span><span class="o">&gt;!</span>

		<span class="nf">init</span><span class="p">(</span><span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span> <span class="p">{</span>
			<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
			<span class="k">super</span><span class="o">.</span><span class="nf">init</span><span class="p">()</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">addObserver</span><span class="p">(</span><span class="k">self</span><span class="p">,</span> <span class="nv">forKeyPath</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span> <span class="nv">context</span><span class="p">:</span> <span class="kc">nil</span><span class="p">)</span>
		<span class="p">}</span>
		
		<span class="kd">deinit</span> <span class="p">{</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">removeObserver</span><span class="p">(</span><span class="k">self</span><span class="p">,</span> <span class="nv">forKeyPath</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
		<span class="p">}</span>

		<span class="k">override</span> <span class="kd">func</span> <span class="nf">observeValue</span><span class="p">(</span><span class="n">forKeyPath</span> <span class="nv">keyPath</span><span class="p">:</span> <span class="kt">String</span><span class="p">?,</span> <span class="n">of</span> <span class="nv">object</span><span class="p">:</span> <span class="kt">Any</span><span class="p">?,</span> <span class="nv">change</span><span class="p">:</span> <span class="p">[</span><span class="kt">NSKeyValueChangeKey</span><span class="p">:</span> <span class="kt">Any</span><span class="p">]?,</span> <span class="nv">context</span><span class="p">:</span> <span class="kt">UnsafeMutableRawPointer</span><span class="p">?)</span> <span class="p">{</span>
			<span class="n">_update</span><span class="o">.</span><span class="n">wrappedValue</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
		<span class="p">}</span>
	<span class="p">}</span>
	
	<span class="k">let</span> <span class="nv">observer</span><span class="p">:</span> <span class="kt">Observer</span>

	<span class="nf">init</span><span class="p">(</span><span class="n">_</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
		<span class="k">self</span><span class="o">.</span><span class="n">defaultValue</span> <span class="o">=</span> <span class="n">defaultValue</span>
		<span class="k">self</span><span class="o">.</span><span class="n">observer</span> <span class="o">=</span> <span class="kt">Observer</span><span class="p">(</span><span class="nv">key</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
	<span class="p">}</span>
	
	<span class="kd">func</span> <span class="nf">update</span><span class="p">()</span> <span class="p">{</span>
		<span class="n">observer</span><span class="o">.</span><span class="n">_update</span> <span class="o">=</span> <span class="n">__update</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>With that, external updates (e.g. using <code class="language-plaintext highlighter-rouge">defaults write</code>) update the view as well. With that, our <code class="language-plaintext highlighter-rouge">Setting</code> is functional and ready to use with SwiftUI. Here’s the final version that we created, for reference:</p>

<aside>

  <details>
    <summary>

      <p class="aside-type"><code class="language-plaintext highlighter-rouge">Preference.swift</code></p>

    </summary>

    <div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@propertyWrapper</span>
<span class="kd">struct</span> <span class="kt">Setting</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span><span class="p">:</span> <span class="kt">DynamicProperty</span> <span class="p">{</span>
	<span class="k">let</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span>
	<span class="k">let</span> <span class="nv">defaultValue</span><span class="p">:</span> <span class="kt">T</span>

	<span class="kd">@State</span>
	<span class="k">var</span> <span class="nv">_update</span> <span class="o">=</span> <span class="kc">false</span>

	<span class="kd">class</span> <span class="kt">Observer</span><span class="p">:</span> <span class="kt">NSObject</span> <span class="p">{</span>
		<span class="k">let</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span>
		<span class="k">var</span> <span class="nv">_update</span><span class="p">:</span> <span class="kt">State</span><span class="o">&lt;</span><span class="kt">Bool</span><span class="o">&gt;!</span>

		<span class="nf">init</span><span class="p">(</span><span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span> <span class="p">{</span>
			<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
			<span class="k">super</span><span class="o">.</span><span class="nf">init</span><span class="p">()</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">addObserver</span><span class="p">(</span><span class="k">self</span><span class="p">,</span> <span class="nv">forKeyPath</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span> <span class="nv">context</span><span class="p">:</span> <span class="kc">nil</span><span class="p">)</span>
		<span class="p">}</span>
		
		<span class="kd">deinit</span> <span class="p">{</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">removeObserver</span><span class="p">(</span><span class="k">self</span><span class="p">,</span> <span class="nv">forKeyPath</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
		<span class="p">}</span>

		<span class="k">override</span> <span class="kd">func</span> <span class="nf">observeValue</span><span class="p">(</span><span class="n">forKeyPath</span> <span class="nv">keyPath</span><span class="p">:</span> <span class="kt">String</span><span class="p">?,</span> <span class="n">of</span> <span class="nv">object</span><span class="p">:</span> <span class="kt">Any</span><span class="p">?,</span> <span class="nv">change</span><span class="p">:</span> <span class="p">[</span><span class="kt">NSKeyValueChangeKey</span><span class="p">:</span> <span class="kt">Any</span><span class="p">]?,</span> <span class="nv">context</span><span class="p">:</span> <span class="kt">UnsafeMutableRawPointer</span><span class="p">?)</span> <span class="p">{</span>
			<span class="n">_update</span><span class="o">.</span><span class="n">wrappedValue</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
		<span class="p">}</span>
	<span class="p">}</span>
	
	<span class="k">let</span> <span class="nv">observer</span><span class="p">:</span> <span class="kt">Observer</span>

	<span class="nf">init</span><span class="p">(</span><span class="n">_</span> <span class="nv">key</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="n">defaultValue</span><span class="p">:</span> <span class="kt">T</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
		<span class="k">self</span><span class="o">.</span><span class="n">defaultValue</span> <span class="o">=</span> <span class="n">defaultValue</span>
		<span class="k">self</span><span class="o">.</span><span class="n">observer</span> <span class="o">=</span> <span class="kt">Observer</span><span class="p">(</span><span class="nv">key</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="nv">wrappedValue</span><span class="p">:</span> <span class="kt">T</span> <span class="p">{</span>
		<span class="k">get</span> <span class="p">{</span>
			<span class="n">_</span> <span class="o">=</span> <span class="n">_update</span>
			<span class="k">return</span> <span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">object</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="k">as?</span> <span class="kt">T</span> <span class="p">??</span> <span class="n">defaultValue</span>
		<span class="p">}</span>
		<span class="k">nonmutating</span> <span class="k">set</span> <span class="p">{</span>
			<span class="n">_update</span><span class="o">.</span><span class="nf">toggle</span><span class="p">()</span>
			<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">setValue</span><span class="p">(</span><span class="n">newValue</span><span class="p">,</span> <span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="nv">projectedValue</span><span class="p">:</span> <span class="kt">Binding</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span> <span class="p">{</span>
		<span class="kt">Binding</span><span class="p">(</span>
			<span class="nv">get</span><span class="p">:</span> <span class="p">{</span>
				<span class="n">wrappedValue</span>
			<span class="p">},</span>
			<span class="nv">set</span><span class="p">:</span> <span class="p">{</span>
				<span class="n">wrappedValue</span> <span class="o">=</span> <span class="nv">$0</span>
			<span class="p">}</span>
		<span class="p">)</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="nv">isSet</span><span class="p">:</span> <span class="kt">Bool</span> <span class="p">{</span>
		<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">value</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span> <span class="o">!=</span> <span class="kc">nil</span>
	<span class="p">}</span>

	<span class="kd">func</span> <span class="nf">reset</span><span class="p">()</span> <span class="p">{</span>
		<span class="kt">UserDefaults</span><span class="o">.</span><span class="n">standard</span><span class="o">.</span><span class="nf">removeObject</span><span class="p">(</span><span class="nv">forKey</span><span class="p">:</span> <span class="n">key</span><span class="p">)</span>
	<span class="p">}</span>
	
	<span class="kd">func</span> <span class="nf">update</span><span class="p">()</span> <span class="p">{</span>
		<span class="n">observer</span><span class="o">.</span><span class="n">_update</span> <span class="o">=</span> <span class="n">__update</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>    </div>

  </details>

</aside>

<p>While it is probably not worth using this code directly in your app (note the disclaimer above!), understanding how and why it works the way it does might be helpful in debugging your own SwiftUI projects.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[If you’ve used SwiftUI for long enough, you’ve probably noticed that the public Swift APIs it provides are really only half the story. Normally inconspicuous unless something goes exceedingly wrong, the private framework called AttributeGraph tracks almost every single aspect of your app from behind the scenes to make decisions on when things need to be updated. It would not be much of an exaggeration to suggest that this C++ library is actually what runs the show, with SwiftUI just being a thin veneer on top to draw some platform-appropriate controls and provide a stable interface to program against. True to its name, AttributeGraph provides the foundation of what a declarative UI framework needs: a graph of attributes that tracks data dependencies.]]></summary></entry><entry><title type="html">Swift Concurrency Waits for No One</title><link href="https://saagarjha.com/blog/2023/12/22/swift-concurrency-waits-for-no-one/" rel="alternate" type="text/html" title="Swift Concurrency Waits for No One" /><published>2023-12-22T00:00:00+00:00</published><updated>2023-12-22T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2023/12/22/swift-concurrency-waits-for-no-one</id><content type="html" xml:base="https://saagarjha.com/blog/2023/12/22/swift-concurrency-waits-for-no-one/"><![CDATA[<blockquote>
  <p>There was once a master engineer who lived by herself in a mystical, far off place, where nourishment flowed freely and the dirt beneath your feet was more valuable than gold. Inaccessible even by foot, only very few could make the trip for a chance at receiving her wisdom. A novice programmer, enthusiastic but still wet behind the ears, visited her one day.</p>

  <p>“I have read your code,” he began, “and I can only describe it as sublime. But, I’ve been learning a lot about Swift Concurrency and I see that you don’t use it all the time. Why is that?”</p>

  <p>The master engineer replied promptly with a question of her own: “Tell me, how would an asynchronous program call synchronous code?”</p>

  <p>“That’s easy,” he replied. “You can just call it directly.”</p>

  <p>“Now, how would one invoke asynchronous code from a synchronous context?”</p>

  <p>“Spawn a <code class="language-plaintext highlighter-rouge">Task</code>, obviously!” replied the novice engineer, glad that his studies had come in handy.</p>

  <p>The master engineer smiled. “Very good. But now, imagine waiting for the work to complete before proceeding. What then? The API, naturally, is provided by the system and cannot be redesigned.”</p>

  <p>This troubled the novice, and he furrowed his brow in concentration for some time. Finally, a half-forgotten memory came back to him: “<code class="language-plaintext highlighter-rouge">DispatchSemaphore</code>! I can use a semaphore to wait for the asynchronous work!”</p>

  <p>“Swift Concurrency requires tasks to make forward progress”, responded the master engineer. Then she fell silent. After a while, the novice was enlightened.</p>
</blockquote>

<h2 id="background">Background</h2>

<p><a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/">Swift Concurrency</a> promises to make it possible to write correct, performant code designed for today’s world of asynchronous events and ubiquitous hardware parallelism. And indeed, when wielded appropriately it does exactly that. However–much like an iceberg–the simple APIs it exposes hide a staggering amount of complexity underneath. Unfortunately, concurrency is a challenging topic to reason about when compared to straight-line, synchronous code, and it is difficult for any programming model to paper over all of its subtleties.</p>

<p>Concurrency is nothing new for most Swift developers, of course. Those programming for Apple’s platforms are almost certainly aware of <a href="https://developer.apple.com/documentation/dispatch">Grand Central Dispatch</a>, or even other APIs such as <a href="https://en.wikipedia.org/wiki/Pthreads">POSIX threads</a>. Many applications will use several of these at once! What’s novel, however, is that Swift Concurrency is an entirely different paradigm for concurrent programming, governed by a completely new set of rules. The penalties for violating these conditions are, on occasion, just as severe as they were for the technologies that came before it–unintentional reentrancy, deadlocks, even data corruption. Thankfully, one of the major selling points for Swift Concurrency is that the compiler tries to enforce many of the rules for us. Often, code that violates the guidelines will fail to build! Other rules are well documented and easy to follow, even if they aren’t checked by the compiler. Some invariants are unconditionally validated at runtime when practical, and others are available as opt-in debug checks.</p>

<p>Despite being critical for writing correct programs, sometimes the rules are less clear (or not mentioned at all). While the runtime is open source, it is constantly evolving and difficult for non-experts to understand. In pathological cases, it may be impossible to write certain code using Swift Concurrency, but easy to construct something that seems like it works–whether it be due to bugs, implementation details of the runtime, or even just plain luck. As a result, a successful practitioner needs a firm grasp of how to reason about the correctness of their code. We will explore one way to analyze programs by tackling what has historically been a problematic area for many developers: Swift Concurrency’s concept of forward progress.</p>

<h2 id="concurrency-and-parallelism">Concurrency and Parallelism</h2>

<p>If you’re coming from the world of threads and queues, Swift Concurrency can look somewhat similar on the surface: you can kick off tasks to run asynchronously and wait on their completion, just like you might with older APIs. In many instances, a model of the runtime having “unlimited threads” to run the work we schedule is sufficient for understanding whether some code is correct or not. Obviously, Swift Concurrency manages its own cooperative thread pool under the hood, so we don’t actually spawn infinitely many threads, but in these cases it’s easy to treat the runtime as “magically” doing the right thing for us.</p>

<p>Occasionally, however, the nature of the cooperative thread pool becomes very important. This is one of those times. Before we talk about how, we need to go over two important terms: concurrency and parallelism. If you’re like me your recollection probably extends to them having something to do with managing several jobs at once, but not much further. After all, you can just look up their exact definitions when you need them. That said, the difference matters here so you can review them now or come back if you forget:</p>

<ul>
  <li>Concurrency lets you have multiple tasks “in progress” (that is: not completed) at any given time.</li>
  <li>Parallelism enables running multiple tasks that are actively executing at the same time.</li>
</ul>

<p>Less abstractly, when you stop coding and start replying to a message from your boss on Slack, you’re practicing <em>concurrency</em>. Likewise, when you’re scrolling through Hacker News while sitting through a boring meeting you’re showing off your <em>parallelism</em> skills. How this usually works out in practice for computers is that concurrent scheduling of tasks involves slicing them up and interleaving the parts, while parallel scheduling requires multiple “cores”. Note that it is possible to have concurrency without parallelism: a single-core machine does not have the ability to do any work in parallel, but it will typically context switch between multiple tasks.</p>

<p>Swift Concurrency (as its name suggests) is a system for <em>concurrently</em> scheduling tasks. One core feature of its implementation is that it can transparently scale to take advantage of all the parallelism on the system, but this detail is exactly that: an <em>implementation</em> detail. A correctly written program will, for the most part, not be able to tell the difference between a single thread and a hundred.</p>

<aside class="aside-fun-fact">

  <p class="aside-type">Fun fact</p>

  <p class="aside-content">Typically the underlying cooperative pool is scaled to match the number of cores on the system, since (at least in theory) there isn’t much point scheduling more tasks than that at once. However, the runtime is free to choose fewer or greater threads at its discretion. For example, older versions of the iOS simulator used to set the pool size to one, and the <code class="language-plaintext highlighter-rouge">DISPATCH_COOPERATIVE_POOL_STRICT</code> environment variable lets you opt into this width for debugging purposes.</p>

</aside>

<h2 id="forward-progress">Forward progress</h2>

<p>Forward progress, roughly speaking, means that something needs to be able to keep doing work. A program that makes forward progress can “wait” (e.g. by taking locks, sleeping, or performing I/O) but there must always be a way for it to come out of the wait. One simple example of a program that is not making forward progress is one that is stuck in an infinite loop, because it’s never going to be able to do anything else no matter what you try or how long you wait.</p>

<p>In Swift Concurrency, one central rule is that <strong><a href="https://developer.apple.com/videos/play/wwdc2021/10254/?time=1450">all tasks on the cooperative thread pool must make forward progress</a></strong>. Violating this rule will result in deadlocks. With that in mind, can we say anything about the following code?</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="nv">semaphore</span> <span class="o">=</span> <span class="kt">DispatchSemaphore</span><span class="p">(</span><span class="nv">value</span><span class="p">:</span> <span class="mi">0</span><span class="p">)</span>

<span class="kd">func</span> <span class="nf">wait</span><span class="p">()</span> <span class="k">async</span> <span class="p">{</span>
	<span class="n">semaphore</span><span class="o">.</span><span class="nf">wait</span><span class="p">()</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">signal</span><span class="p">()</span> <span class="k">async</span> <span class="p">{</span>
	<span class="n">semaphore</span><span class="o">.</span><span class="nf">signal</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>You may have heard that <code class="language-plaintext highlighter-rouge">DispatchSemaphore</code> is unsafe to use with Swift Concurrency. The warnings when you build this also point towards that. But why? What is wrong with it?</p>

<p>To start with, we know that <code class="language-plaintext highlighter-rouge">wait()</code> and <code class="language-plaintext highlighter-rouge">signal()</code> are both <code class="language-plaintext highlighter-rouge">async</code> functions, meaning they will be called on the cooperative thread pool. We also know that all tasks here need to make forward progress. We can spot potential trouble immediately: <code class="language-plaintext highlighter-rouge">wait()</code> calls <code class="language-plaintext highlighter-rouge">DispatchSemaphore.wait()</code>, which blocks the current thread without notifying the runtime about it as <code class="language-plaintext highlighter-rouge">await</code> is designed to do. When this happens nothing else can run on that thread until it returns, and this means that it can arbitrarily block forward progress of this task forever.</p>

<p>“But wait!”, you say. “Who said anything about blocking forward progress <em>forever</em>? Of course I plan to call <code class="language-plaintext highlighter-rouge">signal()</code> at some point in the future, and <em>that</em> will unblock the <code class="language-plaintext highlighter-rouge">wait()</code> call. See, I can make sure there is forward progress!” However, even if you balance all your calls to <code class="language-plaintext highlighter-rouge">wait()</code> and <code class="language-plaintext highlighter-rouge">signal()</code>, this code can still deadlock. How? The answer requires going back to our discussion of parallelism.</p>

<p>The Swift cooperative thread pool is allowed to be any size. This means it can have exactly one thread in it. What happens when you call <code class="language-plaintext highlighter-rouge">wait()</code> in this scenario? It blocks the sole thread, which means that any future call to <code class="language-plaintext highlighter-rouge">signal()</code> will never get a chance to be scheduled. It cannot: it <em>has</em> to go on the cooperative thread pool, and there are no threads available. Ergo, deadlock.</p>

<aside>

  <p class="aside-type">Note</p>

  <p class="aside-content">If you didn’t read the previous fun fact, you should probably read it now. We’ll proceed without it, though, since it’s not critical to the argument. It is an aside, after all.</p>

</aside>

<p>“Hold on!”, you protest again. “This is stupid. Why do we even care about a cooperative thread pool of size one? I understand that this is wrong <em>theoretically</em> but in practice this is never going to break because there are always more threads.” Ok, but you’re still looking at deadlocks. Why? Because I know you’re not going to write code like my example. Instead, you’ll likely write this:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">actor</span> <span class="kt">Lock</span> <span class="p">{</span>
	<span class="k">let</span> <span class="nv">semaphore</span> <span class="o">=</span> <span class="kt">DispatchSemaphore</span><span class="p">(</span><span class="nv">value</span><span class="p">:</span> <span class="mi">0</span><span class="p">)</span>

	<span class="kd">func</span> <span class="nf">lock</span><span class="p">()</span> <span class="p">{</span>
		<span class="n">semaphore</span><span class="o">.</span><span class="nf">wait</span><span class="p">()</span>
	<span class="p">}</span>

	<span class="kd">func</span> <span class="nf">unlock</span><span class="p">()</span> <span class="p">{</span>
		<span class="n">semaphore</span><span class="o">.</span><span class="nf">signal</span><span class="p">()</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Who writes an app with just one semaphore? And if you are going to have a bunch, you might as well name them and all. The name doesn’t matter, obviously; the important part is what happens when all threads in your app happen to call <code class="language-plaintext highlighter-rouge">lock()</code> at the same time. This will only happen rarely, but when it does, no further work can happen on the cooperative thread pool and you’re deadlocked again. There’s nothing special about <code class="language-plaintext highlighter-rouge">Lock</code>: it’s just a stand-in for the more general problem of blocking on multiple threads at once and starving the cooperative pool until it can’t service new work anymore.</p>

<h2 id="waiting-on-async-work">Waiting on <code class="language-plaintext highlighter-rouge">async</code> work</h2>

<p>Let’s look at a more complicated example. Let’s say we have an API for borrowing books. It predates Swift Concurrency and uses a delegate interface:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">protocol</span> <span class="kt">LibraryDelegate</span> <span class="p">{</span>
	<span class="kd">func</span> <span class="nf">shouldLend</span><span class="p">(</span><span class="n">_</span> <span class="nv">book</span><span class="p">:</span> <span class="kt">Book</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Bool</span>
<span class="p">}</span>
</code></pre></div></div>

<p>When the user goes to borrow a book, the framework lets the delegate dissent (maybe they have unpaid fines?). A (simplified) implementation might look like this:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="kt">CheckoutMachine</span><span class="p">:</span> <span class="kt">LibraryDelegate</span> <span class="p">{</span>
	<span class="kd">func</span> <span class="nf">shouldLend</span><span class="p">(</span><span class="n">_</span> <span class="nv">book</span><span class="p">:</span> <span class="kt">Book</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Bool</span> <span class="p">{</span>
		<span class="k">let</span> <span class="nv">account</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="nf">lookupAccount</span><span class="p">(</span><span class="nv">forCardNumber</span><span class="p">:</span> <span class="n">cardNumber</span><span class="p">)</span>
		<span class="k">return</span> <span class="o">!</span><span class="n">account</span><span class="o">.</span><span class="n">hasFines</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This is a great start, but the library would also like to make sure that we don’t check out a book that someone has placed on hold. This could be another library patron, or it can be a researcher at a local university they’ve set up a catalog-sharing partnership with. Thankfully we have some code for this, too. Interacting with the university system can be a bit slow, but the implementation to talk to it is a little more modern:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="kt">HoldManager</span> <span class="p">{</span>
	<span class="kd">func</span> <span class="nf">holds</span><span class="p">(</span><span class="n">on</span> <span class="nv">book</span><span class="p">:</span> <span class="kt">Book</span><span class="p">)</span> <span class="k">async</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="kt">Account</span><span class="p">]</span> <span class="p">{</span>
		<span class="k">let</span> <span class="nv">libraryHolds</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="nf">holds</span><span class="p">(</span><span class="nv">on</span><span class="p">:</span> <span class="n">book</span><span class="p">)</span>
		<span class="c1">// This reaches out to the university system to see if someone reserved it</span>
		<span class="k">let</span> <span class="nv">universityHolds</span> <span class="o">=</span> <span class="k">await</span> <span class="n">university</span><span class="o">.</span><span class="nf">holds</span><span class="p">(</span><span class="nv">on</span><span class="p">:</span> <span class="n">book</span><span class="p">)</span>
		<span class="k">return</span> <span class="n">libraryHolds</span> <span class="o">+</span> <span class="n">universityHolds</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Now we just update <code class="language-plaintext highlighter-rouge">shouldLend(_:)</code> to use thi…wait. This is an <code class="language-plaintext highlighter-rouge">async</code> function, which means we need to <code class="language-plaintext highlighter-rouge">await</code> its result. But <code class="language-plaintext highlighter-rouge">shouldLend(_:)</code> is synchronous! How can we make this work?</p>

<p>Clearly, we need to wait for the task to finish somehow. This problem–making asynchronous work synchronous–is super common when interfacing with Swift Concurrency from older code that was designed without it in mind. Bridging synchronous and asynchronous code has never been easy, but in the past we might have used a semaphore for situations like this one. This has its own issues, but in general it will not block forward progress.</p>

<aside>

  <p class="aside-type">Note</p>

  <p class="aside-content">The primary issue being the potential for priority inversion when waiting on discretionary work from a high-priority thread, which, depending on system conditions, may not be resolved until an arbitrary point in the future. Since fixing this takes “a while” and not “forever” it isn’t a true deadlock, but it can still be problematic: sometimes this “kinda” sucks (e.g. you drop a couple frames because your UI thread blocks); sometimes it <em>really</em> sucks (e.g. your app hangs until low power mode disengages). Friends don’t let friends use <code class="language-plaintext highlighter-rouge">DispatchSemaphore</code>.</p>

</aside>

<p>Swift Concurrency’s Task initializer is a synchronous function that takes an <code class="language-plaintext highlighter-rouge">async</code> closure, which at least matches what we are looking for. If we squint at this construction it looks a bit like how we’ve used to wait for callbacks:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">shouldLend</span><span class="p">(</span><span class="n">_</span> <span class="nv">book</span><span class="p">:</span> <span class="kt">Book</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Bool</span> <span class="p">{</span>
	<span class="kd">class</span> <span class="kt">Unreserved</span><span class="p">:</span> <span class="kd">@unchecked</span> <span class="kt">Sendable</span> <span class="p">{</span> <span class="k">var</span> <span class="nv">value</span><span class="p">:</span> <span class="kt">Bool</span><span class="o">!</span> <span class="p">}</span>
	<span class="k">let</span> <span class="nv">Unreserved</span> <span class="o">=</span> <span class="kt">Unreserved</span><span class="p">()</span>

	<span class="k">let</span> <span class="nv">semaphore</span> <span class="o">=</span> <span class="kt">DispatchSemaphore</span><span class="p">(</span><span class="nv">value</span><span class="p">:</span> <span class="mi">0</span><span class="p">)</span>
	<span class="kt">Task</span> <span class="p">{</span>
		<span class="k">let</span> <span class="nv">holds</span> <span class="o">=</span> <span class="k">await</span> <span class="n">holdManager</span><span class="o">.</span><span class="nf">holds</span><span class="p">(</span><span class="nv">on</span><span class="p">:</span> <span class="n">book</span><span class="p">)</span>
		<span class="n">unreserved</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">holds</span><span class="o">.</span><span class="n">isEmpty</span>
		<span class="n">semaphore</span><span class="o">.</span><span class="nf">signal</span><span class="p">()</span>
	<span class="p">}</span>
	<span class="n">semaphore</span><span class="o">.</span><span class="nf">wait</span><span class="p">()</span>

	<span class="k">let</span> <span class="nv">account</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="nf">lookupAccount</span><span class="p">(</span><span class="nv">forCardNumber</span><span class="p">:</span> <span class="n">cardNumber</span><span class="p">)</span>
	<span class="k">return</span> <span class="o">!</span><span class="n">account</span><span class="o">.</span><span class="n">hasFines</span> <span class="o">&amp;&amp;</span> <span class="n">unreserved</span><span class="o">.</span><span class="n">value</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Because what we’re doing is somewhat unusual, we need a little bit of ceremony to hoist the results out of the <code class="language-plaintext highlighter-rouge">Task</code>. Despite its unsightly appearance, the <code class="language-plaintext highlighter-rouge">@unchecked Sendable</code> and implicitly unwrapped optional are fine, since our control flow guarantees initialization and exclusive access. Is this code correct, though?</p>

<p>At first glance, this seems like it might be OK: even though we’re using <code class="language-plaintext highlighter-rouge">DispatchSemaphore</code>, this time we only <em>signal</em> from an asynchronous context. The blocking wait is on a code path that doesn’t “know” about Swift Concurrency at all. However, this can still deadlock!</p>

<h3 id="analysis">Analysis</h3>

<p>The rationale for this is not obvious, even though it can be described quite simply: the reason the code deadlocks is that <code class="language-plaintext highlighter-rouge">shouldLend(_:)</code> might end up being called on the cooperative pool, even though it is a synchronous, pre-Swift Concurrency callback. Here’s the actual backtrace of the call for <code class="language-plaintext highlighter-rouge">shouldLend(_:)</code>:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">* thread #</span>2, queue <span class="o">=</span> <span class="s1">'com.apple.root.default-qos.cooperative'</span>
<span class="gp">  * frame #</span>0: App<span class="sb">`</span>CheckoutMachine.shouldLend<span class="o">(</span>_: Book<span class="o">)</span>
<span class="gp">    frame #</span>1: LibraryCore<span class="sb">`</span>Library.checkLendability<span class="o">(</span>of: Book<span class="o">)</span>
<span class="gp">    frame #</span>2: LibraryCore<span class="sb">`</span>Library.reallyDoCheckout<span class="o">(</span>of: Book, from: Catalog<span class="o">)</span>
<span class="gp">    frame #</span>3: LibraryCore<span class="sb">`</span>Library.checkoutCommonImpl<span class="o">(</span>book: Book<span class="o">)</span>
<span class="gp">    frame #</span>4: LibraryCore<span class="sb">`</span>Library.checkout<span class="o">(</span>_: Book<span class="o">)</span>
<span class="gp">    frame #</span>5: App<span class="sb">`</span>CheckoutMachine.checkoutBooks<span class="o">()</span> async throws
</code></pre></div></div>

<p>It’s on the cooperative thread pool! This is because in another part of our app, we used <code class="language-plaintext highlighter-rouge">Library.checkout(_:)</code> from an <code class="language-plaintext highlighter-rouge">async</code> context, and LibraryCore ended up calling our delegate method. This is bad news, because in our implementation the semaphore blocks this thread. If we reduce parallelism to one, the <code class="language-plaintext highlighter-rouge">Task</code> we kick off doesn’t get a chance to start, and because we rely on its work to signal the semaphore we’re waiting on we have yet another deadlock.</p>

<p>This analysis might feel somewhat unfair, since I didn’t tell you anything about the rest of <code class="language-plaintext highlighter-rouge">CheckoutMachine</code> or LibraryCore. But that’s the point: we broke the guarantee of forward progress in a surprising, nonlocal way. Even if you have a handle on all the code in your own app (a tall order for any complex project!) the forward progress guarantee depends on scheduling decisions of <em>every single function in your call stack</em>, many of which you may not own or even have the source code to. Needless to say, whether something decides to run its code synchronously, on an internal queue, or even use Swift Concurrency itself is an implementation detail you can’t rely on.</p>

<h2 id="forward-progress-in-legacy-code">Forward progress in legacy code</h2>

<p>It’s probably obvious at this point that blocking in concurrently-executing code is a recipe for deadlocks. There’s a second part to our analysis, though, and it centers around a question you might have had yourself if you read the review above: how can we safely call arbitrary code at all, if we’re not allowed to block the cooperative thread pool? After all, some library we use might be implemented internally using a semaphore. Is this a problem for us?</p>

<p>Experimentally, the answer is “no”: well behaved Swift Concurrency code does not appear to deadlock, regardless of how the libraries it depends on choose to synchronize themselves. Somehow <em>we’re</em> not allowed to block or wait, but the code we call synchronously <em>is</em>. <code class="language-plaintext highlighter-rouge">DispatchSemaphore</code> can’t be smart enough to know the difference…or is it? Is it capable of punishing us with hangs when we misbehave?</p>

<p>Needless to say, this isn’t the case, but the real reason is subtle. We know that code which predates Swift Concurrency might end up running on the cooperative thread pool, but it won’t choose to do so <em>itself</em>. Library code like this is quite common:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">foo</span><span class="p">()</span> <span class="p">{</span>
	<span class="k">let</span> <span class="nv">semaphore</span> <span class="o">=</span> <span class="kt">DispatchSemaphore</span><span class="p">(</span><span class="nv">value</span><span class="p">:</span> <span class="mi">0</span><span class="p">)</span>
	<span class="nf">doSomeAsynchronousWork</span><span class="p">(</span><span class="nv">completion</span><span class="p">:</span> <span class="p">{</span>
		<span class="n">semaphore</span><span class="o">.</span><span class="nf">signal</span><span class="p">()</span>
	<span class="p">})</span>
	<span class="n">semaphore</span><span class="o">.</span><span class="nf">wait</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Even though this looks a lot like our example from above, we can generally call it safely, even from an <code class="language-plaintext highlighter-rouge">async</code> context. Because this code predates Swift Concurrency, it’s not going to spawn a <code class="language-plaintext highlighter-rouge">Task</code> to do the asynchronous work like we did in our example earlier. It might do a <code class="language-plaintext highlighter-rouge">dispatch_async</code>, XPC callout, or network call, but none of these will schedule on the cooperative pool. This allows forward progress because the other work will start and complete independently, unblocking our waiting thread at some point in the future.</p>

<aside class="aside-warning">

  <p class="aside-type">Warning</p>

  <p class="aside-content">I said “generally” because there is one case where this breaks: if <code class="language-plaintext highlighter-rouge">doSomeAsynchronousWork</code> ends up being reimplemented in the future to use Swift Concurrency, such that it captures and calls the completion handler in an <code class="language-plaintext highlighter-rouge">async</code> context, then this code becomes deadlock-prone. This construction is rare today, so I’m mostly just bringing it up as a final reminder of how forward progress invariants can be violated in surprising ways. As Swift Concurrency adoption rises in the future, it’s important to remember that even small details–such as where callbacks run–can be serious API-breaking changes with the potential to cause problems for real programs.</p>

</aside>

<h2 id="takeaways">Takeaways</h2>

<p>Forward progress is a difficult concept to master. While important when reasoning about any concurrent design, in a cooperative system such as Swift Concurrency the repercussions for deadlock are much more pervasive, entangled, and usually harder to debug. Some primitives, notably techniques to wait synchronously without the use of <code class="language-plaintext highlighter-rouge">await</code>, are all but impossible to use safely from Swift Concurrency. Unfortunately, trying to build a homegrown but subtly incorrect version is far easier than analyzing why it is broken. This, paired with stochastic failures, means there’s an an awful lot of code out in the wild with a future full of hangs. (The examples in this post, for example, are derived from searches I performed on GitHub.)</p>

<p>The unwelcome truth is that some code just cannot be bridged with Swift Concurrency. In other cases, the effort needed to write this code and validate its correctness is so exceptionally high that continuing to use the technology is not well justified. This can be particularly painful if discovered long after a choice to use Swift Concurrency was made, and the only solution here (as frustrating as it might be) is to go back and rewrite the program using other APIs.</p>

<p>Despite these limitations, Swift Concurrency remains a good choice for many projects that are seeking to manage asynchronous work; it’s just important to understand which those might be. Checking for forward progress is one way we might make such a decision. This analysis can be complex, but the examples presented here should provide a place to start when thinking about the correctness of your own asynchronous code.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[There was once a master engineer who lived by herself in a mystical, far off place, where nourishment flowed freely and the dirt beneath your feet was more valuable than gold. Inaccessible even by foot, only very few could make the trip for a chance at receiving her wisdom. A novice programmer, enthusiastic but still wet behind the ears, visited her one day. “I have read your code,” he began, “and I can only describe it as sublime. But, I’ve been learning a lot about Swift Concurrency and I see that you don’t use it all the time. Why is that?” The master engineer replied promptly with a question of her own: “Tell me, how would an asynchronous program call synchronous code?” “That’s easy,” he replied. “You can just call it directly.” “Now, how would one invoke asynchronous code from a synchronous context?” “Spawn a Task, obviously!” replied the novice engineer, glad that his studies had come in handy. The master engineer smiled. “Very good. But now, imagine waiting for the work to complete before proceeding. What then? The API, naturally, is provided by the system and cannot be redesigned.” This troubled the novice, and he furrowed his brow in concentration for some time. Finally, a half-forgotten memory came back to him: “DispatchSemaphore! I can use a semaphore to wait for the asynchronous work!” “Swift Concurrency requires tasks to make forward progress”, responded the master engineer. Then she fell silent. After a while, the novice was enlightened.]]></summary></entry><entry><title type="html">Fixing Section 2.5.2</title><link href="https://saagarjha.com/blog/2020/11/08/fixing-section-2-5-2/" rel="alternate" type="text/html" title="Fixing Section 2.5.2" /><published>2020-11-08T00:00:00+00:00</published><updated>2020-11-08T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2020/11/08/fixing-section-2-5-2</id><content type="html" xml:base="https://saagarjha.com/blog/2020/11/08/fixing-section-2-5-2/"><![CDATA[<p>From its inception, applications that wished to make themselves available on the iOS App Store—the de-facto mechanism of third-party software distribution on the platform—have been required to conform to a set of guidelines laid out and enforced by Apple’s <a href="https://developer.apple.com/app-store/review/">App Review</a> process. Apple’s <a href="https://developer.apple.com/app-store/review/guidelines/">list of guidelines</a> have expanded and been amended through the years, but the focus has largely remained the same: preventing the distribution of applications that are fraudulent, malicious, contain questionable or illegal content, or undermine Apple’s business interests. Much has already been said about the review process as a whole or Apple’s choice of guidelines, but we are going to focus on one guideline that may be one of the most important of them all: the rule that dictates restrictions on downloading additional code at runtime. For the last couple years, this rule has lived in <a href="https://developer.apple.com/app-store/review/guidelines#2.5.2">section 2.5.2</a> of the guidelines, and this is the name that we will be using to refer to it.</p>

<aside>

  <p class="aside-type">Note</p>

  <p class="aside-content">For those who are unfamiliar with the premise of this post, my name is Saagar Jha, and I work as a developer, publicist, and compliance expert for iSH, the Linux shell for iOS. iSH has recently been <a href="https://ish.app/app-store-removal">found by Apple to be noncompliant</a> with the App Store Review Guidelines for reasons which we believe to be fundamental flaws in the implementation of this rule. Many of the examples provided come directly from my experience with working on iSH and the App Review process for it.</p>

</aside>

<h2 id="the-history-and-evolution-of-section-252">The history and evolution of section 2.5.2</h2>

<p>The current text of section 2.5.2 in the App Store Review Guidelines is fairly short—it’s three sentences that are just under a hundred words in total, making it concise enough to reproduce here in its entirety:</p>

<blockquote>
  <p>Apps should be self-contained in their bundles, and may not read or write data outside the designated container area, nor may they download, install, or execute code which introduces or changes features or functionality of the app, including other apps. Educational apps designed to teach, develop, or allow students to test executable code may, in limited circumstances, download code provided that such code is not used for other purposes. Such apps must make the source code provided by the Application completely viewable and editable by the user.</p>
</blockquote>

<p>This particular formulation is relatively new, however: its spiritual ancestor, then going by the classification “section 2.7”, was even shorter:</p>

<blockquote>
  <p>Apps that download code in any way or form will be rejected</p>
</blockquote>

<p>The existence of some kind of rule similar to this is fundamental to the premise of App Review—so much so that without it the entire process falls apart. Since the review process is largely done only once, it relies on an app’s behavior not changing after review has been performed on a build. iOS has effective technological protections against applications downloading additional native code at runtime, but the original “section 2.7” formulation of this rule covers the remaining cases arising from non-native (interpreted) code.</p>

<p>The modern 2.5.2 incarnation of this rule has additional verbiage which we will get to in a moment, but still retains the core idea of the guideline: applications that download additional code to alter their functionality as a way to bypass app review are not allowed. This has always been and must always be the intent of this guideline if the format of the App Review process is to remain unchanged. In recent years there have been a handful of modifications to the section, but even as the language of this rule has evolved its enforcement has remained consistent; developers may not create applications that remotely download code, period.</p>

<h2 id="scripting-applications">Scripting applications</h2>

<p>To fully understand section 2.5.2, we must first understand the environment in which the additions were written in. For this we need to talk about the rise of a new type of app, one which we will call “scripting applications”.</p>

<p>Scripting applications consist of two parts: a frontend that accepts code from the user, and a backend that runs it. As generating native code is generally disallowed for third-party apps distributed on the App Store, the backend is usually some sort of Turing-complete interpreter. Under the original “section 2.7” guideline, such apps would not be allowed on the store, as they would allow the addition of new code and thus violate the guidelines. However, it is important to note that these apps do not actually have the issue that the guideline was meant to solve: the app itself—neither the frontend nor the backend—changes, and scripts are user- and not developer-generated.</p>

<p>In recent years a number of factors have caused the guidelines to evolve into the 2.5.2 rules we have today—likely a combination of pent-up demand for being able to write scripts on iOS, Apple releasing their own scripting apps to the App Store, and the creation of a number of high-quality apps that ostensibly did not meet the guidelines but were “harmless” started getting accepted. App Review itself seemed to have started shifting to start allowing “educational” apps to execute code, where the user could fully edit and modify what was being run, with parts of this ending up into section 2.5.2 itself. Today there are many scripting apps on the App Store that will let you write scripts in programming languages such as Python, Lua, or JavaScript, some that let you run WebAssembly or LLVM IR bundles, and still others that provide custom “automations”. Apple themselves ships two scripting apps: Swift Playgrounds and Shortcuts. Our own application, iSH, is a scripting application: it interprets x86 scripts. Scripting applications are quite popular among developers, students, teachers, and power users: for many they quite literally make iOS an operating system they are willing to use.</p>

<h2 id="problems-with-section-252">Problems with section 2.5.2</h2>

<p>With such a vibrant ecosystem of scripting applications, it seems like 2.5.2 is a massive success for the App Store: it allows so many of these apps to exist, all without circumventing the App Review process. In reality, however, it does not protect these applications from being found noncompliant with the guidelines. It shares the same goal that section 2.7 has, but even with its additions it suffers from the same problem in that it does not distinguish between user and developer code, nor does it contain a rigorous definition of scripting applications. In cases where App Review does not understand the intent behind 2.5.2, this leads to erroneous rejections, such as the one that iSH received.</p>

<p>Most applications that allow users to create content inherently indemnify the application author against the app being used to violate the guidelines; section 2.5.2 does not do this. Apps that include explicit content are forbidden on the App Store, for example, but drawing apps are not rejected because they allow the user to create such content. However, developers of scripting apps live in constant fear of App Review finding a way to create scripts that do things that the review team feels is objectionable and rejecting their app.</p>

<p>This situation is made worse when the “violation” is a misinterpretation of section 2.5.2 by the review team, especially because they are not equipped to handle such cases and create nonsensical rejections. For example, iSH was once rejected with the rationale that “During review, your app installed or launched executable code, which is not permitted on the App Store.” The template itself clearly outlines the case it is meant to apply—an app that is installing code by itself, to bypass review—but in the case of iSH the reviewer chose to install code and then complained that the app did what they told it to do. In a second case we removed the package manager from iSH, but the reviewer used the wget tool to redownload it and then rejected the app because they “found that [our] app is not self-contained and has remote package updating functionality”—functionality that the reviewer added themselves and then decided to enforce the rules on. Rejecting a drawing application for what the user can draw in it is absurd, but this is exactly how section 2.5.2 is used to reject legitimate scripting applications.</p>

<p>These issues are not unique to iSH, they apply to every single scripting application. Not only is it impossible for an application developer to prevent their users from doing things that the App Review team doesn’t like, any additional restrictions that review asks a developer to put into place transfer to all scripting applications, including Apple’s. The App Review team seems to have been told that the ability to run code at all is some sort of “security issue”, but again, this is how every scripting application works—trying to enforce the guidelines in this way would require all of them to not be allowed on the store.</p>

<h2 id="fixing-section-252">Fixing section 2.5.2</h2>

<p>With such severe issues with section 2.5.2, it may be difficult to see how to fix it to allow scripting apps to exist, while also preventing App Review from falling apart because we allow apps to update themselves without going through review. However, we’ve already touched on the solution: the difference between the two situations is user involvement. Trying to place restrictions on what a user can write themselves, or download, is not possible in a scripting app. But we can distinguish a scripting application from a normal app that is trying to update its app logic by downloading code quite easily: a scripting application keeps a clear boundary between its native runtime and the scripts that run on top of it, and it also allows users to freely edit scripts. Thus, we suggest the following replacement for section 2.5.2:</p>

<aside>

  <p class="aside-content">Apps may not download, install, or execute code which introduces features or changes functionality of the app. Some applications may provide a scripting runtime to allow users to execute scripts. Scripts differ from normal application code in that they must be fully viewable and modifiable by the user. An app may execute, download, import, or install scripts, provided that this is done at the request of the user. Apps that attempt to write outside of their sandbox container or circumvent other platform security features will be rejected.</p>

</aside>

<p>Not only does this ensure that applications cannot use downloaded code to update themselves, it provides a clear definition of a scripting application and tightens up some language around the platform sandbox.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[From its inception, applications that wished to make themselves available on the iOS App Store—the de-facto mechanism of third-party software distribution on the platform—have been required to conform to a set of guidelines laid out and enforced by Apple’s App Review process. Apple’s list of guidelines have expanded and been amended through the years, but the focus has largely remained the same: preventing the distribution of applications that are fraudulent, malicious, contain questionable or illegal content, or undermine Apple’s business interests. Much has already been said about the review process as a whole or Apple’s choice of guidelines, but we are going to focus on one guideline that may be one of the most important of them all: the rule that dictates restrictions on downloading additional code at runtime. For the last couple years, this rule has lived in section 2.5.2 of the guidelines, and this is the name that we will be using to refer to it.]]></summary></entry><entry><title type="html">Mac App Store Sandbox Escape</title><link href="https://saagarjha.com/blog/2020/05/20/mac-app-store-sandbox-escape/" rel="alternate" type="text/html" title="Mac App Store Sandbox Escape" /><published>2020-05-20T00:00:00+00:00</published><updated>2020-05-20T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2020/05/20/mac-app-store-sandbox-escape</id><content type="html" xml:base="https://saagarjha.com/blog/2020/05/20/mac-app-store-sandbox-escape/"><![CDATA[<p>The <a href="https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html">App Sandbox</a>, originally introduced in Mac OS X Leopard as “the Seatbelt”, is a macOS security feature modeled after <a href="https://www.freebsd.org/doc/handbook/mac.html">FreeBSD’s Mandatory Access Control</a> (left unabbreviated for clarity) that serves as a way to restrict the abilities of an application beyond the usual user- and permission-based systems that UNIX offers. The full extent of the capabilities the sandbox manages is fairly broad, ranging from file operations to Mach calls, and is specified in a custom Scheme implementation called the Sandbox Profile Language (SBPL). The sandbox profiles that macOS ships with can be found in /System/Library/Sandbox/Profiles, and while their format is technically SPI (as the header comment on them will tell you) there is fairly extensive <a href="https://reverse.put.as/wp-content/uploads/2011/09/Apple-Sandbox-Guide-v1.0.pdf">third-party documentation</a>. The implementation details of sandboxing are not intended to be accessed by third-party developers, but applications on Apple’s platforms can request (and in some cases, such as new applications distributed on the Mac App Store and all applications for Apple’s embedded platforms, must function in) a sandbox specified by a fixed, system-defined profile (on macOS, application.sb). Barring <a href="https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AppSandboxTemporaryExceptionEntitlements.html">a few exceptions</a> (which usually require additional review and justification for their use) this system-provided sandbox provide an effective way to prevent applications from accessing user data without consent or performing undesired system modifications.</p>

<p>In January I discovered a flaw in the implementation of the sandbox initialization procedure on macOS that would allow malicious applications distributed through the Mac App Store to circumvent the enforcement of these restrictions and silently perform unauthorized operations, including actions such as accessing sensitive user data. Apple has since implemented changes in the Mac App Store to address this issue and the technique outlined below should no longer be effective.</p>

<h2 id="sandbox-initialization-on-macos">Sandbox initialization on macOS</h2>

<p>Sandboxing is enforced by the kernel and present on both macOS and Apple’s iOS-based operating systems, but it is important to note that third party code is not required to run in a sandbox on macOS. While the use of the platform sandbox is mandatory for third-party software running on embedded devices, on Macs it is rarely used by applications distributed outside of the Mac App Store; even on the store there are still a couple of unsandboxed applications that have been grandfathered into being allowed to remain for sale as they were published prior to the 2012 sandboxing deadline. A lesser known, but likely related fact is that processes are not born sandboxed on macOS: unlike iOS, where the sandbox is applied by the kernel before the first instruction of a program executes, on macOS a process must elect to place itself into the sandbox using the “deprecated” <code class="language-plaintext highlighter-rouge">sandbox_init(3)</code> family of functions. These themselves are wrappers around the <code class="language-plaintext highlighter-rouge">__sandbox_ms</code> function, an alias for <code class="language-plaintext highlighter-rouge">__mac_syscall</code> from libsystem_kernel.dylib in /usr/lib/system. This design raises an important question: if a process <em>chooses</em> to place itself in a sandbox, how does Apple <em>require</em> it for apps distributed through the Mac App Store?</p>

<p>Experienced Mac developers already know the answer: Apple checks for the presence of the <code class="language-plaintext highlighter-rouge">com.apple.security.app-sandbox</code> entitlement in all apps submitted for review, and its mere existence magically places the process in a sandbox by the time code execution reaches <code class="language-plaintext highlighter-rouge">main</code>. But the process isn’t actually magic at all: it’s performed by a function called <code class="language-plaintext highlighter-rouge">_libsecinit_initializer</code> inside the library libsystem_secinit.dylib, also located at /usr/lib/system:</p>

<p><img src="Hopper_libsecinit_initializer.png" alt="libsystem_secinit.dylib opened in Hopper, showing _libsecinit_initializer" /></p>

<p><code class="language-plaintext highlighter-rouge">_libsecinit_initializer</code> calls <code class="language-plaintext highlighter-rouge">_libsecinit_appsandbox</code>, which (among other things) copies the current process’s entitlements, checks for the <code class="language-plaintext highlighter-rouge">com.apple.security.app-sandbox</code> in them, and calls <code class="language-plaintext highlighter-rouge">__sandbox_ms</code> after consulting with the secinitd daemon. So this answers <em>where</em> the sandbox is applied, but doesn’t explain <em>how</em>: for that, we need to look inside libSystem.</p>

<p>libSystem is the standard C library on macOS (see <code class="language-plaintext highlighter-rouge">intro(3)</code> for more details). While it vends system APIs, by itself it does very little; instead, it provides this functionality by re-exporting all the libraries inside of /usr/lib/system:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>otool <span class="nt">-L</span> /usr/lib/libSystem.dylib
<span class="go">/usr/lib/libSystem.dylib:
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
	/usr/lib/system/libcache.dylib (compatibility version 1.0.0, current version 83.0.0)
	/usr/lib/system/libcommonCrypto.dylib (compatibility version 1.0.0, current version 60165.120.1)
	/usr/lib/system/libcompiler_rt.dylib (compatibility version 1.0.0, current version 101.2.0)
	/usr/lib/system/libcopyfile.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/system/libcorecrypto.dylib (compatibility version 1.0.0, current version 866.120.3)
	/usr/lib/system/libdispatch.dylib (compatibility version 1.0.0, current version 1173.100.2)
	/usr/lib/system/libdyld.dylib (compatibility version 1.0.0, current version 750.5.0)
	/usr/lib/system/libkeymgr.dylib (compatibility version 1.0.0, current version 30.0.0)
	/usr/lib/system/liblaunch.dylib (compatibility version 1.0.0, current version 1738.120.8)
	/usr/lib/system/libmacho.dylib (compatibility version 1.0.0, current version 959.0.1)
	/usr/lib/system/libquarantine.dylib (compatibility version 1.0.0, current version 110.40.3)
	/usr/lib/system/libremovefile.dylib (compatibility version 1.0.0, current version 48.0.0)
	/usr/lib/system/libsystem_asl.dylib (compatibility version 1.0.0, current version 377.60.2)
	/usr/lib/system/libsystem_blocks.dylib (compatibility version 1.0.0, current version 74.0.0)
	/usr/lib/system/libsystem_c.dylib (compatibility version 1.0.0, current version 1353.100.2)
	/usr/lib/system/libsystem_configuration.dylib (compatibility version 1.0.0, current version 1061.120.2)
	/usr/lib/system/libsystem_coreservices.dylib (compatibility version 1.0.0, current version 114.0.0)
	/usr/lib/system/libsystem_darwin.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/system/libsystem_dnssd.dylib (compatibility version 1.0.0, current version 1096.100.3)
	/usr/lib/system/libsystem_featureflags.dylib (compatibility version 1.0.0, current version 17.0.0)
	/usr/lib/system/libsystem_info.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/system/libsystem_m.dylib (compatibility version 1.0.0, current version 3178.0.0)
	/usr/lib/system/libsystem_malloc.dylib (compatibility version 1.0.0, current version 283.100.6)
	/usr/lib/system/libsystem_networkextension.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/system/libsystem_notify.dylib (compatibility version 1.0.0, current version 241.100.2)
	/usr/lib/system/libsystem_sandbox.dylib (compatibility version 1.0.0, current version 1217.120.7)
	/usr/lib/system/libsystem_secinit.dylib (compatibility version 1.0.0, current version 62.100.2)
	/usr/lib/system/libsystem_kernel.dylib (compatibility version 1.0.0, current version 6153.121.1)
	/usr/lib/system/libsystem_platform.dylib (compatibility version 1.0.0, current version 220.100.1)
	/usr/lib/system/libsystem_pthread.dylib (compatibility version 1.0.0, current version 416.100.3)
	/usr/lib/system/libsystem_symptoms.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/system/libsystem_trace.dylib (compatibility version 1.0.0, current version 1147.120.0)
	/usr/lib/system/libunwind.dylib (compatibility version 1.0.0, current version 35.4.0)
	/usr/lib/system/libxpc.dylib (compatibility version 1.0.0, current version 1738.120.8)
</span></code></pre></div></div>

<p>Like most standard libraries, the compiler will automatically (and dynamically) link it into your programs even if you don’t specify it explicitly:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">echo</span> <span class="s2">"int main(void) {}"</span> | clang <span class="nt">-x</span> c - <span class="o">&amp;&amp;</span> otool <span class="nt">-L</span> a.out
<span class="go">a.out:
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
</span></code></pre></div></div>

<p>When a program is started, the dynamic linker will <a href="https://github.com/apple-open-source-mirror/dyld/blob/f033f5564c85c5cbfd24cf25e702e4bb0c2c39b4/dyld3/AllImages.cpp#L1627">ensure that libSystem’s initializer functions</a> are called, which includes <a href="https://github.com/apple-open-source-mirror/Libsystem/blob/691891bd298f36bf91780ca4f3a2a2cd57b17999/init.c#L259">the function that calls <code class="language-plaintext highlighter-rouge">_libsecinit_initializer</code></a>. As dyld ensures that libSystem’s initializer is run prior to handing off control to the app’s code, this ensures that any application that links against it will have sandboxing applied to it before it can execute its own code.</p>

<h2 id="bypassing-sandbox-initialization">Bypassing sandbox initialization</h2>

<p>As you may have guessed, this process is problematic. In fact, there are actually multiple issues, each of which allows an application with the <code class="language-plaintext highlighter-rouge">com.apple.security.app-sandbox</code> entitlement to bypass the sandbox initialization process.</p>

<h3 id="dyld-interposing">dyld interposing</h3>

<p>dyld interposing is a neat little feature that allows applications to tell the dynamic linker to “interpose” an exported function and replace it with another by including a special <code class="language-plaintext highlighter-rouge">__DATA,__interpose</code> section in their binary. Since <code class="language-plaintext highlighter-rouge">_libsecinit_appsandbox</code> is exported by libsystem_secinit.dylib so that it can be called by libSystem, we can try interposing it with a function that does nothing:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">_libsecinit_initializer</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>

<span class="kt">void</span> <span class="nf">overriden__libsecinit_initializer</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="p">}</span>

<span class="n">__attribute__</span><span class="p">((</span><span class="n">used</span><span class="p">,</span> <span class="n">section</span><span class="p">(</span><span class="s">"__DATA,__interpose"</span><span class="p">)))</span> <span class="k">static</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">overriden__libsecinit_initializer</span><span class="p">)(</span><span class="kt">void</span><span class="p">);</span>
	<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">_libsecinit_initializer</span><span class="p">)(</span><span class="kt">void</span><span class="p">);</span>
<span class="p">}</span> <span class="n">_libsecinit_initializer_interpose</span> <span class="o">=</span> <span class="p">{</span><span class="n">overriden__libsecinit_initializer</span><span class="p">,</span> <span class="n">_libsecinit_initializer</span><span class="p">};</span>
</code></pre></div></div>

<p>When interposing was first introduced, it would only be applied when a library was preloaded into a process using the <code class="language-plaintext highlighter-rouge">DYLD_INSERT_LIBRARIES</code> environment variable. However, on newer OSes this functionality has been improved to <a href="https://github.com/apple-open-source-mirror/dyld/blob/f033f5564c85c5cbfd24cf25e702e4bb0c2c39b4/src/dyld2.cpp#L6605">work for any linked libraries as well</a>, which means all we have to do to take advantage of this feature is put this code in a framework and link against it in our main app. Since <a href="https://github.com/apple-open-source-mirror/dyld/blob/f033f5564c85c5cbfd24cf25e702e4bb0c2c39b4/src/dyld2.cpp#L6679">interposing is applied before image initializers</a> we will be able to prevent the real <code class="language-plaintext highlighter-rouge">_libsecinit_initializer</code> from running and thus <code class="language-plaintext highlighter-rouge">__sandbox_ms</code> being called. Success!</p>

<p>As this technique allowed an application that appears to be sandboxed (possessing the <code class="language-plaintext highlighter-rouge">com.apple.security.app-sandbox</code> entitlement) to interfere with its own initialization process, I reported this issue to Apple on January 20th and explained that such an app might be able to be submitted to the App Store and get past app review. On March 19th, I received a reply from Apple stating that App Store applications are prevented from being interposed, which was news to me. Apparently right after I submitted my original report Apple added an additional check in dyld, one so new that it’s still not in any public sources:</p>

<p><img src="HopperAdditionaldyldRestrictions.png" alt="Hopper disassembly of dyld::_main, focused on code inlined from configureProcessRestrictions, highlighting the existence of a new AMFI flag" /></p>

<p>While the <a href="https://github.com/apple-open-source-mirror/dyld/blob/f033f5564c85c5cbfd24cf25e702e4bb0c2c39b4/src/dyld2.cpp#L5060">dyld source for <code class="language-plaintext highlighter-rouge">configureProcessRestrictions</code></a> only shows five flags being read from <code class="language-plaintext highlighter-rouge">amfi_check_dyld_policy_self</code>, the binary clearly checks a sixth: <code class="language-plaintext highlighter-rouge">1 &lt;&lt; 6</code>. (<code class="language-plaintext highlighter-rouge">configureProcessRestrictions</code> has been inlined here into its caller, <code class="language-plaintext highlighter-rouge">dyld::_main</code>.) I still do not know what its real name is but it’s used later in <code class="language-plaintext highlighter-rouge">dyld::_main</code> to control whether interposing is allowed. This means we can’t interpose <code class="language-plaintext highlighter-rouge">_libsecinit_initializer</code>–we’ll have to prevent it from from being called instead.</p>

<aside class="aside-update">

  <p class="aside-type">Update, 6/10/19</p>

  <p class="aside-content">With the code to dyld <a href="https://opensource.apple.com/source/dyld/dyld-733.8/src/dyld2.cpp.auto.html">released</a>, we can see that the flag is called <code class="language-plaintext highlighter-rouge">AMFI_DYLD_OUTPUT_ALLOW_LIBRARY_INTERPOSING</code>. Interestingly, there are some applications that are exempted from the check in AMFI’s <code class="language-plaintext highlighter-rouge">macos_dyld_policy_library_interposing</code>, meaning that they are still susceptible to this issue: <img src="HopperAMFIExceptions.png" alt="Hopper disassembly listing showing the bundle identifiers of exemptions" /></p>

</aside>

<h3 id="static-linking">Static linking</h3>

<p>Linking against libSystem causes dyld to call <code class="language-plaintext highlighter-rouge">_libsecinit_initializer</code>, so it’s logical to try to avoid having anything to do with dyld at all. This is fairly strange to do on macOS, as it does not have a stable syscall interface, but with the right set of compiler flags we can make a fully static binary that needs to no additional support to run.</p>

<aside class="aside-fun-fact">

  <p class="aside-type">Fun fact</p>

  <p class="aside-content">We know that this must be possible because Go used to do it, until they got tired of new versions of macOS breaking everything and gave up trying to make system calls themselves. Go programs <a href="https://golang.org/doc/go1.11#runtime">as of Go 1.11</a> now use libSystem.</p>

</aside>

<p>Unfortunately, macOS does not ship with a crt0.o that we can statically link, so using just the <code class="language-plaintext highlighter-rouge">-static</code> flag does not work:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">echo</span> <span class="s2">"int main() {}"</span> | clang <span class="nt">-x</span> c <span class="nt">-static</span> -
<span class="go">ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation
</span></code></pre></div></div>

<p>But if we’re jettisoning the standard library, we might as well get rid of the C runtime as well, defining our own <code class="language-plaintext highlighter-rouge">start</code> symbol:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>clang <span class="nt">-x</span> c <span class="nt">-static</span> <span class="nt">-nostdlib</span> -
<span class="gp">void start(void) __asm__("start");</span><span class="w">
</span><span class="go">
void start(void) {
</span><span class="gp">        while (1);</span><span class="w">
</span><span class="go">}
</span><span class="gp">$</span><span class="w"> </span>otool <span class="nt">-L</span> a.out
<span class="go">a.out:
</span><span class="gp">$</span><span class="w"> </span>a.out
<span class="go">^C
</span><span class="gp">$</span><span class="w">
</span></code></pre></div></div>

<p>No dyld means no code that can arrange a call <code class="language-plaintext highlighter-rouge">_libsecinit_initializer</code>, so we’re free to do whatever we like without restriction. However, not having libSystem and dyld to support us means we cannot use dynamic linking and need to make raw system calls for everything, which is a bit of a pain. One way to resolve this would be to keep the unsandboxed code short–just a couple of calls to acquire a handle on restricted resources–then stash that away before <code class="language-plaintext highlighter-rouge">execve</code>ing a new dynamically linked binary, restoring the process to a sane state. When responding to Apple with a new sample program based on this idea, I simply <code class="language-plaintext highlighter-rouge">open</code>ed a file descriptor for the home directory (you can locate the directory without any syscalls by pulling the current username from the <code class="language-plaintext highlighter-rouge">apple</code> array on the stack during process initialization) and then once that succeeds executed an inner binary. The new file descriptor was preserved for across the <code class="language-plaintext highlighter-rouge">execve</code> call and became accessible to the inner application, even though that one was dynamically linked and had the sandbox applied to it as usual.</p>

<h3 id="dynamically-linking-against-nothing">Dynamically linking against nothing</h3>

<p>Statically linking works, but it’s somewhat inconvenient: either you perform the work of the dynamic linker yourself if you want to do anything non-trivial, or you <code class="language-plaintext highlighter-rouge">execve</code> a new binary. It’s actually worse than that though, because there’s an additional complication: executing a new binary causes a hook in the AppleMobileFileIntegrity kernel extension to run, and when System Integrity Protection is enabled this hook (for reasons unknown to me) checks to see if the process has a valid dyld signature:</p>

<p><img src="HopperAMFIHook.png" alt="Hopper disassembly of the MAC hook _cred_label_update_execve, showing the check for CS_DYLD_PLATFORM" /></p>

<p>The strange pointer arithmetic and mask is really a check for <a href="https://github.com/apple-open-source-mirror/xnu/blob/65d5be84e21bccbae44730ddb3b307a701b0351a/osfmk/kern/cs_blobs.h#L62"><code class="language-plaintext highlighter-rouge">CS_DYLD_PLATFORM</code></a>, which the comment helpfully states is set if the “dyld used to load this is a platform binary”. Since we didn’t use dyld at all, this isn’t set and we can’t <code class="language-plaintext highlighter-rouge">execve</code>. While  malicious applications willing to do a bit of work can still “fix” their process without blowing it away, I figured I might as well figure out a way to construct a new one.</p>

<p>Since the hook wants us to have a valid dyld, we should probably just link dynamically. As we mentioned before, this makes the compiler automatically bring in libSystem (and with it, the libsystem_secinit.dylib initializers), which we don’t want. I couldn’t find out a way to get the linker to not automatically insert the load command for libSystem, but we can get essentially the same result by modifying the binary ourselves afterwards to delete that specific command. <a href="https://github.com/Tyilo/macho_edit">I found a Mach-O editor online</a> that was slightly crashy but worked well enough for this purpose. Unfortunately, removing the load command isn’t enough: dyld <a href="https://github.com/apple-open-source-mirror/dyld/blob/f033f5564c85c5cbfd24cf25e702e4bb0c2c39b4/src/dyld2.cpp#L6703">specifically checks</a> for libSystem “glue” before running our code, and as we don’t have a libSystem at all it aborts execution.</p>

<p>However, there’s one way around this: if we use a <code class="language-plaintext highlighter-rouge">LC_UNIXTHREAD</code> rather than a <code class="language-plaintext highlighter-rouge">LC_MAIN</code> load command, dyld will pass execution to us without checking for libSystem (as it thinks we have linked against crt1.o instead). Both load commands specify the entrypoint of the executable, but <code class="language-plaintext highlighter-rouge">LC_MAIN</code> is the “new” way of doing so. <code class="language-plaintext highlighter-rouge">LC_UNIXTHREAD</code> specifies the entire thread state, but <code class="language-plaintext highlighter-rouge">LC_MAIN</code> only points to the “entry offset” where code execution should begin–the linker sets this to where <code class="language-plaintext highlighter-rouge">main</code> is, unless you’ve used <code class="language-plaintext highlighter-rouge">-e</code> to change it. The compiler uses it for dynamically linked binaries because it expects libSystem to set all the thread state prior to calling the entrypoint function.</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">echo</span> <span class="s2">"int main(void) {}"</span> | clang <span class="nt">-x</span> c -
<span class="gp">$</span><span class="w"> </span>nm a.out
<span class="go">0000000100000000 T __mh_execute_header
0000000100000fb0 T _main
                 U dyld_stub_binder
</span><span class="gp">$</span><span class="w"> </span>otool <span class="nt">-l</span> a.out | <span class="nb">grep</span> <span class="nt">-A</span> 3 <span class="s2">"LC_MAIN"</span>
<span class="go">       cmd LC_MAIN
   cmdsize 24
  entryoff 4016
 stacksize 0
</span><span class="gp">$</span><span class="w"> </span>clang <span class="nt">-x</span> c <span class="nt">-static</span> <span class="nt">-nostdlib</span> -
<span class="gp">void start(void) __asm__("start");</span><span class="w">
</span><span class="go">
void start(void) {
</span><span class="gp">        while (1);</span><span class="w">
</span><span class="go">}
</span><span class="gp">$</span><span class="w"> </span>nm a.out
<span class="go">0000000100000000 A __mh_execute_header
0000000100000fb0 T start
</span><span class="gp">$</span><span class="w"> </span>otool <span class="nt">-l</span> a.out | <span class="nb">grep</span> <span class="nt">-A</span> 11 <span class="s2">"LC_UNIXTHREAD"</span>
<span class="go">        cmd LC_UNIXTHREAD
    cmdsize 184
     flavor x86_THREAD_STATE64
      count x86_THREAD_STATE64_COUNT
   rax  0x0000000000000000 rbx 0x0000000000000000 rcx  0x0000000000000000
   rdx  0x0000000000000000 rdi 0x0000000000000000 rsi  0x0000000000000000
   rbp  0x0000000000000000 rsp 0x0000000000000000 r8   0x0000000000000000
    r9  0x0000000000000000 r10 0x0000000000000000 r11  0x0000000000000000
   r12  0x0000000000000000 r13 0x0000000000000000 r14  0x0000000000000000
   r15  0x0000000000000000 rip 0x0000000100000fb0
rflags  0x0000000000000000 cs  0x0000000000000000 fs   0x0000000000000000
    gs  0x0000000000000000
</span></code></pre></div></div>

<p>The linker flag <code class="language-plaintext highlighter-rouge">-no_new_main</code> tells the linker to use <code class="language-plaintext highlighter-rouge">LC_UNIXTHREAD</code> instead of <code class="language-plaintext highlighter-rouge">LC_MAIN</code> for dynamically linked executables, but it has been silently ignored for years (apparently, this has something to do with <a href="rdar://problem/39514191">rdar://problem/39514191</a>). This means to generate the binary we’ll have to go back in time and download an old toolchain that accepts this flag. The one that <a href="https://download.developer.apple.com/Developer_Tools/xcode_5.1.1/Xcode_5.1.1.dmg">Xcode 5.1.1</a> ships with does nicely.</p>

<aside class="aside-fun-fact">

  <p class="aside-type">Fun fact</p>

  <p class="aside-content">I have a friend who refers to Xcode 5.1.1 as “the good toolchain” because it  supports everything.</p>

</aside>

<p>Once we use that to create a binary, upon running it we have a valid dyld in our process and unsandboxed code execution so we can just continue as we did in the statically linked case, as this will satisfy AMFI’s checks.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>I submitted the final example to Apple just before the initial 90-day disclosure deadline of April 20th, and when they requested an extension to work on the new information I provided them with an additional 30 days. Apple says it has made changes in the Mac App Store to address this issue during that period, and although I <a href="https://twitter.com/0xcharlie/status/133680514950369280">don’t really have a good way to check</a> if or how the change works I would guess that it simply looks for and rejects applications using techniques similar to the ones described above.</p>

<p>dyld is a fairly complicated system and it has many useful features, but these features along with the fact that it runs in-process makes it nontrivial to protect against control flow subversion early in the initialization process. Applying sandboxing in the kernel itself, as iOS does, is probably a better solution in the long run, as the bugs I found here were fairly straightforwards and exploited logic errors rather than undefined behavior in the language. Perhaps we will see such a change in the future.</p>

<p>The code I submitted to Apple to demonstrate the issue is <a href="https://github.com/saagarjha/macOSSandboxInitializationBypass">available online</a>.</p>

<h2 id="timeline">Timeline</h2>

<ul>
  <li><strong>1/20/20:</strong> Initial disclosure of library interposing bypass to Apple</li>
  <li><strong>1/22/20:</strong> Acknowledgment of submission by Apple</li>
  <li><strong>1/28/20:</strong> Request for status update after recent updates did not resolve the issue</li>
  <li><strong>1/29/20:</strong> Response from Apple that they were still investigating</li>
  <li><strong>2/26/20:</strong> Request for update and affirmation of 90-day disclosure timeline</li>
  <li><strong>2/28:20:</strong> Response from Apple that they were still looking into the issue</li>
  <li><strong>3/19:20:</strong> Email from Apple stating that Mac App Store applications cannot be interposed</li>
  <li><strong>3/20/20:</strong> Submission of statically linked application to avoid interposing</li>
  <li><strong>3/23/20:</strong> Acknowledgement of the new information</li>
  <li><strong>4/14/20:</strong> Submission of dynamically linked application to bypass <code class="language-plaintext highlighter-rouge">execve</code> limitation</li>
  <li><strong>4/17/20:</strong> Request for more time from Apple to analyze the new submission</li>
  <li><strong>4/19/20:</strong> Disclosure deadline extended by 30 days to May 20th</li>
  <li><strong>4/20/20:</strong> Confirmation and appreciation for the extension</li>
  <li><strong>5/13/20:</strong> Request for an update on progress</li>
  <li><strong>5/15/20:</strong> Confirmation that a change had been implemented in Mac App Store</li>
  <li><strong>5/20/20:</strong> Expiration of discretionary disclosure extension</li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[The App Sandbox, originally introduced in Mac OS X Leopard as “the Seatbelt”, is a macOS security feature modeled after FreeBSD’s Mandatory Access Control (left unabbreviated for clarity) that serves as a way to restrict the abilities of an application beyond the usual user- and permission-based systems that UNIX offers. The full extent of the capabilities the sandbox manages is fairly broad, ranging from file operations to Mach calls, and is specified in a custom Scheme implementation called the Sandbox Profile Language (SBPL). The sandbox profiles that macOS ships with can be found in /System/Library/Sandbox/Profiles, and while their format is technically SPI (as the header comment on them will tell you) there is fairly extensive third-party documentation. The implementation details of sandboxing are not intended to be accessed by third-party developers, but applications on Apple’s platforms can request (and in some cases, such as new applications distributed on the Mac App Store and all applications for Apple’s embedded platforms, must function in) a sandbox specified by a fixed, system-defined profile (on macOS, application.sb). Barring a few exceptions (which usually require additional review and justification for their use) this system-provided sandbox provide an effective way to prevent applications from accessing user data without consent or performing undesired system modifications.]]></summary></entry><entry><title type="html">Why we at $FAMOUS_COMPANY Switched to $HYPED_TECHNOLOGY</title><link href="https://saagarjha.com/blog/2020/05/10/why-we-at-famous-company-switched-to-hyped-technology/" rel="alternate" type="text/html" title="Why we at $FAMOUS_COMPANY Switched to $HYPED_TECHNOLOGY" /><published>2020-05-10T00:00:00+00:00</published><updated>2020-05-10T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2020/05/10/why-we-at-famous-company-switched-to-hyped-technology</id><content type="html" xml:base="https://saagarjha.com/blog/2020/05/10/why-we-at-famous-company-switched-to-hyped-technology/"><![CDATA[<p>When $FAMOUS_COMPANY launched in 2010, it ran on a single server in $TECHBRO_FOUNDER’s garage. Since then, we’ve experienced explosive VC-funded growth and today we have hundreds of millions of daily active users (DAUs) from all around the globe accessing our products from our mobile apps and on $famouscompany.com. We’ve since made a couple of panic-induced changes to our backend to manage our technical debt (usually right after a high-profile outage) to keep our servers from keeling over. Our existing technology stack has served us well for all these years, but as we seek to grow further it’s clear that a complete rewrite of our application is something which will somehow prevent us from losing two billion dollars a year on customer acquisition.</p>

<h2 id="why-switch">Why switch?</h2>

<p>As we’ve mentioned in previous blog posts, the $FAMOUS_COMPANY backend has historically been developed in $UNREMARKABLE_LANGUAGE and architected on top of $PRACTICAL_OPEN_SOURCE_FRAMEWORK. To suit our unique needs, we designed and open-sourced $AN_ENGINEER_TOOK_A_MYTHOLOGY_CLASS, a highly-available, just-in-time compiler for $UNREMARKABLE_LANGUAGE. Even with our custom runtime, however, we eventually began seeing sporadic spikes in our 99th percentile latency statistics, which grew ever more pronounced as we scaled up to handle our increasing DAU count. Luckily, all of our software is designed from the ground up for introspectability, and using <del>some BPF scripts we copied from Brendan Gregg’s website</del> our in-house profiling tools $FAMOUS_COMPANY engineers determined that the performance bottlenecks were a result of time spent in the garbage collector.</p>

<p>Initially, we tried messing with some garbage collector parameters we didn’t really understand, but to our surprise that didn’t magically solve our problems so instead we disabled garbage collection altogether. This increased our memory usage, but our automatic on-demand scaler handled this for us, as the graph below shows:</p>

<p><img src="MoarAWS.png" alt="The inevitable conclusion of scalable architecture" /></p>

<p>Ultimately, however, our decision to switch was driven by our difficulty in hiring new talent for $UNREMARKABLE_LANGUAGE, despite it being taught in dozens of universities across the United States. Our blog posts on $PRACTICAL_OPEN_SOURCE_FRAMEWORK seemed to get fewer upvotes when posted on Reddit as well, cementing our conviction that our technology stack was now legacy code.</p>

<h2 id="pivoting-to-a-new-stack">Pivoting to a new stack</h2>

<p>We knew we needed to find something that could keep up with us at $FAMOUS_COMPANY scale. We evaluated a number of promising alternatives that we selected and ranked based on the how many bullet points they had on their websites, how often they’d appear on the front page of Hacker News, and a spreadsheet of important language characteristics (performance, efficiency, community, ease-of-use) that we had people in the office fill out.</p>

<aside class="aside-fun-fact">

  <p class="aside-type">Fun fact</p>

  <p class="aside-content">As our spreadsheet met strong statistical guarantees of randomness, we were able to reuse it to replace our application’s CSPRNG.</p>

</aside>

<p>After careful consideration, we settled on rearchitecting our platform to use $FLASHY_LANGUAGE and $HYPED_TECHNOLOGY. Not only is $FLASHY_LANGUAGE popular according to the Stack Overflow developer survey, it’s also cross platform; we’re using it to reimplement our mobile apps as well. Rewriting our core infrastructure was fairly straightforward: as we have more engineers than we could possibly ever need or even know what to do with, we simply put a freeze on handling bug reports and shifted our effort to $HYPED_TECHNOLOGY instead. We originally had some trouble with adapting to some of $FLASHY_LANGUAGE’s quirks, and ran into a couple of bugs with $HYPED_TECHNOLOGY, but overall their powerful new features let us remove some of the complexity that our previous solution had to handle.</p>

<p>Deploying the changes without downtime required some careful planning, but this was also not too difficult: we just hardcoded the status page to not update whenever we pushed new changes, keeping users guessing if our service was up or not. Managing incremental rollout was key: we aggressively A/B tested the new code. Our internal studies showed that gaslighting users by showing them a completely new interface once in a while and then switching back to the old one the next time they loaded a page increases user engagement, so we made sure to implement such a system based on a Medium article we found that had something to do with multi-armed bandits.</p>

<p>With our rewrite now complete and rolled out to all of our customers, we think the effort has been a massive success for us and our team. We have measured our performance and you can see a summary of the results below:</p>

<p><img src="Stonks.png" alt="Stonks" /></p>

<p>Every metric that matters to us has increased substantially from the rewrite, and we even identified some that were no longer relevant to us, such as number of bugs, user frustration, and maintenance cost. Today we are making some of the code that we can afford to open source available on our GitHub page. It is useless by itself and is heavily tied to our infrastructure, but you can star it to make us seem more relevant.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>It’s often said that completely rewriting software is fraught with peril, but we at $FAMOUS_COMPANY like to take big bets, and it’s clear that this one has paid off handsomely. While we focused on our backend changes in this blog post, as we mentioned before we are using $FLASHY_LANGUAGE in our mobile apps as well, since we don’t have the resources to write native applications for each platform. Unfortunately <del>to increase lock-in</del> these rewrites also mean we will be deprecating third-party API access to our services. We know some of our users relied on these interfaces for accessibility reasons, but we at $FAMOUS_COMPANY are dedicated to improving our services for those with disabilities as long as you aren’t using any sort of assistive technologies, which no longer work at all with our apps.</p>

<p>We hope that you internalize our company’s anecdote as some sort of ground truth and show it to your company’s CTO so they too can consider redesigning their architecture like we have done. We know you’ll ignore the fact that you’re not us and we have enough engineers and resources to do whatever we like, but the decision will ruin your startup so it’s not like we’ll see <em>your</em> blog posts about your experience with $HYPED_TECHNOLOGY anytime soon. If you’re not in a position to influence what your company uses, you can still bring it up for point-scoring the next time a language war comes up.</p>

<p>If you’re reading this and are interested in $HYPED_TECHNOLOGY like we are, we are hiring! Be sure to check out our jobs page, where there will be zero positions related to $FLASHY_LANGUAGE.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[When $FAMOUS_COMPANY launched in 2010, it ran on a single server in $TECHBRO_FOUNDER’s garage. Since then, we’ve experienced explosive VC-funded growth and today we have hundreds of millions of daily active users (DAUs) from all around the globe accessing our products from our mobile apps and on $famouscompany.com. We’ve since made a couple of panic-induced changes to our backend to manage our technical debt (usually right after a high-profile outage) to keep our servers from keeling over. Our existing technology stack has served us well for all these years, but as we seek to grow further it’s clear that a complete rewrite of our application is something which will somehow prevent us from losing two billion dollars a year on customer acquisition.]]></summary></entry><entry><title type="html">Debugging Python Operator Precedence With MacsBug</title><link href="https://saagarjha.com/blog/2020/04/22/debugging-python-operator-precedence-with-macsbug/" rel="alternate" type="text/html" title="Debugging Python Operator Precedence With MacsBug" /><published>2020-04-22T00:00:00+00:00</published><updated>2020-04-22T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2020/04/22/debugging-python-operator-precedence-with-macsbug</id><content type="html" xml:base="https://saagarjha.com/blog/2020/04/22/debugging-python-operator-precedence-with-macsbug/"><![CDATA[<p>I’m a <a href="https://en.wikipedia.org/wiki/Capture_the_flag#Computer_security">Capture the Flag</a> (CTF) player with <a href="http://shellphish.net">Shellphish</a>, and last weekend our team participated in <a href="https://plaidctf.com">PlaidCTF 2020</a>, an event organized by the <a href="https://pwning.net">Plaid Parliament of Pwning</a> (PPP). As a <a href="https://oooverflow.io/dc-ctf-2020-quals/#pre-qualifiers">pre-qualifier</a> for the <a href="https://www.defcon.org/html/links/dc-ctf.html">DEF CON CTF</a> 2020, it’s historically been a fairly challenging competition–this year our team only managed to <a href="https://play.plaidctf.com/scoreboard">place 17th</a>, slightly below our usual performance, as many of our team members were preoccupied with inconveniently-placed project deadlines. However, the rest of us had a great time working on the challenges; I helped solve two, <a href="https://ctftime.org/task/11305">golf.so</a> and <a href="https://ctftime.org/task/11312">The Watness 2</a>. golf.so was released early in the CTF and asked teams to create small shared libraries that would call <code class="language-plaintext highlighter-rouge">execve("/bin/sh", ["/bin/sh"], ...)</code> when <code class="language-plaintext highlighter-rouge">LD_PRELOAD</code>ed in to /bin/true; a number of us worked together to solve this fairly quickly, getting under 194 bytes (the requirement for the full 500 points) with some aggressive but straightforward segment overlapping, careful trimming of “required” but leniently checked fields, and stuffing of code into the remaining header bytes that were required but could be set to fairly arbitrary values. Some teams <a href="http://golf.so.pwni.ng">golfed it further</a> to 136 bytes, although I’m not sure how (or why, beside bragging rights) they did so. The Watness 2 took longer and in my opinion was a bit more interesting, and this is the one we’ll be talking about here.</p>

<aside>

  <p class="aside-type">Note</p>

  <p class="aside-content">The description below has been written up after the fact by trawling through chat logs and my recollection, and might not be entirely accurate. To preserve your sanity, screenshots and code snippets were re-extracted and cleaned after the CTF and as such are not representative of what is colloquially referred to as “CTF quality”. (I think I might have lost mine after revisiting some of it.)</p>

</aside>

<h2 id="forensics">Forensics</h2>

<p>CTF challenges usually come in a couple of varieties: among others there’s pwn, which often means that there’s a vulnerable binary running somewhere that you need to exploit to (normally) pop a shell and grab a flag, web, which often means there’s something wrong with a website or a database, crypto, where your RSA exponent is 3, or reversing, which means you have a black box with a flag hidden somewhere in it. As The Watness 2 was a reversing challenge, we were given the challenge title, a protracted snippet of prose that was entirely useless by PPP’s own admission, and .tar.gz that contained the thing we needed to reverse. This time we had one additional clue: last year, PlaidCTF ran a challenge called <a href="https://ctftime.org/task/8246">The .Wat ness</a>, a WebAssembly-based implementation of a puzzle game inspired by <em><a href="https://en.wikipedia.org/wiki/The_Witness_(2016_video_game)">The Witness</a></em>, and we knew to expect something related this year.</p>

<p>Michele from our team took the first look at the challenge, and I joined in soon afterwards. Opening the archive, we hit our first clue: a single file named watness_2.sit–a <a href="https://en.wikipedia.org/wiki/StuffIt">StuffIt archive</a>. It’s an obscure archive format but it’s instantly recognizable to anyone who’s done anything with classic Mac OS. <a href="https://en.wikipedia.org/wiki/The_Unarchiver">The Unarchiver</a> made quick work of expanding it, and we were left with one more file: game_cleaned.rc1, which Michele identified as a <a href="https://en.wikipedia.org/wiki/HyperCard">HyperCard</a> stack. Before running a program, it’s often a good idea to poke around it to get some insight into what it does, so I downloaded a little Swift app called <a href="https://github.com/PierreLorenzi/HyperCardPreview">HyperCardPreview</a> to take a peek inside. This let us take a look at the <a href="https://en.wikipedia.org/wiki/HyperTalk">HyperTalk</a> code for the stack, as well as its cards and resources. The code clearly implemented a game similar to <em>The Witness</em> in HyperCard, and it didn’t take long for us to zero in on the part of the code that was relevant to us:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>on checkSolution
  global puzzle_id,path,constraints,flag_1,flag_2,flag_3
  watnesssolver constraints,path
  put the result into success
  if success = "true" then
    if puzzle_id = 1 then
      decoder path,"clrtffxpry"
      put the result into flag_1
    end if
    if puzzle_id = 2 then
      decoder path,"nyghq7xksg"
      put the result into flag_2
    end if
    if puzzle_id = 3 then
      decoder path,"ppyyvn}1{7"
      put the result into flag_3
    end if
  else
    send opencard to this cd
  end if
end checkSolution
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">watnesssolver</code> didn’t show up anywhere else in the HyperTalk code, but looking into the stack’s resources, we found a number of XCMDs, one which had the same label:</p>

<p><img src="HyperCardPreviewResources.png" alt="The resources contained in the HyperCard stack, including some BITs, STR#, PICT, and XCMD resources, one of which is watnesssolver" /></p>

<p>A quick search revealed that XCMD was the <a href="https://en.wikipedia.org/wiki/Resource_fork#Major_resource_types">four-letter type code</a> for some sort of executable plugin, so we tried loading it into a disassembler as a <a href="https://en.wikipedia.org/wiki/PowerPC">PowerPC</a> blob, thinking to match the architecture that Apple was using at the time. That didn’t really work out, so on a hunch we tried again with the <a href="https://en.wikipedia.org/wiki/Motorola_68000_series">Motorola 68k</a> loader. This proved to be much more sucessful: conveniently, pointing the disassembler at the very top of the file caused it to fall apart, revealing that the XCMD was largely <a href="https://en.wikipedia.org/wiki/Position-independent_code">position-independent</a> and started code execution right from the top of the file:</p>

<p><img src="GhidraWatnessSolver.png" alt="The WatnessSolver XKMD loaded into Ghidra, showing automatic code detection and function recovery" /></p>

<h2 id="reversing">Reversing</h2>

<p>With CTF challenges, we’ve often had to cobble together toolchains to work with strange, obscure, or old platforms, so getting something that would run the stack was not too challenging: we already knew about <a href="http://sheepshaver.cebix.net">SheepShaver</a>, and a quick search <a href="https://jamesfriend.com.au/running-hypercard-stack-2014">gave us</a> a prebuilt “sheepvm” that we could download and run immediately. By this time Michele had drifted off to bed (this was a 48 hour CTF, after all, and it was past 2 AM in Italy) but the promise of a challenge based on <em>The Witness</em> was enough to lure in Eric–in addition to his excellent blob reversing skills, he was one of the few team members who had actually played the game. He instantly recognized the screenshot I sent him from SheepShaver:</p>

<p><img src="SheepShaverTheWitness.png" alt="Screenshot of The Watness 2 HyperCard stack running in SheepShaver, showing a striking similarity to the setting of The Witness" /></p>

<p>I hastened to send him a copy of the files I had used to run the emulator, but we hit upon a snag: the resource forks from before, which were necessary to run the stack, were handed transparently by my filesystem on my Mac, but on Eric’s Linux machine they would literally fall apart and become unusable. After fiddling a bit with sending DMGs back and forth, we realized that the HyperCard sheepvm actually had a copy of StuffIt expander on it, so Eric could just extract it inside the VM and keep the resource forks intact. With Eric busy playing the game and exploring its puzzles, I roped in Paul with the incentive of the 68k binary blob (we have somewhat strange interests) and got to reversing the XCMD. Paul quickly figured out that the XCMD was called with a pointer to some sort of context struct, the layout of which was not too difficult to find online; the remaining interface between the extension and any code outside of it was matched up to a file called HyperXCMD.h that <a href="https://github.com/commanderx16/lcc-816/blob/master/include/iigs/toolbox/hypercard.h">we spotted online</a>, showing that the calls were to <code class="language-plaintext highlighter-rouge">EvalExpr</code> and <code class="language-plaintext highlighter-rouge">ZeroToPas</code> (yes, those are Pascal functions, and yes, the last one converts a null-terminated string to a Pascal-style one). With that out of the way, we got to reversing the code inside the XCMD itself, which was organized a short list of named functions: <code class="language-plaintext highlighter-rouge">ENTRYPOINT</code>, <code class="language-plaintext highlighter-rouge">BUILDAUTOMATON</code>, <code class="language-plaintext highlighter-rouge">GETNEIGHBORS</code>, <code class="language-plaintext highlighter-rouge">CHOOSEEMPTY</code>, <code class="language-plaintext highlighter-rouge">CHOOSERED</code>, <code class="language-plaintext highlighter-rouge">CHOOSEGREEN</code>, <code class="language-plaintext highlighter-rouge">CHOOSEBLUE</code>, <code class="language-plaintext highlighter-rouge">STEPAUTOMATON</code>, <code class="language-plaintext highlighter-rouge">ISRED</code>, <code class="language-plaintext highlighter-rouge">INITIALIZENODES</code>, <code class="language-plaintext highlighter-rouge">PERFORMMOVE</code>, and <code class="language-plaintext highlighter-rouge">SOLVER</code>.</p>

<aside class="aside-fun-fact">

  <p class="aside-type">Fun fact</p>

  <p class="aside-content">The function names were included in the binary as strings, placed just after the function itself. Initially we had labeled the functions based on the name that came <em>before</em> it, making our reversing a bit harder as we tried to figure out why <code class="language-plaintext highlighter-rouge">ENTRYPOINT</code> did not seem to be the entry point and why <code class="language-plaintext highlighter-rouge">PERFORMMOVE</code> was zeroing out internal buffers. For us, this was not so fun, but we realized our mistake fairly early.</p>

</aside>

<p>As we were reversing the functions, Eric found three puzzles and one final gate barred by three locks–fairly straightforwards, if not for the clearly impossible puzzles:</p>

<p><img src="ImpossiblePuzzle.png" alt="A puzzle which would be impossible to solve; the cursor is resting on a spot where no valid path can be drawn" /></p>

<p>In <em>The Witness</em>, Eric explained, you can run into puzzles where the goal is to separate all “unlike” things from each other by drawing a path from start to finish on the grid. In the challenge’s puzzles, this was provably impossible, confirming our suspicions that there were other, hidden rules involved. Looking at <code class="language-plaintext highlighter-rouge">PERFORMMOVE</code> showed that the game wanted a path that always touched a red square–the only problem was that such a path was clearly impossible as well! Every time the function was run, however, it would call the <code class="language-plaintext highlighter-rouge">STEPAUTOMATON</code> function, so it was pretty clear what was going on: the board shown was simply the initial state to some sort of cellular automaton, and it would invisibly evolve as we moved along the board. We decided we needed to simulate the board outside of the game and try to find the path there. The <code class="language-plaintext highlighter-rouge">CHOOSE*</code> functions held the transformation rules, and we translated them as literally as possible to Python for our simulation, with Paul doing the first two cases and me doing the latter two:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">cur</span> <span class="o">==</span> <span class="n">Color</span><span class="p">.</span><span class="n">EMPTY</span><span class="p">:</span>
    <span class="n">d0</span> <span class="o">=</span> <span class="n">gn</span> <span class="o">==</span> <span class="mi">0</span>
    <span class="n">d1</span> <span class="o">=</span> <span class="n">bn</span> <span class="o">==</span> <span class="mi">0</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">d0</span> <span class="ow">and</span> <span class="n">d1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">bn</span> <span class="o">-</span> <span class="n">gn</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">cur</span> <span class="o">==</span> <span class="n">Color</span><span class="p">.</span><span class="n">RED</span><span class="p">:</span>
    <span class="n">d0</span> <span class="o">=</span> <span class="n">rn</span> <span class="o">!=</span> <span class="mi">2</span>
    <span class="n">d1</span> <span class="o">=</span> <span class="n">rn</span> <span class="o">!=</span> <span class="mi">3</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">d0</span> <span class="ow">and</span> <span class="n">d1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">d0</span> <span class="o">=</span> <span class="n">bn</span> <span class="o">==</span> <span class="mi">0</span>
        <span class="n">d1</span> <span class="o">=</span> <span class="n">gn</span> <span class="o">==</span> <span class="mi">0</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">d0</span> <span class="ow">or</span> <span class="n">d1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">cur</span> <span class="o">==</span> <span class="n">Color</span><span class="p">.</span><span class="n">GREEN</span><span class="p">:</span>
    <span class="k">if</span> <span class="mi">4</span> <span class="o">-</span> <span class="n">rn</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">if</span> <span class="mi">4</span> <span class="o">-</span> <span class="n">bn</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">d0</span> <span class="o">=</span> <span class="n">rn</span> <span class="o">==</span> <span class="mi">2</span>
            <span class="n">d1</span> <span class="o">=</span> <span class="n">rn</span> <span class="o">==</span> <span class="mi">3</span>
            <span class="k">if</span> <span class="n">d0</span> <span class="ow">or</span> <span class="n">d1</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">cur</span> <span class="o">==</span> <span class="n">Color</span><span class="p">.</span><span class="n">BLUE</span><span class="p">:</span>
    <span class="k">if</span> <span class="mi">4</span> <span class="o">-</span> <span class="n">rn</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">if</span> <span class="mi">4</span> <span class="o">-</span> <span class="n">gn</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">d0</span> <span class="o">=</span> <span class="n">rn</span> <span class="o">==</span> <span class="mi">2</span>
            <span class="n">d1</span> <span class="o">=</span> <span class="n">rn</span> <span class="o">==</span> <span class="mi">3</span>
            <span class="k">if</span> <span class="n">d0</span> <span class="ow">or</span> <span class="n">d1</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">out</span> <span class="o">=</span> <span class="n">Color</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</code></pre></div></div>

<p>All that remained was to extract the three boards from the game. I dug around a bit in the card scripts to try to find them, but Paul managed to grab them before I could by running <code class="language-plaintext highlighter-rouge">strings</code> on the file (there were a couple of duplicates):</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>strings game_cleaned.rc1 | <span class="nb">grep</span> <span class="nt">-E</span> <span class="s1">'put "[rgb ]+" into constraints'</span> | <span class="nb">sort</span> <span class="nt">-u</span>
<span class="go">put "rbr  bbggrgrggb   bggbb b  b bbrbbgg gbrrbgrbbb g" into constraints
put "rbrr rgb rb  r brgrbrgb  grrgbbg grg bgrg  bbgrbg" into constraints
put "rrbrb rg g  bgrbgggr ggrgr gr rg brr  b  bggrbgbb" into constraints
</span></code></pre></div></div>

<h2 id="debugging">Debugging</h2>

<p>While we had tried our best to transcribe the automaton’s rules accurately, we found that the board in our simulation would run out of red squares within a couple of steps, making it impassible. Clearly there was something wrong with our Python script (you may have found it already), but we couldn’t see anything obviously incorrect so we set out to debug the issue by comparing our results with the actual program’s. As the XCMD had few external dependencies, this process was made somewhat more straightforward.</p>

<p>While Paul and Eric split off to try to emulate it in <a href="http://www.unicorn-engine.org">Unicorn</a>, I sat down to try to get a debugger on the process using <a href="https://en.wikipedia.org/wiki/MacsBug">MacsBug</a>.</p>

<aside>

  <p class="aside-type">Note</p>

  <p class="aside-content">I am obligated to mention that MacsBug stands for “<strong>M</strong>otorola <strong>A</strong>dvanced <strong>C</strong>omputer <strong>S</strong>ystems De<strong>bug</strong>ger”, not “Macs debugger”.</p>

</aside>

<p>I managed to find a copy of MacsBug and install it in SheepSaver, but had a hard time figuring out how to get it to trigger: on real Macs you’d press a key (the “programmer key”) that would send a non-maskable interrupt, or the Command and Power buttons, but neither was easy to figure out how to do in the emulator. I eventually found a forum post that contained SDL2 Cocoa keybindings, which I tweaked a little to remap an unused key to power, but this just caused SheepSaver to crash. The emulator has a number of flags that you can pass it in from the command line with hopeful names like <code class="language-plaintext highlighter-rouge">--ignoresegv</code> and <code class="language-plaintext highlighter-rouge">--ignoreillegal</code>, but neither seemed to work so I gave up on using SheepSaver. Meanwhile, while I wasn’t directly involved in what they were doing, I knew Eric and Paul had a harness up and were working on some unimplemented opcode, but they ran into emulation fidelity issues that prevented accurate simulation. With both of them on that, I figured it was time to try something else, so I found <a href="https://jamesbadger.ca/2018/11/07/emulate-mac-os-9-with-qemu/">a guide on installing Mac OS 9 in QEMU</a> and decided to go through with that.</p>

<p>First, I had to get through the setup screen, which asked a lot of personal questions and then threw you into this screen:</p>

<p><img src="QEMUMacOSSetup.png" alt="Mac OS setup screen in QEMU, on the &quot;Tell me more about the internet&quot; screen" /></p>

<p>With a bit of fiddling around I got MacsBug installed:</p>

<p><img src="QEMUDebuggerInstalled.png" alt="Mac OS boot screen in QEMU, showing that the debugger has been installed" /></p>

<p>Using the QEMU monitor (<code class="language-plaintext highlighter-rouge">-monitor stdio</code>), it was easy to deliver an NMI to Mac OS and get it to successfully drop into MacsBug. It took a little while to get used to it, but after using MacsBug for a bit it seems quite nice; it even has a number of nice GUI features like being able to click on addresses! Initially I used the <code class="language-plaintext highlighter-rouge">F</code> (Find) command to find the function names in memory (since they are included in the binary) but ran into some snags. As Mac OS has no memory segmentation, I hit an issue similar to the one you may have run into when you grep the output of <code class="language-plaintext highlighter-rouge">ps</code>: you find your query itself! In this case, the search was probing through the entire address space and running into the query string in the debugger’s memory. Looking through the manual, I found the <code class="language-plaintext highlighter-rouge">HZ</code> (Heap Zone) command, which let me limit the space I needed to search, and after figuring out that the XCMD was dynamically loaded I managed to find the code and set a breakpoint in it using a raw address. However, I noticed that MacsBug had “symbolicated” the disassembly (<code class="language-plaintext highlighter-rouge">IL</code>, Disassemble From Address), so I pushed my luck and tried a straightforward <code class="language-plaintext highlighter-rouge">BR</code> (Breakpoint) with a function name. Apparently the XCMD had enough information to make this work, and from there working with the module was quite easy.</p>

<p><img src="QEMUMacsBug.png" alt="MacsBug in QEMU, with a breakpoint set on `ENTRYPOINT` and the instruction listing confirming that the code matches our XCMD" /></p>

<p>Paul and Eric abandoned the code they were working on as I got them up to speed on how to use MacsBug, and Paul quickly found the discrepancy between our script and the XCMD. Comparing square by square, the bug in the Python code was obvious: I had forgotten a pair of parentheses when creating the transition rules for green and blue squares, and our <code class="language-plaintext highlighter-rouge">d0 or d1 == 0</code> statements were being interpreted as <code class="language-plaintext highlighter-rouge">d0 or (d1 == 0)</code> rather than <code class="language-plaintext highlighter-rouge">(d0 or d1) == 0</code> as was intended. (In my defense, <a href="https://docs.python.org/3/reference/expressions.html#operator-precedence">the table in Python’s documentation</a> is in the opposite order from <a href="https://en.cppreference.com/w/c/language/operator_precedence">what I’d expect</a>…).</p>

<p>With the fix in place, Paul finished writing a DFS solver for the correct solutions, and we all watched as Eric shared his screen and clicked his way through the puzzles. Our efforts were rewarded with the flag, pctf{l1ke_a_lost_ag3_fkz7bqxp}.</p>

<p><img src="QEMUFlag.png" alt="HyperCard running on QEMU showing the flag for The Watness 2" /></p>

<aside>

  <p class="aside-type">Aside</p>

  <p>By the way, here is what the evolution of puzzle boards looks like dynamically, along with the correct path we found through them:</p>

  <p><img src="Puzzles.svg" alt="Animation of the three puzzle boards, with the path superimposed on them" /></p>

  <p>I am curious if the cellular automata are Turing complete…</p>

</aside>]]></content><author><name></name></author><summary type="html"><![CDATA[I’m a Capture the Flag (CTF) player with Shellphish, and last weekend our team participated in PlaidCTF 2020, an event organized by the Plaid Parliament of Pwning (PPP). As a pre-qualifier for the DEF CON CTF 2020, it’s historically been a fairly challenging competition–this year our team only managed to place 17th, slightly below our usual performance, as many of our team members were preoccupied with inconveniently-placed project deadlines. However, the rest of us had a great time working on the challenges; I helped solve two, golf.so and The Watness 2. golf.so was released early in the CTF and asked teams to create small shared libraries that would call execve("/bin/sh", ["/bin/sh"], ...) when LD_PRELOADed in to /bin/true; a number of us worked together to solve this fairly quickly, getting under 194 bytes (the requirement for the full 500 points) with some aggressive but straightforward segment overlapping, careful trimming of “required” but leniently checked fields, and stuffing of code into the remaining header bytes that were required but could be set to fairly arbitrary values. Some teams golfed it further to 136 bytes, although I’m not sure how (or why, beside bragging rights) they did so. The Watness 2 took longer and in my opinion was a bit more interesting, and this is the one we’ll be talking about here.]]></summary></entry><entry><title type="html">Designing a Better `strcpy`</title><link href="https://saagarjha.com/blog/2020/04/12/designing-a-better-strcpy/" rel="alternate" type="text/html" title="Designing a Better `strcpy`" /><published>2020-04-12T00:00:00+00:00</published><updated>2020-04-12T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2020/04/12/designing-a-better-strcpy</id><content type="html" xml:base="https://saagarjha.com/blog/2020/04/12/designing-a-better-strcpy/"><![CDATA[<p>Like them or not, <a href="https://en.wikipedia.org/wiki/Null-terminated_string">null-terminated strings</a> are essential to C, and working with them is necessary in all but the most trivial programs. While C-style strings are a fundamental part of using the language, manipulating them is a common source of security bugs and lost performance. One of the most common operations is copying a string from one buffer to another, and there are a variety of string functions that claim to do this in C. Anecdotally, however, there is much confusion about what they actually do, and many people desire a string copying function with the following properties:</p>

<ol>
  <li>The function should accept a null-terminated source string, a destination buffer, and an integer representing the size of the destination buffer.</li>
  <li>Upon return the function should ensure that the destination buffer points to a null-terminated string containing a prefix of the source string when possible (specifically, when the destination buffer has a non-zero size) to avoid issues in the future with unterminated strings. (While string truncation has its own issues, it is often a fairly reasonable fallback.)</li>
  <li>The function should indicate how many characters it copied from the source, as well as indicate if an overflow occurred. (This allows for dealing with the overflow, if desired.)</li>
  <li>The function should be efficient, and it should not read or write memory that it does not have to. These go partially hand-in-hand: the function should run in a single pass, not write to the destination buffer past the NUL byte it places, or read characters from the source string once it’s determined that it has filled the destination buffer. Ideally, the implementation would be vectorizable (relaxing some of the previous constraints slightly to within platform alignment guarantees).</li>
  <li>The function should be standardized, so that it may be used portably across systems. Conformance to <a href="https://en.wikipedia.org/wiki/ANSI_C">ISO C</a> or <a href="https://en.wikipedia.org/wiki/POSIX">POSIX.1</a> are generally the most desirable.</li>
</ol>

<p>That is, what is often necessary is the function below, which we’ll call <code class="language-plaintext highlighter-rouge">strxcpy</code>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="o">*</span><span class="nf">strxcpy</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">len</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="k">while</span> <span class="p">(</span><span class="o">--</span><span class="n">len</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="o">*</span><span class="n">dst</span><span class="o">++</span> <span class="o">=</span> <span class="o">*</span><span class="n">src</span><span class="o">++</span><span class="p">))</span>
		<span class="p">;</span>

	<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">len</span><span class="p">)</span> <span class="p">{</span>
		<span class="o">*</span><span class="n">dst</span><span class="o">++</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
		<span class="k">return</span> <span class="o">*</span><span class="n">src</span> <span class="o">?</span> <span class="nb">NULL</span> <span class="o">:</span> <span class="n">dst</span><span class="p">;</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">dst</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<!-- I made a mistake somewhere, didn't I? -->

<p>Other than standardization, this function will copy the smaller of <code class="language-plaintext highlighter-rouge">strlen(src)</code> or <code class="language-plaintext highlighter-rouge">len - 1</code> bytes from <code class="language-plaintext highlighter-rouge">src</code> to <code class="language-plaintext highlighter-rouge">dst</code> and cap the copy with a NUL character. In the case where <code class="language-plaintext highlighter-rouge">src</code> fits in <code class="language-plaintext highlighter-rouge">dst</code>, it will return a pointer past the NUL byte it placed; otherwise it returns <code class="language-plaintext highlighter-rouge">NULL</code> to indicate a truncation. While <a href="https://godbolt.org/z/f8nD4u">current</a> <a href="https://godbolt.org/z/LDBm9y">compilers</a> seem to have trouble with its control flow, it should also be fairly straightforwards to vectorize, as the core loop is somewhat similar to a combination of <code class="language-plaintext highlighter-rouge">strncpy</code> and <code class="language-plaintext highlighter-rouge">strlen</code>.</p>

<p>With guidance to look back to, let’s take a look at a variety of copying routines and see if they can help us.</p>

<aside>

  <p class="aside-type">Note</p>

  <p class="aside-content">To head off the usual concerns, we’ll assume that we must use C, and that we will be eschewing the various length-prefixed or aggregate string constructions available as third-party libraries. While using a different language can solve many of the issues in C besides the one mentioned here; it’s not always desirable or even possible to utilize them. In addition to the usual drawbacks to using third-party libraries, replacing null-terminated strings often causes added syntactical overhead and incompatibilities with other code that has been designed to work with them.</p>

</aside>

<h2 id="some-commonly-used-string-copying-routines">Some commonly used string copying routines</h2>

<h3 id="strcpy"><code class="language-plaintext highlighter-rouge">strcpy</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h4 id="signature">Signature</h4>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="kt">char</span> <span class="o">*</span><span class="nf">strcpy</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">);</span>
</code></pre></div>    </div>

    <h4 id="standardization">Standardization</h4>

    <p><code class="language-plaintext highlighter-rouge">strcpy</code> conforms to <a href="https://en.cppreference.com/w/c/string/byte/strcpy">ISO C90</a>.</p>

    <h4 id="notes">Notes</h4>

    <p>The standard <code class="language-plaintext highlighter-rouge">strcpy</code> function, which copies characters from <code class="language-plaintext highlighter-rouge">src</code> to <code class="language-plaintext highlighter-rouge">dst</code>, up to and including the first NUL byte encountered. If <code class="language-plaintext highlighter-rouge">dst</code> is smaller than or aliases <code class="language-plaintext highlighter-rouge">src</code>, then the behavior of the program is undefined. <code class="language-plaintext highlighter-rouge">dst</code> is returned.</p>

  </details>

</aside>

<p><code class="language-plaintext highlighter-rouge">strcpy</code> certainly fulfills requirement 2 and parts of 4: it will always write out a null-terminated string and it’ll do so quickly. However, it cannot perform bounds checks at all, so we can only use it if we know our source buffer is smaller than our destination buffer–it fails requirement 1. Plus it doesn’t tell us how many characters it wrote, either–that’s requirement 3. It’s been part of C forever, so it does meet requirement 5.</p>

<h3 id="strncpy"><code class="language-plaintext highlighter-rouge">strncpy</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h3 id="signature-1">Signature</h3>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="kt">char</span> <span class="o">*</span><span class="nf">strncpy</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
</code></pre></div>    </div>

    <h3 id="standardization-1">Standardization</h3>

    <p><code class="language-plaintext highlighter-rouge">strncpy</code> conforms to <a href="https://en.cppreference.com/w/c/string/byte/strncpy">ISO C90</a>.</p>

    <h3 id="notes-1">Notes</h3>

    <p><code class="language-plaintext highlighter-rouge">strncpy</code> copies up to <code class="language-plaintext highlighter-rouge">len</code> characters from <code class="language-plaintext highlighter-rouge">src</code> to <code class="language-plaintext highlighter-rouge">dst</code>. If <code class="language-plaintext highlighter-rouge">src</code> is shorter than <code class="language-plaintext highlighter-rouge">len</code>, then <code class="language-plaintext highlighter-rouge">dst</code> is NUL-padded to <code class="language-plaintext highlighter-rouge">len</code> characters. <code class="language-plaintext highlighter-rouge">dst</code> is returned.</p>

  </details>

</aside>

<p><code class="language-plaintext highlighter-rouge">strncpy</code> takes the parameters we want, so it satisfies requirement 1; even in the face of an arbitrary source string it won’t exhibit undefined behavior, provided that we supply it with the correct destination buffer length. However, if the source is longer that the destination, the buffer will not be null-terminated, and if it is shorter <code class="language-plaintext highlighter-rouge">strncpy</code> will continue writing NUL bytes to the destination up to its size. In addition, it doesn’t indicate how many characters from the source were written, though it is possible to detect overflow by writing a NUL byte to the last character of the destination buffer and checking it after the call. That means it fails requirements 2, 3, and 4, but as it’s been around in C for as long as <code class="language-plaintext highlighter-rouge">strcpy</code> it does meet requirement 5.</p>

<h3 id="memcpy"><code class="language-plaintext highlighter-rouge">memcpy</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h3 id="signature-2">Signature</h3>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="kt">void</span> <span class="o">*</span><span class="nf">memcpy</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">n</span><span class="p">);</span>
</code></pre></div>    </div>

    <h3 id="standardization-2">Standardization</h3>

    <p><code class="language-plaintext highlighter-rouge">memcpy</code> conforms to <a href="https://en.cppreference.com/w/c/string/byte/memcpy">ISO C90</a>.</p>

    <h3 id="notes-2">Notes</h3>

    <p>Copies <code class="language-plaintext highlighter-rouge">n</code> bytes form <code class="language-plaintext highlighter-rouge">src</code> to <code class="language-plaintext highlighter-rouge">dst</code>, returning <code class="language-plaintext highlighter-rouge">dst</code>.</p>

  </details>

</aside>

<p><code class="language-plaintext highlighter-rouge">memcpy</code> doesn’t care about NUL characters at all; it doesn’t even require the source to be a null-terminated string. It fails the first three requirements right off the bat, but it’s part of C and it sure is fast so it meets requirements 4 and 5.</p>

<h3 id="strcpy_s"><code class="language-plaintext highlighter-rouge">strcpy_s</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h3 id="signature-3">Signature</h3>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define __STDC_WANT_LIB_EXT1__ 1
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="cp">#ifdef __STDC_LIB_EXT1__
</span><span class="n">errno_t</span> <span class="nf">strcpy_s</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="n">rsize_t</span> <span class="n">len</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">);</span>
<span class="cp">#endif
</span></code></pre></div>    </div>

    <h3 id="standardization-3">Standardization</h3>

    <p><code class="language-plaintext highlighter-rouge">strcpy_s</code> conforms to <a href="https://en.cppreference.com/w/c/string/byte/strcpy">ISO C11</a>, and is available if <code class="language-plaintext highlighter-rouge">__STDC_WANT_LIB_EXT1__</code> is defined prior to including string.h and <code class="language-plaintext highlighter-rouge">__STDC_LIB_EXT1__</code> is defined.</p>

    <h3 id="notes-3">Notes</h3>

    <p>A bounds-checked version of <code class="language-plaintext highlighter-rouge">strcpy</code> that performs the same operation and returns zero except it can write unspecified values to the remainder of <code class="language-plaintext highlighter-rouge">dst</code>, and if <code class="language-plaintext highlighter-rouge">src == NULL</code>, <code class="language-plaintext highlighter-rouge">dst == NULL</code>, if truncation would occur, <code class="language-plaintext highlighter-rouge">len</code> is zero or greater than <code class="language-plaintext highlighter-rouge">RSIZE_MAX</code>, or <code class="language-plaintext highlighter-rouge">src</code> and <code class="language-plaintext highlighter-rouge">dst</code> overlap, it will write a NUL byte to <code class="language-plaintext highlighter-rouge">*dst</code> if possible, return a nonzero value, and call a constraint handler function.</p>

  </details>

</aside>

<p>On the surface, this function <em>seems</em> useful–but a closer look shows that it has a number of unfortunate issues. The largest is that any truncation will call a constraint handler function which can do many things, <a href="https://en.cppreference.com/w/c/error/abort_handler_s">like abort the program</a>. In addition, it doesn’t tell us how much it wrote, can scribble over the destination, and is standardized but only available as an optional extension to C11. Overall, it only satisfies requirement 1.</p>

<h3 id="strncpy_s"><code class="language-plaintext highlighter-rouge">strncpy_s</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h3 id="signature-4">Signature</h3>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define __STDC_WANT_LIB_EXT1__ 1
#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="cp">#ifdef __STDC_LIB_EXT1__
</span><span class="n">errno_t</span> <span class="nf">strncpy_s</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
<span class="cp">#endif
</span></code></pre></div>    </div>

    <h3 id="standardization-4">Standardization</h3>

    <p><code class="language-plaintext highlighter-rouge">strncpy_s</code> conforms to <a href="https://en.cppreference.com/w/c/string/byte/strncpy">ISO C11</a>, and is available if <code class="language-plaintext highlighter-rouge">__STDC_WANT_LIB_EXT1__</code> is defined prior to including string.h and <code class="language-plaintext highlighter-rouge">__STDC_LIB_EXT1__</code> is defined.</p>

    <h3 id="notes-4">Notes</h3>

    <p>A bounds-checked version of <code class="language-plaintext highlighter-rouge">strncpy</code>, that returns a non-zero value if <code class="language-plaintext highlighter-rouge">src == NULL</code>, <code class="language-plaintext highlighter-rouge">dst == NULL</code>, if truncation would occur, <code class="language-plaintext highlighter-rouge">len</code> is zero or greater than <code class="language-plaintext highlighter-rouge">RSIZE_MAX</code>, or <code class="language-plaintext highlighter-rouge">src</code> and <code class="language-plaintext highlighter-rouge">dst</code> overlap, in which case it will write the NUL byte to <code class="language-plaintext highlighter-rouge">*dst</code> if possible, unspecified values to the remainder of <code class="language-plaintext highlighter-rouge">dst</code>, return a nonzero value, and call a constraint handler function. Otherwise is will copy <code class="language-plaintext highlighter-rouge">len</code> bytes from <code class="language-plaintext highlighter-rouge">src</code> to <code class="language-plaintext highlighter-rouge">dst</code> and then add a NUL terminating byte at <code class="language-plaintext highlighter-rouge">dst[len - 1]</code>, returning zero.</p>

  </details>

</aside>

<p>This function has the same constraint handler issue as <code class="language-plaintext highlighter-rouge">strcpy_s</code>, and is also standardized but often not available. While it will  null-terminate when the string fits and only clobber the destination on an error, it still only satisfies the first requirement.</p>

<h3 id="stpncpy"><code class="language-plaintext highlighter-rouge">stpncpy</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h4 id="signature-5">Signature</h4>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="kt">char</span> <span class="o">*</span><span class="nf">stpncpy</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
</code></pre></div>    </div>

    <h4 id="standardization-5">Standardization</h4>

    <p><code class="language-plaintext highlighter-rouge">stpncpy</code> conforms to <a href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/string.h.html">POSIX.1-2008</a>.</p>

    <h4 id="notes-5">Notes</h4>

    <p>Identical to <code class="language-plaintext highlighter-rouge">strncpy</code>, except that a pointer to the written NUL byte is returned, if any; otherwise <code class="language-plaintext highlighter-rouge">dst + len</code> is returned.</p>

  </details>

</aside>

<p><code class="language-plaintext highlighter-rouge">stpncpy</code> is an improvement on <code class="language-plaintext highlighter-rouge">strncpy</code>, but it only fixes the issue of detecting termination or overflow, which is requirement 3. It still fails requirement 2 because it doesn’t necessarily null-terminate and it fails requirement 4 because it writes NULs to the end of the destination buffer. Unlike <code class="language-plaintext highlighter-rouge">strncpy</code> it’s part of POSIX, but it still meets requirement 5 in addition to requirement 1.</p>

<h3 id="snprintf"><code class="language-plaintext highlighter-rouge">snprintf</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h4 id="signature-6">Signature</h4>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">snprintf</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">fmt</span><span class="p">,</span> <span class="p">...);</span>
</code></pre></div>    </div>

    <h4 id="standardization-6">Standardization</h4>

    <p><code class="language-plaintext highlighter-rouge">snprintf</code> conforms to <a href="https://en.cppreference.com/w/c/io/snprintf">ISO C99</a>.</p>

    <h4 id="notes-6">Notes</h4>

    <p>When used with <code class="language-plaintext highlighter-rouge">%s</code> as <code class="language-plaintext highlighter-rouge">fmt</code>, copies the first variadic parameter (a string) to <code class="language-plaintext highlighter-rouge">dst</code>, or the first <code class="language-plaintext highlighter-rouge">len - 1</code> bytes followed by the NUL byte. Returns the length of the first variadic parameter.</p>

  </details>

</aside>

<p><code class="language-plaintext highlighter-rouge">snprintf</code> is a somewhat strange inclusion, but it’s a standard function that can help us if we use “%s” as the format string, taking a size and null-terminating its destination. It fulfills requirements 1, 2, and 5, but falls short on 3 and 4: its return value is essentially “what <code class="language-plaintext highlighter-rouge">sprintf</code> would have returned”, which means it must perform an equivalent of a <code class="language-plaintext highlighter-rouge">strlen</code> at the very least. This is slow, not what we want, and an <code class="language-plaintext highlighter-rouge">int</code> (not a <code class="language-plaintext highlighter-rouge">size_t</code>).</p>

<h3 id="strlcpy"><code class="language-plaintext highlighter-rouge">strlcpy</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h4 id="signature-7">Signature</h4>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="kt">size_t</span> <span class="nf">strlcpy</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
</code></pre></div>    </div>

    <h4 id="standardization-7">Standardization</h4>

    <p><code class="language-plaintext highlighter-rouge">strlcpy</code> is a common BSD extension.</p>

    <h4 id="notes-7">Notes</h4>

    <p>Semantically equivalent to <code class="language-plaintext highlighter-rouge">sprintf(dst, len, "%s", src)</code> save for the return value, which is a <code class="language-plaintext highlighter-rouge">size_t</code>.</p>

  </details>

</aside>

<p><code class="language-plaintext highlighter-rouge">strlcpy</code> is identical to the <code class="language-plaintext highlighter-rouge">sprintf</code> invocation from before, except it uses the correct <code class="language-plaintext highlighter-rouge">size_t</code> return type. This still means it fails to satisfy the performance requirements of 3 and 4, and it’s not standard so it doesn’t satisfy 5 either. Since it does the copy and leaves you with a null-terminated string it fills the first two requirements.</p>

<h3 id="strscpy"><code class="language-plaintext highlighter-rouge">strscpy</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h4 id="signature-8">Signature</h4>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">size_t</span> <span class="nf">strscpy</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
</code></pre></div>    </div>

    <h4 id="standardization-8">Standardization</h4>

    <p><code class="language-plaintext highlighter-rouge">strscpy</code> is a <a href="https://www.kernel.org/doc/htmldocs/kernel-api/API-strscpy.html">Linux kernel function</a>.</p>

    <h4 id="notes-8">Notes</h4>

    <p><code class="language-plaintext highlighter-rouge">strscpy</code> copies <code class="language-plaintext highlighter-rouge">src</code> to <code class="language-plaintext highlighter-rouge">dst</code> if it fits in the buffer and return the number of characters copied excluding the trailing NUL byte; otherwise it will copy the first <code class="language-plaintext highlighter-rouge">len - 1</code> characters and set <code class="language-plaintext highlighter-rouge">dst[len - 1]</code> to a NUL byte, returning <code class="language-plaintext highlighter-rouge">-E2BIG</code>.</p>

  </details>

</aside>

<p><code class="language-plaintext highlighter-rouge">strscpy</code> is the first function we’ve seen that satisfies the four functional requirements: it copies the as much of the source string as possible, null terminates the destination buffer, returns the number of characters copied, and does not perform excessive reads or writes. In fact, we can implement our <code class="language-plaintext highlighter-rouge">strxcpy</code> function using it:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="o">*</span><span class="nf">strxcpy</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
	<span class="kt">ssize_t</span> <span class="n">copied</span> <span class="o">=</span> <span class="n">strscpy</span><span class="p">(</span><span class="n">dst</span><span class="p">,</span> <span class="n">src</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
	<span class="k">return</span> <span class="n">copied</span> <span class="o">!=</span> <span class="o">-</span><span class="n">E2BIG</span> <span class="o">:</span> <span class="n">src</span> <span class="o">+</span> <span class="n">copied</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">:</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>It has two issues: the first, is that it returns an <code class="language-plaintext highlighter-rouge">ssize_t</code> rather than a <code class="language-plaintext highlighter-rouge">size_t</code>, but in practice this isn’t really a problem. The second is that it’s unfortunately non-standard–it’s something the Linux kernel wrote for itself–which means it violates requirement 5.</p>

<h3 id="memccpy"><code class="language-plaintext highlighter-rouge">memccpy</code></h3>

<aside>

  <details>
    <summary>

      <p class="aside-type">Summary</p>

    </summary>

    <h3 id="signature-9">Signature</h3>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span>
<span class="kt">void</span> <span class="o">*</span><span class="nf">memccpy</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">int</span> <span class="n">chr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">);</span>
</code></pre></div>    </div>

    <h3 id="standardization-9">Standardization</h3>

    <p><code class="language-plaintext highlighter-rouge">memccpy</code> is an <a href="https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap02.html#tag_02_01_04">XSI extension</a> to <a href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/string.h.html">POSIX.1-2001</a>, and is <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2349.htm">planned to be added</a> to <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2479.pdf">ISO C2X</a>.</p>

    <h3 id="notes-9">Notes</h3>

    <p><code class="language-plaintext highlighter-rouge">memccpy</code> is identical to <code class="language-plaintext highlighter-rouge">memcpy</code>, but may stop prematurely if <code class="language-plaintext highlighter-rouge">src</code> contains <code class="language-plaintext highlighter-rouge">chr</code>, copying <code class="language-plaintext highlighter-rouge">chr</code> and returning pointer after its location in <code class="language-plaintext highlighter-rouge">dst</code>. If <code class="language-plaintext highlighter-rouge">len</code> characters are copied without encountering <code class="language-plaintext highlighter-rouge">chr</code>, then <code class="language-plaintext highlighter-rouge">NULL</code> is returned.</p>

  </details>

</aside>

<p><code class="language-plaintext highlighter-rouge">memccpy</code>, when used with the NUL character, satisfies all the requirements except for the second one, but this is trivial to fix:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="o">*</span><span class="nf">strxcpy</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="kr">restrict</span> <span class="n">src</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
	<span class="kt">char</span> <span class="o">*</span><span class="n">end</span> <span class="o">=</span> <span class="n">memccpy</span><span class="p">(</span><span class="n">dst</span><span class="p">,</span> <span class="n">src</span><span class="p">,</span> <span class="sc">'\0'</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
	<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">end</span> <span class="o">&amp;&amp;</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">dst</span><span class="p">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="n">end</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>While it’ll ship in an upcoming C standard, it’s already widely available as a popular, optional POSIX extension.</p>

<aside class="aside-fun-fact">

  <p class="aside-type">Fun fact</p>

  <p class="aside-content">The original implementation listed here contained a bug when handling <code class="language-plaintext highlighter-rouge">len == 0</code>. Fittingly, the out-of-bounds write went unnoticed for over two years, which goes to show that string handling in C remains difficult ;) Thanks to <a href="https://forums.rockbox.org/index.php?action=profile;u=63414">Bilgus</a> for finding this!</p>

</aside>

<h3 id="other-functions">Other functions</h3>

<p>There’s a couple of other functions–<code class="language-plaintext highlighter-rouge">stpcpy</code>, <code class="language-plaintext highlighter-rouge">mempcpy</code>, <code class="language-plaintext highlighter-rouge">sprintf</code>, <code class="language-plaintext highlighter-rouge">sprintf_s</code>, and <code class="language-plaintext highlighter-rouge">snprintf_s</code>–that have been omitted for brevity, as their behavior (and issues) are fairly self-explanatory based on the other functions. (<code class="language-plaintext highlighter-rouge">mempcpy</code> is a GNU extension.)</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>Copying strings in C is an extremely common operation, but doing so safely and efficiently is non-trivial. Almost all currently available string routines, standardized or not, have subtle quirks that often prevent them from matching the expectations of the programmer who reaches for them. This issue is compounded by the fact that many style guides or linters will recommend the use of one (or sometimes more than one!) of these functions to replace <code class="language-plaintext highlighter-rouge">strcpy</code> without discussing their limitations. Finally, as we saw above the functions compose quite poorly: our <code class="language-plaintext highlighter-rouge">strxcpy</code>, an academic but not improbable scenario, could not use any of them in its implementation; one can only imagine that those writing an ad-hoc replacement for it may make both errors in doing so.</p>

<p>In contrast, the standardization of <code class="language-plaintext highlighter-rouge">memccpy</code> is a very welcome improvement, as it facilitates the construction of safer and more efficient string algorithms–in addition to <code class="language-plaintext highlighter-rouge">strxcpy</code>, a number of the functions discussed are <em>also</em> easy to construct with it. As it becomes more widespread, most code that relies on some of the semantics of <code class="language-plaintext highlighter-rouge">strxcpy</code> but uses one of the other functions to achieve it should probably migrate to <code class="language-plaintext highlighter-rouge">memccpy</code>, and ideally the push to phase out the use of them will drive the standardization and adoption of many more widely applicable string functions.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Like them or not, null-terminated strings are essential to C, and working with them is necessary in all but the most trivial programs. While C-style strings are a fundamental part of using the language, manipulating them is a common source of security bugs and lost performance. One of the most common operations is copying a string from one buffer to another, and there are a variety of string functions that claim to do this in C. Anecdotally, however, there is much confusion about what they actually do, and many people desire a string copying function with the following properties:]]></summary></entry><entry><title type="html">Jailed Just-in-Time Compilation on iOS</title><link href="https://saagarjha.com/blog/2020/02/23/jailed-just-in-time-compilation-on-ios/" rel="alternate" type="text/html" title="Jailed Just-in-Time Compilation on iOS" /><published>2020-02-23T00:00:00+00:00</published><updated>2020-02-23T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2020/02/23/jailed-just-in-time-compilation-on-ios</id><content type="html" xml:base="https://saagarjha.com/blog/2020/02/23/jailed-just-in-time-compilation-on-ios/"><![CDATA[<p>Just-in-time compilation on iOS normally requires applications to possess the dynamic-codesigning entitlement, a privilege that Apple uniquely awards to system processes that require the high-performance tiers of JavaScriptCore. “True” just-in-time compilers require the ability to generate executable pages with an invalid code signature, a practice that is usually prohibited on iOS for third-party apps because it sidesteps code validation guarantees that Apple would like to enforce. While these applications cannot use <code class="language-plaintext highlighter-rouge">mmap</code>’s <code class="language-plaintext highlighter-rouge">MAP_JIT</code> without this entitlement (the usual way to create a RWX region for JIT purposes), there is a method that does work on devices without a jailbreak, though its combination of being unfit for the App Store and really only being useful for speeding up virtual machines makes it seemingly unknown outside of the emulation community. The technique relies on a somewhat arcane side effect of how debugging works on iOS to enable a slightly more limited JIT.</p>

<aside class="aside-update">

  <p class="aside-type">Update, 6/24/20</p>

  <p class="aside-content">Preliminary testing on iOS 14 seems to indicate that Apple has changed the kernel so that this trick no longer works.</p>

</aside>

<h2 id="introducing-the-wx-jit">Introducing the W^X JIT</h2>

<p>The simplest way to implement a JIT is to create pages that have both <code class="language-plaintext highlighter-rouge">PROT_WRITE</code> and <code class="language-plaintext highlighter-rouge">PROT_EXEC</code> (along with <code class="language-plaintext highlighter-rouge">PROT_READ</code>–this isn’t the <a href="https://www.blackhat.com/docs/us-16/materials/us-16-Krstic.pdf">bulletproof JIT</a>) enabled simultaneously, writing code into this region, and executing it. As this code is generated on the fly, it lack a code signature to back it, and <code class="language-plaintext highlighter-rouge">mmap</code> (or its Mach VM equivalents) will only allow these kinds of mappings if the process requesting them possesses the dynamic-codesigning entitlement and passes the <code class="language-plaintext highlighter-rouge">MAP_JIT</code> flag as mentioned previously. But we don’t actually need both permissions at the same time: unless we’re generating self-modifying code, we only need the write permissions when writing the code to memory and the execute permissions when executing it. In fact, if we just continually flipped the permissions of the pages back and forth between <code class="language-plaintext highlighter-rouge">PROT_WRITE</code> and <code class="language-plaintext highlighter-rouge">PROT_EXEC</code> based on when we were generating or running code, we’d be able to implement a just-in-time compiler while still maintaining the exclusivity of <a href="https://en.wikipedia.org/wiki/W%5EX">W^X</a>–we’d never have a page be both at once. Many platforms other than iOS enforce this policy by default as a rudimentary security mitigation, including OpenBSD.</p>

<p>While this approach works, continuously changing page permissions is often quite slow. A better solution for performance is to (ab)use memory mappings to map the same physical page twice, with two virtual addresses, one of which is accessible with write permissions and one which enables execute permissions. From the perspective of virtual memory, the address space is still W^X, but by using the appropriate pointer to access the memory the region is effectively RWX.</p>

<h2 id="the-cs_debugged-loophole">The <code class="language-plaintext highlighter-rouge">CS_DEBUGGED</code> loophole</h2>

<p>On iOS there is normally no reason for a third-party process to need to possess invalid pages except for one: when it is being debugged. Since setting breakpoints requires overwriting code with an appropriate trapping instruction, debugging a process <a href="https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_cs.c#L217">must disable</a> the <code class="language-plaintext highlighter-rouge">CS_KILL</code> and <code class="language-plaintext highlighter-rouge">CS_HARD</code> flags that would ordinary cause a process to be killed when its code signature becomes invalid; a program in this state instead has the <code class="language-plaintext highlighter-rouge">CS_DEBUGGED</code> flag <a href="https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_cs.c#L220">set on it</a>.</p>

<p>The usual way this flag gets set is using Xcode to debug the app, which causes debugserver to attach the process by <a href="https://github.com/llvm/llvm-project/blob/bae33a7c5a1f220671e6d99cda21749afe2501a6/lldb/tools/debugserver/source/MacOSX/MachProcess.mm#L2552">using <code class="language-plaintext highlighter-rouge">ptrace</code> with the <code class="language-plaintext highlighter-rouge">PT_ATTACHEXC</code> request</a> (which the same as the deprecated <code class="language-plaintext highlighter-rouge">PT_ATTACH</code>, except it causes signals to be delivered as Mach exceptions; see below). However, relying on debugserver to make our JIT work is somewhat inconvenient and cumbersome: ideally there would be a way to do this without having to be connected to Xcode all the time. Since <a href="https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/mach_process.c#L484">we cannot attach to ourselves</a>, it’d be nice if we could create a new, temporary process with the sole purpose to attach to ours to set <code class="language-plaintext highlighter-rouge">CS_DEBUGGED</code>…except that this is nonjailbroken iOS, where we can’t spawn new processes. Hmm.</p>

<p>A closer look at <code class="language-plaintext highlighter-rouge">ptrace</code>’s documentation reveals an interesting request: <code class="language-plaintext highlighter-rouge">PT_TRACE_ME</code>, intended to be used by a process that expects to be traced. In addition to the interesting property that it is called by the <em>child</em> process (that is: ours, not the debugger’s!), it <em>also</em> <a href="https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/mach_process.c#L191">disables code signing validation</a>!</p>

<aside class="aside-fun-fact">

  <p class="aside-type">Fun fact</p>

  <p class="aside-content">Interestingly, it disables validation in the <em>parent</em> process as well for some reason. I wonder if calling this in an ordinary process will end up disabling validation in its parent process, launchd, or if this is blocked by MAC.</p>

</aside>

<p>So all we need to do is call <code class="language-plaintext highlighter-rouge">ptrace</code> with the <code class="language-plaintext highlighter-rouge">PT_TRACE_ME</code> request (the other arguments are ignored) and we’ll have all we need to implement a W^X JIT (unfortunately, a true RWX JIT would still require dynamic-codesigning, because <code class="language-plaintext highlighter-rouge">mmap</code> checks for the entitlement specifically when granting <code class="language-plaintext highlighter-rouge">MAP_JIT</code> requests). While the <code class="language-plaintext highlighter-rouge">&lt;sys/ptrace.h&gt;</code> isn’t the iOS SDK, the function is still present and loaded into every process. In C we can just forward declare the function and the appropriate constants and dynamic linking will take care of the rest:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;sys/types.h&gt;</span><span class="cp">
</span>
<span class="cp">#define PT_TRACE_ME 0
</span><span class="kt">int</span> <span class="nf">ptrace</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span> <span class="n">pid_t</span><span class="p">,</span> <span class="n">caddr_t</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">ptrace</span><span class="p">(</span><span class="n">PT_TRACE_ME</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In Swift, the process is a little more involved, but still fairly straightforward:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">Darwin</span>

<span class="k">let</span> <span class="nv">PT_TRACE_ME</span><span class="p">:</span> <span class="kt">CInt</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">let</span> <span class="nv">ptrace</span> <span class="o">=</span> <span class="nf">unsafeBitCast</span><span class="p">(</span><span class="nf">dlsym</span><span class="p">(</span><span class="nf">dlopen</span><span class="p">(</span><span class="kc">nil</span><span class="p">,</span> <span class="kt">RTLD_LAZY</span><span class="p">),</span> <span class="s">"ptrace"</span><span class="p">),</span> <span class="nv">to</span><span class="p">:</span> <span class="p">(</span><span class="kd">@convention</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="p">(</span><span class="kt">CInt</span><span class="p">,</span> <span class="n">pid_t</span><span class="p">,</span> <span class="n">caddr_t</span><span class="p">?,</span> <span class="kt">CInt</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">CInt</span><span class="p">)</span><span class="o">.</span><span class="k">self</span><span class="p">)</span>

<span class="nf">ptrace</span><span class="p">(</span><span class="kt">PT_TRACE_ME</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="kc">nil</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="limitations">Limitations</h2>

<p>This isn’t a RWX JIT (which isn’t a huge deal as you can still map the memory twice), but there are other limitations to consider. Since this is ARM, <a href="https://github.com/WebKit/webkit/blob/7e6418e6296a1abe0ce4406838c08f2a95dfeb29/Source/JavaScriptCore/assembler/ARM64Assembler.h#L2811">the normal cache-flushing recommendations apply</a>. Unlike processes with dynamic-codesigning, which get access to <a href="https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_exec.c#L3061">“jumbo VA spaces”</a>, iOS applications can normally only allocate a limited amount of virtual memory (which is determined using <a href="https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/osfmk/arm/pmap.c#L9868">a fairly elaborate calculation</a> based on the size of physical memory).</p>

<p>However, one major issue is actually described in description for <code class="language-plaintext highlighter-rouge">PT_TRACE_ME</code> in <a href="https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/ptrace.2.html">the man page for <code class="language-plaintext highlighter-rouge">ptrace(2)</code></a>:</p>

<blockquote>
  <p>PT_TRACE_ME
This request is one of two used by the traced process; it declares that the process expects to be traced by its parent.  All the other arguments are ignored.  <strong>(If the parent process does not expect to trace the child, it will probably be rather confused by the results; once the traced process stops, it cannot be made to continue except via ptrace().)</strong>  When a process has used this request and calls execve(2) or any of the routines built on it (such as execv(3)), it will stop before executing the first instruction of the new image.  Also, any setuid or setgid bits on the executable being executed will be ignored.</p>
</blockquote>

<p>The part I have emphasized is quite important: if the process ends up stopping for any reason, it will be impossible to start it again. When a process is being <code class="language-plaintext highlighter-rouge">ptrace</code>d, it will stop upon delivery of any signal (normally, so the parent process can respond appropriately) but in this cause launchd has no idea that we are being traced so it will not know how to handle it correctly. If our program crashes or is killed by the system, the process will not exit, and this will cause the <em>entire system</em> to slowly grind to a halt as (I think) it first tries to repeatedly <code class="language-plaintext highlighter-rouge">SIGKILL</code> your process, fails to do, and then just hangs in something important while waiting for process termination that will never come. One way to avoid this is to convert signals to Mach exceptions using the <code class="language-plaintext highlighter-rouge">PT_SIGEXC</code> <code class="language-plaintext highlighter-rouge">ptrace</code> request, and install a Mach exception handler to handle these:</p>

<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#import &lt;mach/mach.h&gt;
#import &lt;pthread.h&gt;
#import &lt;sys/sysctl.h&gt;
</span>
<span class="cp">#import "AppDelegate.h"
</span>
<span class="n">boolean_t</span> <span class="nf">exc_server</span><span class="p">(</span><span class="n">mach_msg_header_t</span> <span class="o">*</span><span class="p">,</span> <span class="n">mach_msg_header_t</span> <span class="o">*</span><span class="p">);</span>
<span class="kt">int</span> <span class="nf">ptrace</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span> <span class="n">pid_t</span><span class="p">,</span> <span class="n">caddr_t</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>

<span class="cp">#define PT_TRACE_ME 0
#define PT_SIGEXC 12
</span>
<span class="n">kern_return_t</span> <span class="nf">catch_exception_raise</span><span class="p">(</span><span class="n">mach_port_t</span> <span class="n">exception_port</span><span class="p">,</span>
                                    <span class="n">mach_port_t</span> <span class="kr">thread</span><span class="p">,</span>
                                    <span class="n">mach_port_t</span> <span class="n">task</span><span class="p">,</span>
                                    <span class="n">exception_type_t</span> <span class="n">exception</span><span class="p">,</span>
                                    <span class="n">exception_data_t</span> <span class="n">code</span><span class="p">,</span>
                                    <span class="n">mach_msg_type_number_t</span> <span class="n">code_count</span><span class="p">)</span> <span class="p">{</span>
	<span class="c1">// Forward the request to the next-level Mach exception handler. This will</span>
	<span class="c1">// probably be ReportCrash's.</span>
	<span class="k">return</span> <span class="n">KERN_FAILURE</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="o">*</span><span class="nf">exception_handler</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">argument</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">mach_port_t</span> <span class="n">port</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">mach_port_t</span> <span class="o">*</span><span class="p">)</span><span class="n">argument</span><span class="p">;</span>
	<span class="n">mach_msg_server</span><span class="p">(</span><span class="n">exc_server</span><span class="p">,</span> <span class="mi">2048</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
	<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">ptrace</span><span class="p">(</span><span class="n">PT_TRACE_ME</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="n">ptrace</span><span class="p">(</span><span class="n">PT_SIGEXC</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>

	<span class="n">mach_port_t</span> <span class="n">port</span> <span class="o">=</span> <span class="n">MACH_PORT_NULL</span><span class="p">;</span>
	<span class="n">mach_port_allocate</span><span class="p">(</span><span class="n">mach_task_self</span><span class="p">(),</span> <span class="n">MACH_PORT_RIGHT_RECEIVE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">port</span><span class="p">);</span>
	<span class="n">mach_port_insert_right</span><span class="p">(</span><span class="n">mach_task_self</span><span class="p">(),</span> <span class="n">port</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">MACH_MSG_TYPE_MAKE_SEND</span><span class="p">);</span>
	<span class="c1">// PT_SIGEXC maps signals to EXC_SOFTWARE; note that this will interfere</span>
	<span class="c1">// with the debugger (which will try to do the same thing via PT_ATTACHEXC).</span>
	<span class="c1">// Usually you'd check for that and predicate the execution of the following</span>
	<span class="c1">// code on whether it's attached.</span>
	<span class="n">task_set_exception_ports</span><span class="p">(</span><span class="n">mach_task_self</span><span class="p">(),</span> <span class="n">EXC_MASK_SOFTWARE</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">EXCEPTION_DEFAULT</span><span class="p">,</span> <span class="n">THREAD_STATE_NONE</span><span class="p">);</span>
	<span class="n">pthread_t</span> <span class="kr">thread</span><span class="p">;</span>
	<span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="kr">thread</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">exception_handler</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">port</span><span class="p">);</span>

	<span class="k">@autoreleasepool</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">UIApplicationMain</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">,</span> <span class="nb">nil</span><span class="p">,</span> <span class="n">NSStringFromClass</span><span class="p">([</span><span class="n">AppDelegate</span> <span class="nf">class</span><span class="p">]));</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>While this won’t catch <code class="language-plaintext highlighter-rouge">SIGKILL</code>, we can try to avoid being sent these by exiting before we’d get one in the cases were we can:</p>

<div class="language-objc highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#import "AppDelegate.h"
</span>
<span class="k">@implementation</span> <span class="nc">AppDelegate</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">applicationWillTerminate</span><span class="p">:(</span><span class="n">UIApplication</span> <span class="o">*</span><span class="p">)</span><span class="nv">application</span> <span class="p">{</span>
	<span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">@end</span>
</code></pre></div></div>

<p>Finally, this procedure is unfit for the App Store: not only does it use private API, it requires the process to have the <code class="language-plaintext highlighter-rouge">get-task-allow</code> entitlement, which Apple only grants for code signed with a development certificate. Apps of this type cannot be submitted to the App Store or TestFlight.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Just-in-time compilation on iOS normally requires applications to possess the dynamic-codesigning entitlement, a privilege that Apple uniquely awards to system processes that require the high-performance tiers of JavaScriptCore. “True” just-in-time compilers require the ability to generate executable pages with an invalid code signature, a practice that is usually prohibited on iOS for third-party apps because it sidesteps code validation guarantees that Apple would like to enforce. While these applications cannot use mmap’s MAP_JIT without this entitlement (the usual way to create a RWX region for JIT purposes), there is a method that does work on devices without a jailbreak, though its combination of being unfit for the App Store and really only being useful for speeding up virtual machines makes it seemingly unknown outside of the emulation community. The technique relies on a somewhat arcane side effect of how debugging works on iOS to enable a slightly more limited JIT.]]></summary></entry><entry><title type="html">AppKit in Swift Playgrounds</title><link href="https://saagarjha.com/blog/2020/02/11/appkit-in-swift-playgrounds/" rel="alternate" type="text/html" title="AppKit in Swift Playgrounds" /><published>2020-02-11T00:00:00+00:00</published><updated>2020-02-11T00:00:00+00:00</updated><id>https://saagarjha.com/blog/2020/02/11/appkit-in-swift-playgrounds</id><content type="html" xml:base="https://saagarjha.com/blog/2020/02/11/appkit-in-swift-playgrounds/"><![CDATA[<p>A <a href="https://apps.apple.com/us/app/swift-playgrounds/id1496833156?mt=12">Catalyst version</a> of <a href="https://www.apple.com/swift/playgrounds/">the Swift Playgrounds app</a> launched for macOS earlier today, with support for the <a href="https://developer.apple.com/documentation/uikit/mac_catalyst">Mac Catalyst platform SDK</a>. While it’s usually impractical to import AppKit in a Catalyst application, this is apparently now possible in Swift Playgrounds. Most Cocoa APIs have been marked as unavailable, but <code class="language-plaintext highlighter-rouge">import AppKit</code> does cause the image to actually end up being loaded so it only takes a little bit of work to be able to use them:</p>

<p><img src="AppKitWindow.png" alt="A native AppKit window presented from Swift Playgrounds on macOS. It's titled &quot;Hello from Swift Playgrounds!&quot;." /></p>

<p>Catalyst sets up an application for us already, so all we need to do to show a native window is to find the class for <code class="language-plaintext highlighter-rouge">NSWindow</code> dynamically and mock its interface so the Objective-C runtime will let us call the right methods on it set it up. The code used to make the demo above is quite simple:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">AppKit</span>
<span class="kd">import</span> <span class="kt">PlaygroundSupport</span>
<span class="kd">import</span> <span class="kt">SwiftUI</span>

<span class="kd">@objc</span> <span class="kd">protocol</span> <span class="n">_NSWindow</span> <span class="p">{</span>
    <span class="k">var</span> <span class="nv">title</span><span class="p">:</span> <span class="kt">String</span><span class="p">?</span> <span class="p">{</span> <span class="k">get</span> <span class="k">set</span> <span class="p">}</span>
    <span class="k">var</span> <span class="nv">styleMask</span><span class="p">:</span> <span class="kt">UInt</span> <span class="p">{</span> <span class="k">get</span> <span class="k">set</span> <span class="p">}</span>
    <span class="kd">func</span> <span class="nf">setFrame</span><span class="p">(</span><span class="n">_</span> <span class="nv">frameRect</span><span class="p">:</span> <span class="kt">NSRect</span><span class="p">,</span> <span class="n">display</span> <span class="nv">flag</span><span class="p">:</span> <span class="kt">Bool</span><span class="p">)</span>
    <span class="kd">func</span> <span class="nf">center</span><span class="p">()</span>
    <span class="kd">func</span> <span class="nf">makeKeyAndOrderFront</span><span class="p">(</span><span class="n">_</span> <span class="nv">sender</span><span class="p">:</span> <span class="kt">Any</span><span class="p">?)</span>
<span class="p">}</span>

<span class="k">let</span> <span class="nv">_NSWindowStyleMaskClosable</span><span class="p">:</span> <span class="kt">UInt</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span>

<span class="c1">// A bit more roundabout than it needs to be: see https://bugs.swift.org/browse/SR-4243</span>
<span class="k">let</span> <span class="nv">window</span> <span class="o">=</span> <span class="nf">unsafeBitCast</span><span class="p">((</span><span class="kt">NSClassFromString</span><span class="p">(</span><span class="s">"NSWindow"</span><span class="p">)</span><span class="o">!</span> <span class="k">as!</span> <span class="kt">NSObject</span><span class="o">.</span><span class="k">Type</span><span class="p">)</span><span class="o">.</span><span class="nf">init</span><span class="p">(),</span> <span class="nv">to</span><span class="p">:</span> <span class="n">_NSWindow</span><span class="o">.</span><span class="k">self</span><span class="p">)</span>
<span class="n">window</span><span class="o">.</span><span class="n">styleMask</span> <span class="o">|=</span> <span class="n">_NSWindowStyleMaskClosable</span>
<span class="n">window</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="s">"Hello from Swift Playgrounds!"</span>
<span class="n">window</span><span class="o">.</span><span class="nf">setFrame</span><span class="p">(</span><span class="kt">CGRect</span><span class="p">(</span><span class="nv">x</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nv">y</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="nv">width</span><span class="p">:</span> <span class="mi">300</span><span class="p">,</span> <span class="nv">height</span><span class="p">:</span> <span class="mi">300</span><span class="p">),</span> <span class="nv">display</span><span class="p">:</span> <span class="kc">true</span><span class="p">)</span>
<span class="n">window</span><span class="o">.</span><span class="nf">center</span><span class="p">()</span>
<span class="n">window</span><span class="o">.</span><span class="nf">makeKeyAndOrderFront</span><span class="p">(</span><span class="kc">nil</span><span class="p">)</span>

<span class="kt">PlaygroundPage</span><span class="o">.</span><span class="n">current</span><span class="o">.</span><span class="n">needsIndefiniteExecution</span> <span class="o">=</span> <span class="kc">true</span>
</code></pre></div></div>

<p>Perhaps Apple is simply testing this internally and we’ll be able to do this officially in a future release of Playgrounds.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[A Catalyst version of the Swift Playgrounds app launched for macOS earlier today, with support for the Mac Catalyst platform SDK. While it’s usually impractical to import AppKit in a Catalyst application, this is apparently now possible in Swift Playgrounds. Most Cocoa APIs have been marked as unavailable, but import AppKit does cause the image to actually end up being loaded so it only takes a little bit of work to be able to use them:]]></summary></entry></feed>