<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://pschanely.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://pschanely.github.io/" rel="alternate" type="text/html" /><updated>2024-11-19T05:16:10+00:00</updated><id>https://pschanely.github.io/feed.xml</id><title type="html">Phillip Schanely</title><entry><title type="html">Handling Nondeterminism in CrossHair</title><link href="https://pschanely.github.io/2022/05/17/handling-nondeterminism.html" rel="alternate" type="text/html" title="Handling Nondeterminism in CrossHair" /><published>2022-05-17T00:00:00+00:00</published><updated>2022-05-17T00:00:00+00:00</updated><id>https://pschanely.github.io/2022/05/17/handling-nondeterminism</id><content type="html" xml:base="https://pschanely.github.io/2022/05/17/handling-nondeterminism.html"><![CDATA[<p>CrossHair v0.0.23 was released today with an important new capability for
dealing with nondeterministic behavior.
Let’s get into it.</p>

<h2 id="handling-nondeterminism">Handling Nondeterminism</h2>

<p>CrossHair will fail or even yield a incorrect result if you run it on
nondeterministic code.</p>

<p>Here are some common things that cause nondeterminism:</p>
<ul>
  <li>Code that uses the current time, e.g. <code class="language-plaintext highlighter-rouge">time.time()</code>.</li>
  <li>Code that uses random numbers, e.g. <code class="language-plaintext highlighter-rouge">random.randint(...)</code></li>
  <li>Code that uses a cache, e.g. <code class="language-plaintext highlighter-rouge">functools.lru_cache(...)</code></li>
  <li>Code that reads data from the disk or network.</li>
</ul>

<p>As you might imagine, it’s very common to use functions like these.
Now, with the work that <a href="https://github.com/lmontand">Loïc Montandon</a> just integrated,
we have ways to check properties even when nondeterministic behavior exists.</p>

<p>By identifing the core functions that contain the nondeterminism, we can
now tell CrossHair to skip them and instead allow the function to return any value.</p>

<p>One can also apply contracts to these functions to constrain the parameters and
return value.</p>

<p>What’s more, this capability is part of the plugin system, so you can create this kind of
behavior for 3rd party modules in a reusable &amp; shareable fashion.</p>

<p>You can read more about this capability in the updated
<a href="https://crosshair.readthedocs.io/en/latest/plugins.html#adding-contracts-to-external-functions">plugins docs</a>!</p>

<h2 id="whats-up-next">What’s Up Next?</h2>

<ul>
  <li>I’m going to do a pass through the standard library and patch the most common sources
of nondeterminism (<code class="language-plaintext highlighter-rouge">time.time</code>, <code class="language-plaintext highlighter-rouge">random</code>, etc) using Loïc’s work.
You can follow that effort
<a href="https://github.com/pschanely/CrossHair/issues/162">in this issue</a>.</li>
  <li>Separately, I’m making some progress refactoring hypothesis to
better support the CrossHair integration.
Importantly, this will give us access to a large number of
properties to test CrossHair.
And perhaps start a bug trophy list!
You can follow this effort
<a href="https://github.com/HypothesisWorks/hypothesis/issues/3086">here</a>.</li>
</ul>

<p>As always, thanks for taking some time to share this journey with me. - Phil</p>]]></content><author><name></name></author><summary type="html"><![CDATA[CrossHair v0.0.23 was released today with an important new capability for dealing with nondeterministic behavior. Let’s get into it.]]></summary></entry><entry><title type="html">Simple length estimation for variable-width fonts</title><link href="https://pschanely.github.io/2022/04/11/relative-per-character-widths.html" rel="alternate" type="text/html" title="Simple length estimation for variable-width fonts" /><published>2022-04-11T00:00:00+00:00</published><updated>2022-04-11T00:00:00+00:00</updated><id>https://pschanely.github.io/2022/04/11/relative-per-character-widths</id><content type="html" xml:base="https://pschanely.github.io/2022/04/11/relative-per-character-widths.html"><![CDATA[<p>This post is much more mundane than
<a href="https://github.com/pschanely/CrossHair">CrossHair</a>!
But handy, I think.</p>

<p>It’s hard to compute the width of text in a font
because the character “i” is likely much more narrow
than the character “m”.</p>

<p>If you just want an estimate, you can count characters.</p>

