Skip to content

Commit

Permalink
wip on fixing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thedavidmeister committed Aug 23, 2024
1 parent aff8b4a commit 2485a11
Show file tree
Hide file tree
Showing 19 changed files with 615 additions and 585 deletions.
2 changes: 1 addition & 1 deletion src/concrete/extern/RainterpreterReferenceExternNPE2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ bytes32 constant SUB_PARSER_LITERAL_REPEAT_KEYWORD_MASK =
uint256 constant SUB_PARSER_LITERAL_REPEAT_INDEX = 0;

/// @dev Thrown when the repeat literal parser is not a single digit.
error InvalidRepeatCount(uint256 value);
error InvalidRepeatCount();

/// @dev Number of opcode function pointers available to run at eval time.
uint256 constant OPCODE_FUNCTION_POINTERS_LENGTH = 1;
Expand Down
3 changes: 3 additions & 0 deletions src/error/ErrParse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,6 @@ error BadSubParserResult(bytes bytecode);

/// Thrown when there are more than 16 inputs or outputs for a given opcode.
error OpcodeIOOverflow(uint256 offset);

/// Thrown when an operand value is larger than the maximum allowed.
error OperandOverflow();
5 changes: 3 additions & 2 deletions src/generated/RainterpreterNPE2.pointers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
pragma solidity =0.8.25;

/// @dev Hash of the known bytecode.
bytes32 constant BYTECODE_HASH = bytes32(0xf8382556fc29d39e6e42d3c8a93f6004c731efce7e61a4bbb7eac4a772f05151);
bytes32 constant BYTECODE_HASH = bytes32(0xb2bb360cac3a5504625d94621550913d5024da27fc6dbb11140efcc425d9cf7b);

/// @dev The function pointers known to the interpreter for dynamic dispatch.
/// By setting these as a constant they can be inlined into the interpreter
/// and loaded at eval time for very low gas (~100) due to the compiler
/// optimising it to a single `codecopy` to build the in memory bytes array.
bytes constant OPCODE_FUNCTION_POINTERS = hex"06b407040746091209f90a0b0a1d0a400a820ad40ae50af60b980bd50c840d080d570e4d";
bytes constant OPCODE_FUNCTION_POINTERS =
hex"06b407040746091209f90a0b0a1d0a360a780aca0adb0aec0b8e0bcb0c7a0cfe0d4d0e43";
4 changes: 2 additions & 2 deletions src/generated/RainterpreterParserNPE2.pointers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
pragma solidity =0.8.25;

/// @dev Hash of the known bytecode.
bytes32 constant BYTECODE_HASH = bytes32(0x11aba6006d98ab79c4372ab4f0d673880a1efc51f9c1f901f06e706029c052d7);
bytes32 constant BYTECODE_HASH = bytes32(0x943577dab2a943ee58c82e161256096c3025f5cf14afee602f91a18a8d0dfdcc);

/// @dev The parse meta that is used to lookup word definitions.
/// The structure of the parse meta is:
Expand Down Expand Up @@ -38,7 +38,7 @@ uint8 constant PARSE_META_BUILD_DEPTH = 2;
/// These positional indexes all map to the same indexes looked up in the parse
/// meta.
bytes constant OPERAND_HANDLER_FUNCTION_POINTERS =
hex"13ef13ef13ef145414cd14cd14cd1454145413ef13ef13ef14cd14cd14cd14cd14cd14cd";
hex"13ef13ef13ef14b415ab15ab15ab14b414b413ef13ef13ef15ab15ab15ab15ab15ab15ab";

/// @dev Every two bytes is a function pointer for a literal parser.
/// Literal dispatches are determined by the first byte(s) of the literal
Expand Down
6 changes: 3 additions & 3 deletions src/generated/RainterpreterReferenceExternNPE2.pointers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
pragma solidity =0.8.25;

/// @dev Hash of the known bytecode.
bytes32 constant BYTECODE_HASH = bytes32(0x4247a5ea9bd8abcbe989b8ae09f2b9b29cafa521add389fc7b6f2b1ca3c49ecc);
bytes32 constant BYTECODE_HASH = bytes32(0xa6f1f65cad3f9e2d59cbe0234b3d684442e6152a23f7966772d1bc21270e4ccf);

/// @dev The hash of the meta that describes the contract.
bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0xadf71693c6ecf3fd560904bc46973d1b6e651440d15366673f9b3984749e7c16);
Expand Down Expand Up @@ -47,14 +47,14 @@ bytes constant SUB_PARSER_WORD_PARSERS = hex"0775079707a607b607c7";
/// @dev Every two bytes is a function pointer for an operand handler.
/// These positional indexes all map to the same indexes looked up in the parse
/// meta.
bytes constant OPERAND_HANDLER_FUNCTION_POINTERS = hex"0a270a6c0a270a270a27";
bytes constant OPERAND_HANDLER_FUNCTION_POINTERS = hex"0a370a7c0a370a370a37";

