bitcoin-spv - multiple integer under-/overflows
The bitcoin-spv library allows for multiple integer under-/overflows while processing or converting potentially untrusted or user-provided data.\\n`uint8` underflow `uint256(uint8(_e - 3))`\\nNote: `_header[75]` will throw consuming all gas if out of bounds while the majority of the library usually uses `slice(start, 1)` to handle this more gracefully.\\n```\\n/// @dev Target is a 256 bit number encoded as a 3-byte mantissa and 1 byte exponent\\n/// @param \\_header The header\\n/// @return The target threshold\\nfunction extractTarget(bytes memory \\_header) internal pure returns (uint256) {\\n    bytes memory \\_m = \\_header.slice(72, 3);\\n    uint8 \\_e = uint8(\\_header[75]);\\n    uint256 \\_mantissa = bytesToUint(reverseEndianness(\\_m));\\n    uint \\_exponent = \\_e - 3;\\n\\n    return \\_mantissa \\* (256 \\*\\* \\_exponent);\\n}\\n```\\n\\n`uint8` overflow `uint256(uint8(_len + 8 + 1))`\\nNote: might allow a specially crafted output to return an invalid determineOutputLength <= 9.\\nNote: while type `VarInt` is implemented for inputs, it is not for the output length.\\n```\\n/// @dev 5 types: WPKH, WSH, PKH, SH, and OP\\_RETURN\\n/// @param \\_output The output\\n/// @return The length indicated by the prefix, error if invalid length\\nfunction determineOutputLength(bytes memory \\_output) internal pure returns (uint256) {\\n    uint8 \\_len = uint8(\\_output.slice(8, 1)[0]);\\n    require(\\_len < 0xfd, "Multi-byte VarInts not supported");\\n\\n    return \\_len + 8 + 1; // 8 byte value, 1 byte for \\_len itself\\n}\\n```\\n\\n`uint8` underflow `uint256(uint8(extractOutputScriptLen(_output)[0]) - 2)`\\n```\\n/// @dev Determines type by the length prefix and validates format\\n/// @param \\_output The output\\n/// @return The hash committed to by the pk\\_script, or null for errors\\nfunction extractHash(bytes memory \\_output) internal pure returns (bytes memory) {\\n    if (uint8(\\_output.slice(9, 1)[0]) == 0) {\\n        uint256 \\_len = uint8(extractOutputScriptLen(\\_output)[0]) - 2;\\n        // Check for maliciously formatted witness outputs\\n        if (uint8(\\_output.slice(10, 1)[0]) != uint8(\\_len)) {\\n            return hex"";\\n        }\\n        return \\_output.slice(11, \\_len);\\n    } else {\\n        bytes32 \\_tag = \\_output.keccak256Slice(8, 3);\\n```\\n\\n`BytesLib` input validation multiple start+length overflow\\nNote: multiple occurrences. should check `start+length > start && bytes.length >= start+length`\\n```\\nfunction slice(bytes memory \\_bytes, uint \\_start, uint \\_length) internal  pure returns (bytes memory res) {\\n    require(\\_bytes.length >= (\\_start + \\_length), "Slice out of bounds");\\n```\\n\\n`BytesLib` input validation multiple start overflow\\n```\\nfunction toUint(bytes memory \\_bytes, uint \\_start) internal  pure returns (uint256) {\\n    require(\\_bytes.length >= (\\_start + 32), "Uint conversion out of bounds.");\\n```\\n\\n```\\nfunction toAddress(bytes memory \\_bytes, uint \\_start) internal  pure returns (address) {\\n    require(\\_bytes.length >= (\\_start + 20), "Address conversion out of bounds.");\\n```\\n\\n```\\nfunction slice(bytes memory \\_bytes, uint \\_start, uint \\_length) internal  pure returns (bytes memory res) {\\n    require(\\_bytes.length >= (\\_start + \\_length), "Slice out of bounds");\\n```\\n\\n```\\nfunction keccak256Slice(bytes memory \\_bytes, uint \\_start, uint \\_length) pure internal returns (bytes32 result) {\\n    require(\\_bytes.length >= (\\_start + \\_length), "Slice out of bounds");\\n```\\n
We believe that a general-purpose parsing and verification library for bitcoin payments should be very strict when processing untrusted user input. With strict we mean, that it should rigorously validate provided input data and only proceed with the processing of the data if it is within a safe-to-use range for the method to return valid results. Relying on the caller to provide pre-validate data can be unsafe especially if the caller assumes that proper input validation is performed by the library.\\nGiven the risk profile for this library, we recommend a conservative approach that balances security instead of gas efficiency without relying on certain calls or instructions to throw on invalid input.\\nFor this issue specifically, we recommend proper input validation and explicit type expansion where necessary to prevent values from wrapping or processing data for arguments that are not within a safe-to-use range.
```\\n/// @dev Target is a 256 bit number encoded as a 3-byte mantissa and 1 byte exponent\\n/// @param \\_header The header\\n/// @return The target threshold\\nfunction extractTarget(bytes memory \\_header) internal pure returns (uint256) {\\n    bytes memory \\_m = \\_header.slice(72, 3);\\n    uint8 \\_e = uint8(\\_header[75]);\\n    uint256 \\_mantissa = bytesToUint(reverseEndianness(\\_m));\\n    uint \\_exponent = \\_e - 3;\\n\\n    return \\_mantissa \\* (256 \\*\\* \\_exponent);\\n}\\n```\\n