<p>But can we get a better estimate without needing to know the
font details?</p>

<p>Recently, I wanted to attempt per-character estimates, and wrote
<a href="https://gist.github.com/pschanely/7df86fdc4150141487d1615a0398b562">a quick script</a>
. Here they are!:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{" ": 0.328, "!": 0.381, "\"": 0.475, "#": 0.655, "$": 0.655, "%": 1.069,
"&amp;": 0.9, "'": 0.347, "(": 0.414, ")": 0.414, "*": 0.555, "+": 0.713,
",": 0.328, "-": 0.414, ".": 0.328, "/": 0.346, "0": 0.655, "1": 0.655,
"2": 0.655, "3": 0.655, "4": 0.655, "5": 0.655, "6": 0.655, "7": 0.655,
"8": 0.655, "9": 0.655, ":": 0.346, ";": 0.346, "&lt;": 0.713, "=": 0.713,
"&gt;": 0.713, "?": 0.619, "@": 1.201, "A": 0.864, "B": 0.829, "C": 0.862,
"D": 0.897, "E": 0.793, "F": 0.724, "G": 0.931, "H": 0.897, "I": 0.381,
"J": 0.55, "K": 0.864, "L": 0.726, "M": 1.071, "N": 0.897, "O": 0.931,
"P": 0.758, "Q": 0.931, "R": 0.862, "S": 0.758, "T": 0.759, "U": 0.897,
"V": 0.864, "W": 1.173, "X": 0.864, "Y": 0.864, "Z": 0.759, "[": 0.381,
"\\": 0.346, "]": 0.381, "^": 0.583, "_": 0.655, "`": 0.347, "a": 0.619,
"b": 0.655, "c": 0.585, "d": 0.655, "e": 0.619, "f": 0.381, "g": 0.655,
"h": 0.655, "i": 0.312, "j": 0.312, "k": 0.621, "l": 0.312, "m": 1.0,
"n": 0.655, "o": 0.655, "p": 0.655, "q": 0.655, "r": 0.414, "s": 0.55,
"t": 0.346, "u": 0.655, "v": 0.621, "w": 0.897, "x": 0.621, "y": 0.621,
"z": 0.585, "{": 0.509, "|": 0.285, "}": 0.509, "~": 0.698}
</code></pre></div></div>

<p>Each value in this JSON map is a width, relative to the width of a
lowercase “m” character.
(e.g. the width of the “i” character is 0.312 times the
width of the “m” character)</p>

<p>This data is limited to printable ASCII characters. (the
.afm files I found don’t have information for unicode, sadly)
But if you find it useful, feel free to use it in your project.</p>

<h2 id="the-details">The Details</h2>

<p>I easily found some metrics for a few fonts: “Helvetica”, and “Times New Roman”.
I computed a relative-width map for each, and averaged them to produce the
above map. Hopfully combining a serif and sans-sarif font gives us some diversity.</p>

<p>This approach ignores a lot of details that matter, like letter spacing, word
spacing, and ligatures.</p>

<h2 id="how-much-better-is-it">How much better is it?</h2>

<p>Digging up metrics for a third font, “Arial”, I computed the average per-character
error compared to that font.</p>

<p>The estimate from the map above will be <strong>6% different</strong> than the
actual width, on average.</p>

<p>On the other hand, if you use a constant character width, your estimate will be
<strong>17% different</strong> than the actual width.</p>

<p>Using the map is clearly an improvment, but it’s also no substitute for working
with the real font you’re using.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[This post is much more mundane than CrossHair! But handy, I think.]]></summary></entry><entry><title type="html">CrossHair string support, semver, and formal methods</title><link href="https://pschanely.github.io/2022/04/01/complete-string-support.html" rel="alternate" type="text/html" title="CrossHair string support, semver, and formal methods" /><published>2022-04-01T00:00:00+00:00</published><updated>2022-04-01T00:00:00+00:00</updated><id>https://pschanely.github.io/2022/04/01/complete-string-support</id><content type="html" xml:base="https://pschanely.github.io/2022/04/01/complete-string-support.html"><![CDATA[<p>Hello friends. This is another bucket-of-updates kind of newsletter.</p>

<p>I’m hoping to write some more in-depth content soon (things like using CrossHair in practice, what CrossHair v1.0 looks like, a comparison with fuzzing). Let me know what you want to hear about too!</p>