/// @dev Every two bytes is a function pointer for a literal parser.
/// Literal dispatches are determined by the first byte(s) of the literal
/// rather than a full word lookup, and are done with simple conditional
/// jumps as the possibilities are limited compared to the number of words we
/// have.
bytes constant LITERAL_PARSER_FUNCTION_POINTERS = hex"09f8";
bytes constant LITERAL_PARSER_FUNCTION_POINTERS = hex"0a06";

/// @dev The function pointers for the integrity check fns.
bytes constant INTEGRITY_FUNCTION_POINTERS = hex"08ad";
Expand Down
23 changes: 21 additions & 2 deletions src/lib/parse/LibParseOperand.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
UnclosedOperand,
OperandValuesOverflow,
UnexpectedOperand,
UnexpectedOperandValue
UnexpectedOperandValue,
OperandOverflow
} from "../../error/ErrParse.sol";
import {Operand} from "rain.interpreter.interface/interface/unstable/IInterpreterV4.sol";
import {LibParse} from "./LibParse.sol";
Expand Down Expand Up @@ -157,8 +158,11 @@ library LibParseOperand {
assembly ("memory-safe") {
operand := mload(add(values, 0x20))
}
(int256 signedCoefficient, int256 exponent) = LibDecimalFloat.unpack(operand);
(int256 signedCoefficient, int256 exponent) = LibDecimalFloat.unpack(Operand.unwrap(operand));
operand = Operand.wrap(LibDecimalFloat.toFixedDecimalLossless(signedCoefficient, exponent, 0));
if (Operand.unwrap(operand) > type(uint16).max) {
revert OperandOverflow();
}
} else if (values.length == 0) {
operand = Operand.wrap(0);
} else {
Expand All @@ -175,6 +179,9 @@ library LibParseOperand {
}
(int256 signedCoefficient, int256 exponent) = LibDecimalFloat.unpack(Operand.unwrap(operand));
operand = Operand.wrap(LibDecimalFloat.toFixedDecimalLossless(signedCoefficient, exponent, 0));
if (Operand.unwrap(operand) > type(uint16).max) {
revert OperandOverflow();
}
} else if (values.length == 0) {
revert ExpectedOperand();
} else {
Expand All @@ -198,6 +205,10 @@ library LibParseOperand {
(signedCoefficient, exponent) = LibDecimalFloat.unpack(b);
b = LibDecimalFloat.toFixedDecimalLossless(signedCoefficient, exponent, 0);

if (a > type(uint8).max || b > type(uint8).max) {
revert OperandOverflow();
}

operand = Operand.wrap(a | (b << 8));
} else if (values.length < 2) {
revert ExpectedOperand();
Expand Down Expand Up @@ -242,6 +253,10 @@ library LibParseOperand {
(signedCoefficient, exponent) = LibDecimalFloat.unpack(c);
c = LibDecimalFloat.toFixedDecimalLossless(signedCoefficient, exponent, 0);

if (a > type(uint8).max || b > 1 || c > 1) {
revert OperandOverflow();
}

operand = Operand.wrap(a | (b << 8) | (c << 9));
} else if (length == 0) {
revert ExpectedOperand();
Expand Down Expand Up @@ -279,6 +294,10 @@ library LibParseOperand {
(signedCoefficient, exponent) = LibDecimalFloat.unpack(b);
b = LibDecimalFloat.toFixedDecimalLossless(signedCoefficient, exponent, 0);

if (a > 1 || b > 1) {
revert OperandOverflow();
}

operand = Operand.wrap(a | (b << 1));
} else {
revert UnexpectedOperandValue();
Expand Down
3 changes: 2 additions & 1 deletion test/src/lib/op/bitwise/LibOpShiftBitsLeftNP.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreter
import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol";
import {UnsupportedBitwiseShiftAmount} from "src/error/ErrBitwise.sol";
import {LibOperand} from "test/lib/operand/LibOperand.sol";
import {OperandOverflow} from "src/error/ErrParse.sol";

contract LibOpShiftBitsLeftNPTest is OpTest {
/// Directly test the integrity logic of LibOpShiftBitsLeftNP. Tests the
Expand Down Expand Up @@ -143,7 +144,7 @@ contract LibOpShiftBitsLeftNPTest is OpTest {
);
// Lets go ahead and overflow the operand.
checkUnhappyParse(
"_: bitwise-shift-left<65536>(0);", abi.encodeWithSelector(IntegerOverflow.selector, 65536, 65535)
"_: bitwise-shift-left<65536>(0);", abi.encodeWithSelector(OperandOverflow.selector)
);
}
}
3 changes: 2 additions & 1 deletion test/src/lib/op/bitwise/LibOpShiftBitsRightNP.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreter
import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol";
import {UnsupportedBitwiseShiftAmount} from "src/error/ErrBitwise.sol";
import {LibOperand} from "test/lib/operand/LibOperand.sol";
import {OperandOverflow} from "src/error/ErrParse.sol";

contract LibOpShiftBitsRightNPTest is OpTest {
/// Directly test the integrity logic of LibOpShiftBitsRightNP. Tests the
Expand Down Expand Up @@ -142,7 +143,7 @@ contract LibOpShiftBitsRightNPTest is OpTest {
);
// Lets go ahead and overflow the operand.
checkUnhappyParse(
"_: bitwise-shift-right<65536>(0);", abi.encodeWithSelector(IntegerOverflow.selector, 65536, 65535)
"_: bitwise-shift-right<65536>(0);", abi.encodeWithSelector(OperandOverflow.selector)
);
}
}
2 changes: 1 addition & 1 deletion test/src/lib/op/evm/LibOpMaxUint256NP.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ contract LibOpMaxUint256NPTest is OpTest {
}

/// Test the eval of LibOpMaxUint256NP parsed from a string.
function testOpMaxUint256NPEval() external {
function testOpMaxUint256NPEval() external view {
checkHappy("_: uint256-max-value();", type(uint256).max, "");
}

Expand Down
41 changes: 21 additions & 20 deletions test/src/lib/parse/LibParse.operand8M1M1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {UnsupportedLiteralType} from "src/lib/parse/literal/LibParseLiteral.sol"
import {ParserOutOfBounds} from "src/lib/parse/LibParse.sol";
import {ExpectedOperand, UnclosedOperand} from "src/error/ErrParse.sol";
import {OperandTest} from "test/abstract/OperandTest.sol";
import {OperandOverflow} from "src/error/ErrParse.sol";

import {LibMetaFixture} from "test/lib/parse/LibMetaFixture.sol";

Expand All @@ -24,7 +25,7 @@ contract LibParseOperand8M1M1Test is OperandTest {
checkOperandParse("_:e<255>();", hex"061000ff");

// Above uint8 max will overflow.
checkParseError("_:e<256>();", abi.encodeWithSelector(IntegerOverflow.selector, 256, 255));
checkParseError("_:e<256>();", abi.encodeWithSelector(OperandOverflow.selector));
}

/// Single value and one bit can be provided, other bit will default to zero.
Expand All @@ -37,10 +38,10 @@ contract LibParseOperand8M1M1Test is OperandTest {
checkOperandParse("_:e<255 1>();", hex"061001ff");

// Non binary bit will overflow.
checkParseError("_:e<1 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<1 3>();", abi.encodeWithSelector(IntegerOverflow.selector, 3, 1));
checkParseError("_:e<2 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<255 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<1 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<1 3>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<2 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<255 2>();", abi.encodeWithSelector(OperandOverflow.selector));
}

/// Single value and two bits can be provided.
Expand All @@ -59,21 +60,21 @@ contract LibParseOperand8M1M1Test is OperandTest {
checkOperandParse("_:e<255 1 1>();", hex"061003ff");

// Non binary bit will overflow.
checkParseError("_:e<1 0 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<1 1 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<1 2 0>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<1 2 1>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<1 2 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<2 0 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<2 1 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<2 2 0>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<2 2 1>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<2 2 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<255 0 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<255 1 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<255 2 0>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<255 2 1>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<255 2 2>();", abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
checkParseError("_:e<1 0 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<1 1 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<1 2 0>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<1 2 1>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<1 2 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<2 0 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<2 1 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<2 2 0>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<2 2 1>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<2 2 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<255 0 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<255 1 2>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<255 2 0>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<255 2 1>();", abi.encodeWithSelector(OperandOverflow.selector));
checkParseError("_:e<255 2 2>();", abi.encodeWithSelector(OperandOverflow.selector));
}

/// Unclosed operand is disallowed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {ExpectedOperand, UnclosedOperand, UnexpectedOperandValue} from "src/erro
import {LibParse} from "src/lib/parse/LibParse.sol";
import {LibMetaFixture} from "test/lib/parse/LibMetaFixture.sol";
import {ParseState} from "src/lib/parse/LibParseState.sol";
import {OperandOverflow} from "src/error/ErrParse.sol";

contract LibParseOperandDoublePerByteNoDefaultTest is Test {
using LibParse for ParseState;
Expand Down Expand Up @@ -152,15 +153,15 @@ contract LibParseOperandDoublePerByteNoDefaultTest is Test {

/// 2 literals are expected for this operand parser. Tests 256 256.
function testOperandDoublePerByteNoDefaultSecondOverflow() external {
vm.expectRevert(abi.encodeWithSelector(IntegerOverflow.selector, 256, 255));
vm.expectRevert(abi.encodeWithSelector(OperandOverflow.selector));
(bytes memory bytecode, uint256[] memory constants) = LibMetaFixture.newState("_:c<256 256>();").parse();
(bytecode);
(constants);
}

/// 2 literals are expected for this operand parser. Tests 256 255.
function testOperandDoublePerByteNoDefaultSecondOverflowFirst() external {
vm.expectRevert(abi.encodeWithSelector(IntegerOverflow.selector, 256, 255));
vm.expectRevert(abi.encodeWithSelector(OperandOverflow.selector));
(bytes memory bytecode, uint256[] memory constants) = LibMetaFixture.newState("_:c<256 255>();").parse();
(bytecode);
(constants);
Expand Down
5 changes: 3 additions & 2 deletions test/src/lib/parse/LibParse.operandM1M1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {ParserOutOfBounds, LibParse, ExpectedLeftParen} from "src/lib/parse/LibP
import {OperandTest} from "test/abstract/OperandTest.sol";
import {LibMetaFixture} from "test/lib/parse/LibMetaFixture.sol";
import {ParseState} from "src/lib/parse/LibParseState.sol";
import {OperandOverflow} from "src/error/ErrParse.sol";

contract LibParseOperandM1M1Test is OperandTest {
using LibParse for ParseState;
Expand Down Expand Up @@ -81,7 +82,7 @@ contract LibParseOperandM1M1Test is OperandTest {

/// Default is zero for this operand parser. Tests first overflow.
function testOperandM1M1FirstOverflow() external {
vm.expectRevert(abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
vm.expectRevert(abi.encodeWithSelector(OperandOverflow.selector));
(bytes memory bytecode, uint256[] memory constants) = LibMetaFixture.newState("_:d<2>();").parse();
(bytecode);
(constants);
Expand Down Expand Up @@ -135,7 +136,7 @@ contract LibParseOperandM1M1Test is OperandTest {

/// Default is zero for this operand parser. Tests 0 2.
function testOperandM1M1SecondOverflow() external {
vm.expectRevert(abi.encodeWithSelector(IntegerOverflow.selector, 2, 1));
vm.expectRevert(abi.encodeWithSelector(OperandOverflow.selector));
(bytes memory bytecode, uint256[] memory constants) = LibMetaFixture.newState("_:d<0 2>();").parse();
(bytecode);
(constants);
Expand Down
5 changes: 3 additions & 2 deletions test/src/lib/parse/LibParse.operandSingleFull.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {ExpectedOperand, UnclosedOperand, UnexpectedOperandValue} from "src/erro
import {LibParse, ExpectedLeftParen} from "src/lib/parse/LibParse.sol";
import {LibMetaFixture} from "test/lib/parse/LibMetaFixture.sol";
import {ParseState} from "src/lib/parse/LibParseState.sol";
import {OperandOverflow} from "src/error/ErrParse.sol";

contract LibParseOperandSingleFullTest is Test {
using LibParse for ParseState;
Expand Down Expand Up @@ -204,15 +205,15 @@ contract LibParseOperandSingleFullTest is Test {

/// Overflowing decimal uint16 max as single full operand reverts.
function testOperandSingleFullUint16MaxOverflow() external {
vm.expectRevert(abi.encodeWithSelector(IntegerOverflow.selector, 65536, 65535));
vm.expectRevert(abi.encodeWithSelector(OperandOverflow.selector));
(bytes memory bytecode, uint256[] memory constants) = LibMetaFixture.newState("_:b<65536>();").parse();
(bytecode);
(constants);
}

/// Overflowing hexadecimal uint16 max as a single full operand reverts.
function testOperandSingleFullHexUint16MaxOverflow() external {
vm.expectRevert(abi.encodeWithSelector(IntegerOverflow.selector, 65536, 65535));
vm.expectRevert(abi.encodeWithSelector(OperandOverflow.selector));
(bytes memory bytecode, uint256[] memory constants) = LibMetaFixture.newState("_:b<0x010000>();").parse();
(bytecode);
(constants);
Expand Down
Loading

0 comments on commit 2485a11

Please sign in to comment.