Remove hint.html and index.html

As per discussions on GitHub the index.html and hint.html files should
be deleted in favour of README.md files (from any
.text/.txt/.markdown/.md files which will be turned into README.md in an
upcoming commit).
This commit is contained in:
Cody Boone Ferguson committed 2023-02-08 05:07:05 -08:00
1 parent ee8a36310f
commit 77fb0f11a2
143 files changed
-28606

No files matched your search

-326
View File
@@ -1,326 +0,0 @@
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
<html>
<head>
<meta name="GENERATOR" content="mkd2html 2.2.2">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css" />
<title></title>
<title>Best of show - abuse of libc</title>
</head>
<body>
<CENTER>
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
<div id="bar">
<ul>
<li><a href="../index.html">About the 27th IOCCC</a></li>
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
<li><a href="/index.html">IOCCC home</a></li>
<li><a href="/winners.html">List of All Winners</a></li>
<li><a href="/judges.html">The Judges</a></li>
</ul>
</div>
<P><FONT size="6"><B>A 27<sup>th</sup> IOCCC Winner</B></FONT></P>
</CENTER>
<h1>Best of show - abuse of libc</h1>
<p>Nicholas Carlini <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#110;&#105;&#99;&#104;&#111;&#108;&#97;&#115;&#64;&#99;&#97;&#114;&#108;&#105;&#110;&#105;&#46;&#99;&#111;&#109;">&#110;&#105;&#99;&#104;&#111;&#108;&#97;&#115;&#64;&#99;&#97;&#114;&#108;&#105;&#110;&#105;&#46;&#99;&#111;&#109;</a><br/>
<a href="https://nicholas.carlini.com">https://nicholas.carlini.com</a></p>
<p>The code for this entry can be found in <a href="prog.c">prog.c</a></p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
./prog
</code></pre>
<h3>Try:</h3>
<pre><code># Play with a friend, P1 and P2, squares are numbered 1..9
./prog
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>This program consists of a single print statement wrapped in a while loop. You
would not think that this would amount to much, but you would be very, very
wrong. A clue to what is happening and how this works is encoded in the
ASCII art of the program source.</p>
<h2>Author&rsquo;s comments:</h2>
<p>HOW ABOUT A NICE GAME OF <strike>CHESS</strike>TIC-TAC-TOE?</p>
<h3>USAGE</h3>
<pre><code>cc -o prog prog.c
./prog
</code></pre>
<p>Alternates between P1 and P2. Enter a digit [1-9] to move:</p>
<pre><code>1 | 2 | 3
---------
4 | 5 | 6
---------
7 | 8 | 9
</code></pre>
<p>The game ends if:</p>
<ul>
<li>A player completes three in a row; that player wins</li>
<li>All squares are taken; neither player wins</li>
<li>A player makes an illegal move; their opponent wins</li>
</ul>
<h3>LIMITATIONS</h3>
<p>Bad things may happen if the entered move is outside of the range [1..9]</p>
<p>While the game will stop if one player tries to overwrite another player&rsquo;s move,
it will happily allow a player to move on top of themself. However, given that
this is an effective no-op and guarantees a loss to a competent opponent, if you
do this you probably deserve to lose.</p>
<p>Your terminal may beep at you every turn. We&rsquo;ll call this a feature that &hellip;
the program &hellip; is hard at work processing your move! That is! Please be
patient.</p>
<p>After macro expansion the format string is roughly 100K. This makes some
compilers unhappy, and others slow. (For example, passing GCC the flags -Wall
-Wextra -pedantic will result in a warning about oversized strings.)</p>
<p>Under some terminals the program may exit early. The following should always work:</p>
<pre><code>echo "1 2 3 4 5 6 7" | ./prog
</code></pre>
<h3>OBFUSCATION</h3>
<p>The entirety of the program consists of a single iterated call to printf.</p>
<pre><code>int main() {
while(*d) printf(fmt, arg);
}
</code></pre>
<p>Here, <code>fmt</code> is a single string, and <code>arg</code> is a series of arguments to printf.</p>
<p>While its primary purpose is to serve as The One True Debugger, printf also happens
to be Turing complete. (See &ldquo;Control-Flow Bending: On the Effectiveness of Control-Flow
Integrity&rdquo; where we introduced this in an actual, published, academic paper. The
things you can get away with sometimes.)</p>
<p>We <strike>ab</strike>use this fact to implement the logic of tic-tac-toe entirely within
this one printf call (and a call to scanf() to read user input).</p>
<p>Here&rsquo;s (briefly) how it works.</p>
<h4>Preliminaries</h4>
<p>This program uses three printf format specifiers.
- <code>%d</code> takes an integer argument and prints it
- <code>%s</code> takes a string argument and prints it
- <code>%n</code> takes a pointer and writes (!!) the number of bytes printed so far.</p>
<p>Okay, everyone probably knows this. Let&rsquo;s get a bit more advanced.</p>
<p>Format specifiers can take extra &ldquo;arguments&rdquo;.
- <code>"%hhn"</code>: store the number of bytes written mod 256 to the char pointer
- <code>"%2$d"</code>: print argument 2 to printf (and not the sequentially next argument)
- <code>"%8d"</code>: pad the printed integer to 8 characters
- <code>"%3$.*4$d"</code>: print argument 3 to printf with as many zeros as in argument 4.</p>
<p>For example, the following expression</p>
<pre><code>printf("%1$.*2$d%3$hhn", 5, 10, &amp;x)
</code></pre>
<p>will have the same effect as if we had written</p>
<pre><code>x = 10;
</code></pre>
<p>because it will print out <code>0000000005</code> (5 padded to size 10) and then write the
number of bytes written to x.</p>
<h4>Printf Oriented Programming</h4>
<p>Alright, now we can get to the real fun.</p>
<p>We perform arbitrary computation with printf treating memory as a binary
array&mdash;one bit per pair of bytes:
- The zero bit is represented by the sequence <code>00 00</code>
- The one-bit is represented by the sequence <code>xx 00</code> where <code>xx</code> is any non-zero byte.</p>
<p>We can use format strings to compute the OR/NOT of arbitrary &ldquo;bits&rdquo;.</p>
<p>We&rsquo;ll start with the simplest, OR:</p>
<pre><code>printf("%1$s%2$s%3$hhn", a, b, c)
</code></pre>
<p>will compute</p>
<pre><code>*c = strlen(a) + strlen(b)
</code></pre>
<p>but given that <code>strlen(x)</code> is <code>1</code> for a 1-bit and <code>0</code> for a 0-bit, we have</p>
<pre><code>*c = a | b
</code></pre>
<p>Computing the NOT of a single value is also easy:</p>
<pre><code>printf("%1$255d%1$s%hhn", a, b)
</code></pre>
<p>will compute</p>
<pre><code>*b = (strlen(a)+255)%256 = strlen(a)-1
</code></pre>
<p>and again, because <code>strlen(x)</code> is either <code>1</code> or <code>0</code> we have</p>
<pre><code>*c = !b
</code></pre>
<p>From here we can compute any binary circuit. Doing something efficient,
though, still takes work.</p>
<h4>Tic-Tac-Toe</h4>
<p>The game itself is represented as a board of 18 bits, 9 bits per player, along
with a turn counter that alternates between player 1 and player 2.</p>
<p>To detect who has won, we implement the following logic. Let A, B, and C be
pointers to three squares in a row to test, and D be where to save if there is a
win or not.</p>
<pre><code>"%A$s%B$s%C$s%1$253d%11$hhn" // r11 = !(*A &amp; *B &amp; *C)
ZERO
"%11$s%1$255d%11hhn" // r11 = !r11
ZERO
"%11$s%D$s%D$hhn" // *D = *D | r11
</code></pre>
<p>That is, we set <code>*D</code> to <code>1</code> if there is a three-in-a-row. We repeat this for all
possible three-in-a-row configurations, for both players.</p>
<p>The ZERO macro ensures that the number of bytes written out is 0 mod 256 with
the following expression</p>
<pre><code>"%1$hhn%1$s" (repeated 256 times)
</code></pre>
<p>where argument 1 is a pointer to a temporary variable followed by a null byte.</p>
<p>This works because if the current count is 0 mod 256, then &ldquo;%1$hhn&rdquo; will write
zero to argument 1 and then &ldquo;%1$s&rdquo; will never emit any text. If, on the other
hand, the count is not 0 mod 256, a length-1 string will be written to argument
1, and then &ldquo;%1$s&rdquo; will increment the count by one. By repeating this 256
times we&rsquo;re eventually going to reach 0 mod 256.</p>
<p>Checking if there has been an invalid move is achieved similarly.</p>
<p>In order to decide what to print out, we have to cast the &ldquo;in-memory&rdquo; array of
bits to Xs and Os to print out. This is actually rather straightforward. Given
in 1$ the pointer to player 1&rsquo;s square, and 2$ the pointer to player 2&rsquo;s, and
in 3$ the pointer to the board string, we can compute</p>
<pre><code>"%1$s" (repeated 47 times) "%2$s" (repeated 56 times) %1$32d%3$hhn"
</code></pre>
<p>which will, in effect, compute</p>
<pre><code>*r3 = (*r1) * 47 + (*r2) * 56 + 32
</code></pre>
<p>which will output &lsquo; &rsquo; if neither are true, &lsquo;X&rsquo; if r1 is, or &lsquo;O&rsquo; if r2 is.</p>
<h4>Further Obfuscations</h4>
<p>In order to be able to finally display the board, while still only using one
printf statement, we finish the statement with</p>
<pre><code>"\n\033[2J\n%26$s"
</code></pre>
<p>which is the escape sequence to clear the screen, and then prints argument 26.
Argument 26 is a pointer to a char* in memory, that initially is undefined,
but within the printf statement we will construct this string to look like a
tic-tac-toe board.</p>
<p>After the board, we need to print one of the following strings:</p>
<pre><code>P1&gt;_
P2&gt;_
P1 WINS
P2 WINS
P1 TIES
P2 TIES
</code></pre>
<p>Depending on if it&rsquo;s P1 or P2&rsquo;s turn to move, the game is over and someone
won, or the game is over and it is a draw.</p>
<p>This turns out not to be as hard as it might look. Using the same trick as
before, we set byte four to be</p>
<pre><code>*byte4 = is_win * 'W' + is_tie * 'T'
</code></pre>
<p>The byte <code>'I'</code> and <code>'S'</code> can always be the same, and we do the same for <code>'E'</code>/<code>'N'</code>.</p>
<p>We do this same on-the-fly creation of the <code>scanf()</code> format string, but for a
different reason. We first want to run <code>printf()</code> to show the first board, and
then alternate between runs to <code>scanf()</code> and <code>printf()</code> reading and then
displaying moves. importantly, we <em>do not</em> want a final scanf when the game
ends. It should just exit.</p>
<p>One option would be to implement the logic as</p>
<pre><code>printf()
while (*ok) {
scanf();
printf();
}
</code></pre>
<p>but this would DOUBLE the number of calls to printf we require. So instead we
implement it like this</p>
<pre><code>while (*ok) {
scanf();
printf();
}
</code></pre>
<p>(In reality we actually pass <code>scanf()</code> as an argument to avoid the extra
statement, but it has the same effect.)</p>
<p>Notice there is now no initial <code>printf()</code>. In order make sure the program doesn&rsquo;t
block before the first <code>printf()</code>, but we initialize the <code>scanf()</code> format to the null
string so that it returns right away without blocking. The first time the <code>printf()</code>
call runs, it writes out &ldquo;%hhd&rdquo; to create the <code>scanf()</code> format string.</p>
<BR>
<HR>
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2020,
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
- All rights reserved<BR>
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>