<h2 id="string-support-complete">String support complete</h2>

<p>Since v0.0.20, CrossHair has complete string support! CrossHair can reason about every single string method and every single regular expression feature (albeit with varying effectiveness).</p>

<p>Be sure to let me know how it goes if you try it out.</p>

<h2 id="contractual-semver">Contractual SemVer</h2>

<p><a href="https://semver.org/">SemVer</a> is frequently criticized on the basis that every code change has the potential to break <strong>someone</strong>. We are then challenged to describe what “backwards-compatible” really means.</p>

<p>What if we used contracts to define “backwards-compatible?”</p>

<p>I’ve proposed a variant of SemVer, <a href="https://github.com/pschanely/contractual-semver">Contractual SemVer</a>, to explore that idea.</p>

<p>CrossHair can help library authors and consumers using Contractual SemVer, too. <a href="https://crosshair.readthedocs.io/en/latest/case_studies.html#contractual-semver">See this example</a>.</p>

<h2 id="formal-methods-and-crosshair">Formal Methods and CrossHair</h2>

<p>At present, CrossHair is “bug finder” and not a	verification tool: in particular, your code can easily have bugs that CrossHair does not discover. See <a href="https://github.com/pschanely/CrossHair/discussions/156">this discussion</a> for details.</p>

<p>However, <a href="https://github.com/lmontand">Loïc Montandon</a> is actively pushing CrossHair in the verification-tool direction. As a result of his work, CrossHair will:</p>

<ol>
  <li>More accurately describe when CrossHair’s symbolic exploration has been exhaustive.</li>
  <li>Produce an exhaustive result	in more	situations.</li>
</ol>

<p>I am really exicted about this work. Stay tuned for the details.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Hello friends. This is another bucket-of-updates kind of newsletter.]]></summary></entry><entry><title type="html">CrossHair unicode and more</title><link href="https://pschanely.github.io/2021/10/13/crosshair-unicode-and-more.html" rel="alternate" type="text/html" title="CrossHair unicode and more" /><published>2021-10-13T00:00:00+00:00</published><updated>2021-10-13T00:00:00+00:00</updated><id>https://pschanely.github.io/2021/10/13/crosshair-unicode-and-more</id><content type="html" xml:base="https://pschanely.github.io/2021/10/13/crosshair-unicode-and-more.html"><![CDATA[<p>Plenty of things to talk about in this update. I’ll get right to it.</p>

<h2 id="full-unicode-support">Full Unicode Support</h2>

<p>In version 0.0.18, CrossHair can generate counterexample strings in full unicode.
Until now, unicode support was probably the most glaring omission in CrossHair’s
capability list.</p>

<p>It also has expanded symbolic support for regexes and various string methods.
(<a href="https://crosshair.readthedocs.io/en/latest/changelog.html#version-0-0-18">full release notes</a>)</p>

<h2 id="deal-support">Deal Support</h2>

<p>CrossHair can now check contracts written in
<a href="https://deal.readthedocs.io/">deal</a>!
Check out
<a href="file:///Users/pschanely/proj/CrossHair/doc/build/kinds_of_contracts.html#analysis-kind-deal">the details here</a>.</p>

<p>One neat thing about deal in particular: it encourages you to tag side-effects of your
functions.
CrossHair uses some of these tags to avoid unintended side effects while checking
contracts.</p>

<h2 id="europython-talk---released">EuroPython Talk - Released!</h2>

<p>All of the EuroPython recordings
<a href="https://www.youtube.com/playlist?list=PL8uoeex94UhFuRtXhkqOrROsdNI6ejuiq">have been released</a>!</p>

<p>I shared a talk about contracts, and you can skip ahead to my
<a href="https://youtu.be/ynRdJR5UQWY?t=1428">CrossHair section</a> if you like.</p>

<p>One of the neat things about this section of the talk is that I get into some of the
<a href="/2021/07/30/contracts-propogate-expectations.html">design consequences of developing with contracts specifically</a>
(as opposed to related strategies like fuzzing and property-based testing, which 
can also be CrossHair-facilitated).</p>

<h2 id="hacktoberfest">Hacktoberfest</h2>

