// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8; /* runner.json { "differential": true, "actions": [ { "Upload": { "code": { "Solidity": { "contract": "UlongRem" } } } }, { "Instantiate": { "code": { "Solidity": { "contract": "UlongRemTester" } } } }, { "VerifyCall": { "success": true } } ] } */ /// Exercises the stdlib `__ulongrem` Knuth-D helper via mulmod's slow path /// (modulus >= 2^128). Inputs come over calldata to defeat solc folding. contract UlongRem { function bigMulMod(uint256 a, uint256 b, uint256 m) external pure returns (uint256) { return mulmod(a, b, m); } } contract UlongRemTester { constructor() { UlongRem c = new UlongRem(); // PoC from the bug report. Drives the second-iteration trial-quotient // candidate to exactly 2^128 - 1, the boundary the off-by-one loop bound // in `__ulongrem` mishandled. Failure mode (pre-fix): PVM returns // `correct + m`. uint256 a = 1 << 159; uint256 b = type(uint256).max - (1 << 54); uint256 m = (1 << 255) + 1; uint256 r = c.bigMulMod(a, b, m); assert(r < m); } }