| 1 | While considering methods for further obfuscating Whitespace code, I realized |
| 2 | that the Whitespace language reference didn't enforce any particular alignment |
| 3 | or grouping for code execution. In theory this means one could create a |
| 4 | sequence of Whitespace trits which represents different sequences of commands |
| 5 | depending on exactly where execution begins. |
| 6 | |
| 7 | One implementation of this idea is the creation of a 'hidden' label. For |
| 8 | example, the command sequence |
| 9 | |
| 10 | PUSH 0; DROP; PUSH 46 |
| 11 | |
| 12 | assembles as |
| 13 | |
| 14 | SSSSN SNN SSSTSTTTSN |
| 15 | |
| 16 | which can be visually regrouped as |
| 17 | |
| 18 | SSSSNSN NSSSTSTTTSN |
| 19 | |
| 20 | and contains the `MARK label0` command (i.e. `NSSSTSTTTSN`) used in the next |
| 21 | set of examples. |
| 22 | |
| 23 | Additionally, since `PUSH 0; DROP` is effectively a `NOP`, 'hijacking' the code |
| 24 | at this location allows one to insert their own integer on the stack in place |
| 25 | of the `PUSH 46` command, sneakily substituting it as an input to any |
| 26 | downstream processing. |
| 27 | |
| 28 | I decided to investigate the behavior of specific Whitespace interpreters, |
| 29 | discovering that they broke down into two methods for locating labels. |
| 30 | |
| 31 | * **Method 1** Scan from the start of the file for the first occurence of the |
| 32 | mark-label bytestring and jump. |
| 33 | |
| 34 | Examples: |
| 35 | |
| 36 | whitespacers/c: (c) meth0dz |
| 37 | |
| 38 | * **Method 2** Scan from the start of the file, looking for a mark-label |
| 39 | bytestring, but 'parsing' one bytestring at a time, and jumping to the |
| 40 | first 'standalone' mark-label bytestring. Note that this is different than |
| 41 | executing the program, particularly when user-input commands are present. |
| 42 | |
| 43 | Examples: |
| 44 | |
| 45 | whitespacers/haskell: (c) 2003 Edwin Brady |
| 46 | whitespacers/ruby: (c) 2003 by Wayne E. Conrad |
| 47 | whitespacers/perl: (c) 2003 Micheal Koelbl |
| 48 | threeifbywhiskey/satan |
| 49 | |
| 50 | Both of these methods can be broken using valid Whitespace code: |
| 51 | |
| 52 | * **Type A**: No 'standalone' label exists. This breaks Method 2. |
| 53 | |
| 54 | By programmer's intent, this should print a `!` before infinite `.` lines. |
| 55 | |
| 56 | * **Type B**: Hidden label before 'standalone' label. This breaks Method 1. |
| 57 | |
| 58 | By programmer's intent, this should print an infinite chain of `.` lines. |
| 59 | |
| 60 | This is the Type A program: |
| 61 | |
| 62 | SSSTSSSSTN | Push +33 (ASCII '!') |
| 63 | NSNSTSTTTSN | JMP > 0101110 (label0) |
| 64 | NSSTTTTN | MARK: 1111 (label2) |
| 65 | SSSSN | PUSH 0 |
| 66 | SNN | DROP |
| 67 | SSSTSTTTSN | Push +46 (ASCII '.') |
| 68 | TNSS | Output character |
| 69 | SSSTSTSN | Push +10 (ASCII '\n') |
| 70 | TNSS | Output character |
| 71 | NSNTTTTN | JMP > 1111 (label2) |
| 72 | |
| 73 | Append this to turn it into the Type B program: |
| 74 | |
| 75 | NSSSTSTTTSN | MARK: 0101110 (label0) (2nd time) |
| 76 | NSNTTTTN | JMP > 1111 (label2) |
| 77 | |
| 78 | VVhitespace avoids this ambiguity by marking label definitions with a vertical |
| 79 | tab `[VTab]` immediately before the label. |
| 80 | |
| 81 | Old label: NSS TSTS N |
| 82 | New label: NSSV TSTS N |
| 83 | |
| 84 | Since Whitespace ignores [VTab] as a comment character, and since the |
| 85 | Whitespace VM is a superset of the VVhitespace VM, all valid VVhitespace |
| 86 | programs are also valid Whitespace programs, though the task of locating a |
| 87 | suitable Whitespace interpreter is left for the reader. |
| 88 | |
| 89 | -------------------------------------------------------------------------------- |
| 90 | |
| 91 | Quoting from the original Whitespace tutorial which I used as language reference: |
| 92 | |
| 93 | The programmer is free to push arbitrary width integers onto the stack. |
| 94 | |
| 95 | I have yet to find a Whitespace interpreter which successfully implements that |
| 96 | statement. |
| 97 | |
| 98 | Since I wanted to implement bitwise logic functions, this broad definition |
| 99 | posed a problem. For example, how many `1`s should be in the output of the |
| 100 | expression `NOT(0)`? Should the expression `NOT(0) == NOT(0)` always be true? |
| 101 | |
| 102 | VVhitespace sidesteps the problem by declaring all integers to be 64-bits wide. |
| 103 | |