<p>CrossHair has
<a href="https://github.com/pschanely/CrossHair/issues?q=is%3Aissue+is%3Aopen+label%3AHacktoberfest">a few open issues</a>
marked for
<a href="https://hacktoberfest.digitalocean.com/">Hacktoberfest</a>.</p>

<p>That said, one of the biggest ways to help CrossHair is to:</p>
<ol>
  <li>Try using CrossHair while out while you work on <strong>other</strong> Hacktoberfest projects!</li>
  <li>Find CrossHair bugs. File issues.</li>
  <li>File a pull request against CrossHair with failing unit test(s) 
(with @pytest.mark.skip).</li>
  <li>Watch me joyously merge them and get your PR count even higher.</li>
</ol>

<h2 id="the-feels">The Feels</h2>

<p>Watching Python take the leader position this month in the
<a href="https://www.tiobe.com/tiobe-index/">TIOBE index</a>, I am filled with optimism.
Python, the language, has some properties that are particularly suited to 
the strengths of SMT solvers. (arbitrary size integers, for one)</p>

<p>We just need to wield that strength.</p>

<p>Let’s get to work.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Plenty of things to talk about in this update. I’ll get right to it.]]></summary></entry><entry><title type="html">An early Hypothesis-CrossHair integration</title><link href="https://pschanely.github.io/2021/08/25/hypothesis-crosshair-integration.html" rel="alternate" type="text/html" title="An early Hypothesis-CrossHair integration" /><published>2021-08-25T00:00:00+00:00</published><updated>2021-08-25T00:00:00+00:00</updated><id>https://pschanely.github.io/2021/08/25/hypothesis-crosshair-integration</id><content type="html" xml:base="https://pschanely.github.io/2021/08/25/hypothesis-crosshair-integration.html"><![CDATA[<p><strong>TLDR</strong>: As of today,
<a href="https://crosshair.readthedocs.io/en/latest/kinds_of_contracts.html#hypothesis-support">CrossHair
can check</a>
Hypothesis tests. (but it’s bad at it right now!)</p>

<p><strong>Preliminary Concepts:</strong></p>

<ul>
  <li><a href="https://hypothesis.readthedocs.io/">Hypothesis</a> - Write property-based tests in Python</li>
  <li><a href="https://github.com/pschanely/CrossHair">CrossHair</a> - Check Python contracts with concolic testing</li>
  <li><a href="https://en.wikipedia.org/wiki/Design_by_contract">design by contract</a> - Describe your functions with preconditions and postconditions</li>
  <li><a href="https://en.wikipedia.org/wiki/Property_testing">property-based testing</a> - Test properties of your code, not just examples</li>
  <li><a href="https://en.wikipedia.org/wiki/Concolic_testing">concolic testing</a> - Test concrete execution paths with symbolic inputs</li>
  <li><a href="https://en.wikipedia.org/wiki/Satisfiability_modulo_theories">SMT solvers</a> - Find values that satisfy constraints</li>
</ul>

<h2 id="the-story">The Story</h2>

<p>I
<a href="/2021/07/30/contracts-propogate-expectations.html">recently mentioned</a>
that property-based testing and contracts are similar.</p>

<p>This similarity has prompted a variety of great thought and discussions about whether
CrossHair’s concolic execution engine could be applied to Hypothesis, including
<a href="https://github.com/pschanely/CrossHair/issues/45">this longstanding github issue</a>.</p>

<p>The idea of applying both fuzzing and symbolic approaches to the same set of
specifications isn’t new, though these tend to be bleeding-edge projects
(proptest in Rust can be <a href="https://hypofuzz.com/docs/literature.html#rust-proptest-propfuzz-propverify">both fuzzed and sometimes verified</a>)!</p>

<p>Late last year, 
<a href="https://zhd.dev/">Zac Hatfield-Dodds</a>
and I brainstormed about this and
<a href="https://gist.github.com/Zac-HD/28a81c7fc9c73637eba4b2f675bb3b5a#write-for-hypothesis-run-with-crosshair">dug into the challenges</a>.
This year,
<a href="https://github.com/JinghanCode">Matthew Law</a>
experimented with a
<a href="https://github.com/JinghanCode/Crosshair-Hypothesis/pull/1">hypothesis-strategy-introspection</a>
approach, which I’ll touch on below.
And today, I’ve released a comprehensive-but-slow proof of concept (mostly in commits
<a href="https://github.com/pschanely/CrossHair/commit/fd259dc99d2a544f48b83c8ca3647fd39866d2b8">1</a>,
<a href="https://github.com/pschanely/CrossHair/commit/687b791514d489f9d171aaebd17483a1691a0c59">2</a>, and
<a href="https://github.com/pschanely/CrossHair/commit/2bd3b29ef4bb1e303ef47b9f9775c44bfb8064c2">3</a>).</p>

