An open API service indexing awesome lists of open source software.

https://github.com/jubnzv/tolk-less

Tolk less – fix the math! TON compiler fuzzer
https://github.com/jubnzv/tolk-less

compiler-fuzzer emi fuzzing smt tolk ton z3

Last synced: 2 days ago
JSON representation

Tolk less – fix the math! TON compiler fuzzer

Awesome Lists containing this project

README

          

# tolk-less
tolk-less is a [Tolk](https://docs.ton.org/blockchain-basics/tolk/overview) compiler fuzzer. It demonstrates a zero-effort way to find nasty math bugs in the compiler.

* **Key idea:** sound EMI mutations + bitwise diff of TVM outputs across Tolk/FunC × optimized/non-optimized builds
* **Target:** arithmetic miscompilations
* **Effort:** <1 hour to vibecode a 1k-loc script, 2 hours to execute and review
* **Result:** 13 semantic drifts in arithmetic, 6 ICEs

## Usage
Clone with submodules, build `./third-party/ton` and execute:

```
SEED=0 MKL=10 MKH=20 N=195000 MD=4 MK=3 Z3=1 ABORT=0 ZINP=1 ZIT=500
python3 tl.py
```

## Findings

> ⚠️ **Note**: No Tolk contracts on mainnet, no [bug bounty coverage](https://github.com/ton-blockchain/bug-bounty). Nothing exploitable.

Commit: [4539cfab](https://github.com/ton-blockchain/ton/commit/4539cfabf2877e09d13032861f36c1490d13a941)

### Miscompiles

- [assert-K-eq-flipped](findings/assert-K-eq-flipped/README.md) — `assert(K != 0)` always throws, `assert(K == 0)` always passes
- [bitwise-noop-keeps-denorm](findings/bitwise-noop-keeps-denorm/README.md) — `K | 0` / `K & -1` preserve a BigInt denorm and re-arm the const-shift bug family
- [cancel-from-both-sides](findings/cancel-from-both-sides/README.md) — `K > (K - a)` rewritten to `K > -a`
- [const-shift-eq-broken](findings/const-shift-eq-broken/README.md) — `(K + 0) == K` folds to false
- [drop-const-from-add](findings/drop-const-from-add/README.md) — `a + K` silently drops K, body becomes empty
- [if-K-eq-0](findings/if-K-eq-0/README.md) — `if (K == 0) { throw }` always throws even when K is non-zero
- [muldiv-zeroed](findings/muldiv-zeroed/README.md) — `mulDivFloor/Ceil/Round(K, a, b)` folds to 0
- [neg-K-vs-K-cmp](findings/neg-K-vs-K-cmp/README.md) — `(-K) < K` folds to wrong constant
- [pushnegpow2-zero](findings/pushnegpow2-zero/README.md) — Tolk emits invalid `0 PUSHNEGPOW2` bytecode
- [repeat-skipped](findings/repeat-skipped/README.md) — `repeat (K) { body }` body silently elided
- [ternary-inverted](findings/ternary-inverted/README.md) — `(K != 0) ? a : b` picks the wrong branch
- [throwarg-bigimm](findings/throwarg-bigimm/README.md) — Tolk emits ` THROWARG`, Fift assembler rejects
- [while-skipped](findings/while-skipped/README.md) — `while (K != 0 && cond) { body }` body silently dropped

### ICE

- [tolk-bool-and-chain](findings/tolk-bool-and-chain/README.md) — `true && true && true && true && expr` crashes Tolk (`tolk.h:892`)
- [tolk-codegen-208](findings/tolk-codegen-208/README.md) — nested `!((true||false) != true)` shape crashes Tolk (`codegen.cpp:208`)
- [tolk-codegen-578](findings/tolk-codegen-578/README.md) — duplicated `false ? K : a` ternary + `(0<<3)>>3` shape crashes Tolk (`codegen.cpp:578`)
- [func-stack-validate](findings/func-stack-validate/README.md) — `a + ((a + (-1 ? 0 : 1)) * 0)` crashes FunC (`func.h:1622`)
- [func-codegen-168](findings/func-codegen-168/README.md) — `(a + (0 ? c : a*0)) * 0` crashes FunC (`codegen.cpp:168`)

## Further work
If you are serious about spending time on this, look at:

1. **Better oracles:** anything is better than the FunC oracle, some *sane* alternatives:
* hand-written concrete interpreter
* translation validation TVM/Fift→SMT for equivalence checks
2. **Program generation** beyond constants and arithmetic
3. **EMI synthesis:** start from the [Souper](https://github.com/google/souper) [paper](https://arxiv.org/pdf/1711.04422) and [this work](https://arxiv.org/pdf/2206.07086)