I was analyzing a contract in Oyente. The contract is :
pragma solidity ^0.4.21;
contract Test{
address admin;
function Test() public{
admin = msg.sender;
}
string str = "";
function setStr(string _str) public{
str = _str;
}
function getStr() public view returns (string){
return str;
}
}
When I passed this contract to oyente to analyze then the following report came:
INFO:root:contract Test.sol:Test: INFO:symExec: ============ Results =========== INFO:symExec: EVM Code Coverage: 24.1% INFO:symExec: Integer Underflow: True INFO:symExec: Integer Overflow: True INFO:symExec: Parity Multisig Bug 2: False INFO:symExec: Callstack Depth Attack Vulnerability: False INFO:symExec: Transaction-Ordering Dependence (TOD): False INFO:symExec: Timestamp Dependency: False INFO:symExec: Re-Entrancy Vulnerability: False INFO:symExec:Test.sol:16:9: Warning: Integer Underflow. return str Integer Underflow occurs if: return str = 1 INFO:symExec:Test.sol:11:5: Warning: Integer Overflow. function setStr(string _str) public{ ^ Spanning multiple lines. Integer Overflow occurs if: _str = 115792089237316195423570985008687907853269984665640564039457584007913129639932 INFO:symExec: ====== Analysis Completed ======
It shows Integer overflow and underflow in a string variable. I really don't understand how it could happen or how to solve it. Any help will be appreciated.
That's a false positive result.
Value of the string
type is stored as a byte array, not as an integer. If you convert the specified integers into byte array, and then try to return them as string
, the value is not readable.
Example:
function getStr2() public view returns (string) {
bytes memory byteArray = abi.encode(115792089237316195423570985008687907853269984665640564039457584007913129639932);
return string(byteArray);
}
Fails in Remix IDE (uses JS VM emulator and ethers.js) with error:
Failed to decode output: null: invalid codepoint at offset 0; bad codepoint prefix (argument="bytes", value=Uint8Array(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc), code=INVALID_ARGUMENT, version=strings/5.5.0)
Which signalizes that the "string" contains some UTF-8 bytes but doesn't start with the UTF-8 BOM.
Same goes for the value 1
.
Solidity strings span across multiple slots (each slot has 32 bytes), where the first slot contains the string length.
So if they set the str
value to 0x01
, this suggests the array should have a length of 1. And then - depending on their emulator and the tool implementation, it:
0x0000000000000000000000000000000000000000000000000000000000000000
(32 empty bytes), which is still not the expected value 0x01
.