<h2 id="show-it-to-me">Show it to me!</h2>

<p>Sometimes, Hypothesis doesn’t pick the right inputs for your test; an example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from hypothesis import given
import hypothesis.strategies as st

def round_to_millions(number):
    return ((number + 500_000) // 1_000_000) * 1_000_000

@given(st.integers())
def test_round(number):
    difference = abs(number - round_to_millions(number))
    assert difference &lt; 500_000  # &lt;- This should be "&lt;=", not "&lt;"
</code></pre></div></div>

<p>Hypothesis doesn’t readily guess that it needs to try an number like 500_000 to make
this test fail.</p>

<p>But now you can run CrossHair on the same test file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ crosshair watch --analysis_kind=hypothesis test_rounding.py
</code></pre></div></div>

<p>And, after almost 3 minutes(!), it’ll find a counterexample:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>I found an exception while running your function.
test_rounding.py:12:
|@given(st.integers())
|def test_round(number):
&gt;    assert abs(number - round_to_millions(number)) &lt; 500_000

AssertionError: 
when calling test_round(number = -500000)
</code></pre></div></div>

<p>Three minutes seems like a long time for a constraint solver to find this input!</p>

<p>In fact, CrossHair’s
<a href="https://crosshair-web.org/?crosshair=0.1&amp;python=3.8&amp;gist=633aa35fe921e85e310bc431330a4781">contract-based version of the same problem</a>
can be solved in seconds. What gives?</p>

<p>CrossHair is symbolically executing all of the hypothesis code which generates function
inputs.
That code is pretty sophisticated - it’s essentially parsing values out of a byte
sequence.
So CrossHair needs to do a lot of work before it even gets to the body of the test.</p>

<p>Some datatypes are harder to generate than others;
for example, CrossHair cannot analyze Hypothesis string inputs in any reasonable
timeframe.</p>

<h2 id="whats-next">What’s Next?</h2>

<p>Matthew’s work above can help us detect some common cases when we don’t need to run the
hypothesis input generation code.
I think this makes a lot of sense in cases where this doesn’t add too much complexity
to CrossHair or dependencies on Hypothesis internals - I’m hoping to incorporate at
least some of this work soon.</p>

<p>A more ambitious arc is to introduce a new “mid-level” representation into Hypothesis
itself!
We’d add a layer above the byte string that can generate a fixed set of richer types:
ints, strings, and floats.</p>

<p>The mid-level would have bi-directional transformations with the byte string format.
Then, CrossHair can start at the mid-level representation;
this lets us more directly apply a lot of the type-specific reasoning that SMT solvers
are known for.</p>

<p>Zac
<a href="https://gist.github.com/Zac-HD/28a81c7fc9c73637eba4b2f675bb3b5a#mir-design-notes">has some ideas</a>
about how this mid-level representation could be added to Hypothesis.
If you’re interested in helping to bring more effective symbolic reasoning to
Hypothesis, we’d love your help - don’t hesitate to reach out!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[TLDR: As of today, CrossHair can check Hypothesis tests. (but it’s bad at it right now!)]]></summary></entry><entry><title type="html">Contracts Propagate Requirements</title><link href="https://pschanely.github.io/2021/07/30/contracts-propogate-expectations.html" rel="alternate" type="text/html" title="Contracts Propagate Requirements" /><published>2021-07-30T00:00:00+00:00</published><updated>2021-07-30T00:00:00+00:00</updated><id>https://pschanely.github.io/2021/07/30/contracts-propogate-expectations</id><content type="html" xml:base="https://pschanely.github.io/2021/07/30/contracts-propogate-expectations.html"><![CDATA[<p><a href="https://en.wikipedia.org/wiki/Design_by_contract">Contracts</a> and
<a href="https://increment.com/testing/in-praise-of-property-based-testing/">property-based testing</a>
have a lot of overlap: they both can be used to check arbitrary behaviors of your code.
But contracts <strong>propagate</strong>, and that has big implications.</p>

<p>I was very happy to share a
<a href="https://ep2021.europython.eu/talks/5UJcSrs-automatic-testing-of-python-functions-based-on-contracts/">EuroPython talk</a>
with
<a href="https://github.com/mristin">Marko Ristin-Kaufmann</a>
and
<a href="https://www.linkedin.com/in/lauren-de-bruyn">Lauren De bruyn</a> today.
We introduced the concept of code contracts and two tools that can be used to check contracts,
<a href="https://github.com/mristin/icontract-hypothesis">icontract-hypothesis</a>
and
<a href="https://github.com/pschanely/CrossHair">CrossHair</a>.</p>

<p>One obvious difference between contracts and property-based tests:
only contracts can be run in staging/production.</p>

<p>But I emphasized another important difference:</p>

<blockquote>
  <p>Unlike proprety-based tests, contract requirements <strong>propagate</strong> through your codebase.</p>
</blockquote>

<p>I’ll explain with the example I used in my talk.
Imagine we’re building an online shopping site, and need a function to compute the total
price for an order:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class LineItem:
    item_id: str
    quantity: int

def compute_total(items: List[LineItem], prices: Dict[str, float]) -&gt; float:
    total = 0.0
    for item in items:
        total += prices[item.item_id] * item.quantity
    return total
</code></pre></div></div>

<p>One might imagine that we want every order total to be greater than zero.
It’s easy enough to make a postcondition for that (in the 
<a href="">icontract</a>
syntax):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@ensure(lambda result: result &gt; 0)
def compute_total(items: List[LineItem], prices: Dict[str, float]) -&gt; float:
    ...
</code></pre></div></div>

<p><a href="">CrossHair</a>
quickly points out <strong>several</strong> ways to break this postcondition.</p>

<p>We might dutifully handle each of these cases. There are 4 of them!:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># There is at least one item:
@require(lambda items: len(items) &gt; 0)

# Each quantity is at least one:
@require(lambda items: all(i.quantity &gt; 0 for i in items))

# Every item has a price:
@require(lambda items, prices: all(i.item_id in prices for i in items))

# Every price is greater than zero:
@require(lambda prices: all(p &gt; 0 for p in prices.values()))
</code></pre></div></div>

<p>After we add all these preconditions, CrossHair is satisfied.</p>

<p>This is an awful lot of work, and we didn’t find a single bug in our function.
Was it worth it?</p>

<p>If this were a property-based test, probably not.</p>

<p>But as a contract, these new preconditions propagate to callers.
And, via more contracts, to the callers of callers.
This kind of propagation is very similar to what happens when you change a type:
the change ripples throughout the system, causing you to notice all the other
places that need to be changed.</p>

<p>Zooming out to a wider scale, each of the preconditions imply requirements for
other parts of the system. Let’s look at each of these preconditions again, this
time while “zoomed out”:</p>

<p> </p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@require(lambda items: len(items) &gt; 0)
</code></pre></div></div>
<p>You cannot check out if your cart is empty!</p>

<p> </p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@require(lambda items: all(i.quantity &gt; 0 for i in items))
</code></pre></div></div>
<p>Setting a quantity to zero should remove the entire line item!</p>

<p> </p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@require(lambda items, prices: all(i.item_id in prices for i in items))
</code></pre></div></div>
<p>You can’t add something to a cart that doesn’t have a price!</p>

<p> </p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@require(lambda prices: all(p &gt; 0 for p in prices.values()))
</code></pre></div></div>
<p>When parsing prices from a feed or table, verify the prices are nonzero!</p>

<p> </p>

<p>All of these requirements are important and could be easy to forget.
Contracts, along with tooling like icontract-hypothesis and CrossHair,
help us <strong>discover</strong> them.</p>

<p>Sometimes, we don’t want to propagate requirements, and that’s fine too.
This comes back to a point that Marko made today - all these testing
approaches (unit tests, property-based tests, contract) are <strong>complementary</strong>.</p>

<p>UPDATE 2021-10-12: The talk recording has been released!
You can jump to the CrossHair part
<a href="https://youtu.be/ynRdJR5UQWY?t=1428">here</a>!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Contracts and property-based testing have a lot of overlap: they both can be used to check arbitrary behaviors of your code. But contracts propagate, and that has big implications.]]></summary></entry><entry><title type="html">A little about how CrossHair works: Part 1</title><link href="https://pschanely.github.io/2020/02/04/how-crosshair-works-part-1.html" rel="alternate" type="text/html" title="A little about how CrossHair works: Part 1" /><published>2020-02-04T00:00:00+00:00</published><updated>2020-02-04T00:00:00+00:00</updated><id>https://pschanely.github.io/2020/02/04/how-crosshair-works-part-1</id><content type="html" xml:base="https://pschanely.github.io/2020/02/04/how-crosshair-works-part-1.html"><![CDATA[<p><a href="https://github.com/pschanely/CrossHair">CrossHair</a> is an ambitous project,
and a lot of it seems pretty magical. It’s less magical than you might
think, and Python does a lot of the heavy lifting for us.</p>

<p>This is <strong>part one</strong> in hopefully a series of posts about how CrossHair works.</p>

<p>I recommend the following reading as well, depending on your familiarity
with other work in this space.</p>

<ul>
  <li>
    <p>First, I can’t recommend <a href="https://www.fuzzingbook.org/">the fuzzing book</a>
enough. CrossHair’s approach largely corresponds to the chapter on
<a href="https://www.fuzzingbook.org/html/ConcolicFuzzer.html">Concolic Fuzzing</a>.
Some parts of the
<a href="https://www.fuzzingbook.org/html/SymbolicFuzzer.html">Symbolic Fuzzing</a>
chapter are relevant as well.
Unlike concolic execution, CrossHair’s values start each path execution as
purely symbolic values, and do not get concrete values until they are needed.</p>
  </li>
  <li>
    <p>CrossHair uses the Z3 SMT solver to perform its deductions.
<a href="https://www.cs.tau.ac.il/~msagiv/courses/asv/z3py/guide-examples.htm">This Python-specific introduction</a>
is a good place to get a feel for what it does. Please note that I’ll say “Z3”
below, but many statements about Z3 apply to all SMT solvers and/or the SMT-LIB
language.</p>
  </li>
</ul>

<h2 id="the-basic-idea">The Basic Idea</h2>

<p>CrossHair just
repeatedly calls the function you want to analyze and passes in special objects
that behave like things your function expects.</p>

<p>CrossHair doesn’t do any kind of AST or bytecode analysis. It just calls your
function.</p>

<p>These “special objects” behave differently on each execution. That’s how
CrossHair explores different paths through your function.</p>

<p>These special CrossHair objects hold one or more Z3 expressions which are used
in the Z3 solver. Here are some examples:</p>

<table>
  <thead>
    <tr>
      <th>When your function takes a parameter with this python type,</th>
      <th>we supply an object of this CrossHair type,</th>
      <th>which holds an expression with this Z3 sort:</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">int</code></td>
      <td><code class="language-plaintext highlighter-rouge">SmtInt</code></td>
      <td><code class="language-plaintext highlighter-rouge">IntSort()</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">bool</code></td>
      <td><code class="language-plaintext highlighter-rouge">SmtBool</code></td>
      <td><code class="language-plaintext highlighter-rouge">BoolSort()</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">str</code></td>
      <td><code class="language-plaintext highlighter-rouge">SmtStr</code></td>
      <td><code class="language-plaintext highlighter-rouge">StringSort()</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">dict</code></td>
      <td><code class="language-plaintext highlighter-rouge">SmtDict</code></td>
      <td><code class="language-plaintext highlighter-rouge">ArraySort(K, V)</code> and <code class="language-plaintext highlighter-rouge">IntSort()</code> for the length</td>
    </tr>
  </tbody>
</table>

<h2 id="lets-explore">Let’s Explore</h2>

<p>We can initialize a CrossHair object by giving it a name:</p>
<pre>
&gt;&gt;&gt; crosshair_x = SmtInt('x')
</pre>
<p>We can access the <code class="language-plaintext highlighter-rouge">.var</code> attribute of any CrossHair object to get
the Z3 variable(s) that it holds:</p>
<pre>
&gt;&gt;&gt; crosshair_x.var
x
&gt;&gt;&gt; type(crosshair_x.var)
&lt;class 'Z3.Z3.ArithRef'&gt;
</pre>

<p>This takes the Z3 variable we just defined and adds one to it:</p>
<pre>
&gt;&gt;&gt; expr = crosshair_x.var + Z3.IntVal(1)
&gt;&gt;&gt; expr
x + 1
&gt;&gt;&gt; type(expr)
&lt;class 'Z3.Z3.ExprRef'&gt;
</pre>

<p>We can create CrossHair objects not only for fresh variables, but
also for Z3 expressions.
So, if we wanted to wrap <code class="language-plaintext highlighter-rouge">x + 1</code> back into a CrossHair object,
we’d write:</p>
<pre>
&gt;&gt;&gt; SmtInt(crosshair_x.var + Z3.IntVal(1))
</pre>

<p>The <code class="language-plaintext highlighter-rouge">SmtInt</code> class defines the <code class="language-plaintext highlighter-rouge">__add__</code> method so that you don’t
have to spell that out, though. You can just say <code class="language-plaintext highlighter-rouge">crosshair_x + 1</code>, and
<code class="language-plaintext highlighter-rouge">SmtInt</code> does the necessary unwrapping and re-wrapping:</p>

<pre>
&gt;&gt;&gt; type(crosshair_x + 1)
&lt;class 'crosshair.libimpl.builtinslib.SmtInt'&gt;
</pre>

<p><code class="language-plaintext highlighter-rouge">SmtInt</code> also defines the comparison methods so that they return symbolic
booleans:</p>

<pre>
&gt;&gt;&gt; type(crosshair_x &gt;= 0)
&lt;class 'crosshair.libimpl.builtinslib.SmtBool'&gt;
</pre>

<p>The symbolic boolean holds an equivalent Z3 expression:</p>
<pre>
&gt;&gt;&gt; (crosshair_x &gt;= 0).var
0 &lt;= x
</pre>

<p>So far, everything is symbolic. But eventually, the Python interpreter
needs a real value; consider:</p>
<pre>
&gt;&gt;&gt; if crosshair_x &gt; 0:
&gt;&gt;&gt;   print('bigger than zero')
</pre>

<p>Should this execute the print or not? When python executes the <code class="language-plaintext highlighter-rouge">if</code>
statement, it calls <code class="language-plaintext highlighter-rouge">__bool__</code> on the <code class="language-plaintext highlighter-rouge">SmtBool</code> object. This method
does something very special. It consults Z3:</p>
<ul>
  <li>If the Z3 boolean expression must be True (or False), just return
that value.</li>
  <li>Otherwise, decide it to be True or False randomly. Take that decision
and add it to the set of Z3 constraints for this execution path.
Return the (concrete) bool that we decided.</li>
</ul>

<p>CrossHair will remember what decisions it has made so that
it can make different decisions on future executions. Ultimately,
we’re looking for some target thing to happen: an exception to be
raised, or a postcondition to return False. When that happens,
we ask Z3 for a model and report it as a counterexample.</p>

<p>That’s the core of how CrossHair works.</p>

<h2 id="simple-right">Simple, right?</h2>

<p>Well, if there is an accomplishment about CrossHair, it’s that it
tries hard to get the details right. And there are <strong>a lot</strong> of
details.</p>

<p>Here are some of the topics I’m considering talking about next. Let me
know which ones interest you the most!</p>

<ul>
  <li>Balancing the amount of work done inside and outside the solver.</li>
  <li>Developing heuristics for effective path exploration.</li>
  <li>Dealing with the cases that Z3 cannot. (concrete/symbolic scaling)</li>
  <li>Interpreting logic that’s implemented in C.</li>
  <li>Reconciling semantic differences between Python and Z3.</li>
  <li>Dealing with mutable values.</li>
  <li>Dealing with potentially aliased mutable values (x is y).</li>
  <li>Creating symbolics for your custom classes.</li>
  <li>Reconciling error behavior (ValueErrors, TypeErrors).</li>
  <li>Implicitly converting types accurately.</li>
  <li>Managing evaluation order. (under-approximation and over-approximation tactics)</li>
  <li>Creating symbolics for base classes, or even for <code class="language-plaintext highlighter-rouge">object</code>.</li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[CrossHair is an ambitous project, and a lot of it seems pretty magical. It’s less magical than you might think, and Python does a lot of the heavy lifting for us.]]></summary></entry></feed>