mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
commit
4633f3def8
@ -8,7 +8,7 @@ include(EthPolicy)
|
||||
eth_policy()
|
||||
|
||||
# project name and version should be set after cmake_policy CMP0048
|
||||
set(PROJECT_VERSION "0.4.3")
|
||||
set(PROJECT_VERSION "0.4.4")
|
||||
project(solidity VERSION ${PROJECT_VERSION})
|
||||
|
||||
# Let's find our dependencies
|
||||
|
@ -1,3 +1,9 @@
|
||||
### 0.4.4 (2016-10-31)
|
||||
|
||||
Bugfixes:
|
||||
* Type checker: forbid signed exponential that led to an incorrect use of EXP opcode.
|
||||
* Code generator: properly clean higher order bytes before storing in storage.
|
||||
|
||||
### 0.4.3 (2016-10-25)
|
||||
|
||||
Features:
|
||||
|
@ -180,12 +180,12 @@ elseif (DEFINED MSVC)
|
||||
# Always use Release variant of C++ runtime.
|
||||
# We don't want to provide Debug variants of all dependencies. Some default
|
||||
# flags set by CMake must be tweaked.
|
||||
string(REPLACE "/MDd" "/MD" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
string(REPLACE "/D_DEBUG" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
string(REPLACE "/MDd" "/MD" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
|
||||
string(REPLACE "/D_DEBUG" "" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
|
||||
string(REPLACE "/RTC1" "" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
|
||||
string(REPLACE "/MDd" "/MD" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "/D_DEBUG" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "/MDd" "/MD" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
string(REPLACE "/D_DEBUG" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
string(REPLACE "/RTC1" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS OFF)
|
||||
|
||||
# disable empty object file warning
|
||||
|
@ -119,7 +119,7 @@ function(eth_use TARGET REQUIRED)
|
||||
endif()
|
||||
|
||||
foreach(MODULE ${ARGN})
|
||||
string(REPLACE "::" ";" MODULE_PARTS ${MODULE})
|
||||
string(REPLACE "::" ";" MODULE_PARTS "${MODULE}")
|
||||
list(GET MODULE_PARTS 0 MODULE_MAIN)
|
||||
list(LENGTH MODULE_PARTS MODULE_LENGTH)
|
||||
if (MODULE_LENGTH GREATER 1)
|
||||
|
@ -56,9 +56,9 @@ copyright = '2016, Ethereum'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.4.3'
|
||||
version = '0.4.4'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.4.3-develop'
|
||||
release = '0.4.4-develop'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -5,7 +5,7 @@ Solidity is a contract-oriented, high-level language whose syntax is similar to
|
||||
and it is designed to target the Ethereum Virtual Machine.
|
||||
|
||||
Solidity is statically typed, supports inheritance, libraries and complex
|
||||
user-defines types among other features.
|
||||
user-defined types among other features.
|
||||
|
||||
As you will see, it is possible to create contracts for voting,
|
||||
crowdfunding, blind auctions, multi-signature wallets and more.
|
||||
|
@ -12,7 +12,7 @@ Versioning
|
||||
Solidity versions follow `semantic versioning <https://semver.org>`_ and in addition to
|
||||
releases, **nightly development builds** are also made available. The nightly builds
|
||||
are not guaranteed to be working and despite best efforts they might contain undocumented
|
||||
and/or broken changes. We recommend to use the latest release. Package installers below
|
||||
and/or broken changes. We recommend using the latest release. Package installers below
|
||||
will use the latest release.
|
||||
|
||||
Browser-Solidity
|
||||
|
@ -330,9 +330,32 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
|
||||
if (nonStandard)
|
||||
return;
|
||||
|
||||
std::map<std::string, Instruction> const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD }, { "&", Instruction::AND }, { "|", Instruction::OR }, { "^", Instruction::XOR } };
|
||||
std::map<std::string, pair<Instruction, bool>> const c_binary = { { "<", { Instruction::LT, false } }, { "<=", { Instruction::GT, true } }, { ">", { Instruction::GT, false } }, { ">=", { Instruction::LT, true } }, { "S<", { Instruction::SLT, false } }, { "S<=", { Instruction::SGT, true } }, { "S>", { Instruction::SGT, false } }, { "S>=", { Instruction::SLT, true } }, { "=", { Instruction::EQ, false } }, { "!=", { Instruction::EQ, true } } };
|
||||
std::map<std::string, Instruction> const c_unary = { { "!", Instruction::ISZERO } };
|
||||
std::map<std::string, Instruction> const c_arith = {
|
||||
{ "+", Instruction::ADD },
|
||||
{ "-", Instruction::SUB },
|
||||
{ "*", Instruction::MUL },
|
||||
{ "/", Instruction::DIV },
|
||||
{ "%", Instruction::MOD },
|
||||
{ "&", Instruction::AND },
|
||||
{ "|", Instruction::OR },
|
||||
{ "^", Instruction::XOR }
|
||||
};
|
||||
std::map<std::string, pair<Instruction, bool>> const c_binary = {
|
||||
{ "<", { Instruction::LT, false } },
|
||||
{ "<=", { Instruction::GT, true } },
|
||||
{ ">", { Instruction::GT, false } },
|
||||
{ ">=", { Instruction::LT, true } },
|
||||
{ "S<", { Instruction::SLT, false } },
|
||||
{ "S<=", { Instruction::SGT, true } },
|
||||
{ "S>", { Instruction::SGT, false } },
|
||||
{ "S>=", { Instruction::SLT, true } },
|
||||
{ "=", { Instruction::EQ, false } },
|
||||
{ "!=", { Instruction::EQ, true } }
|
||||
};
|
||||
std::map<std::string, Instruction> const c_unary = {
|
||||
{ "!", Instruction::ISZERO },
|
||||
{ "~", Instruction::NOT }
|
||||
};
|
||||
|
||||
vector<CodeFragment> code;
|
||||
CompilerState ns = _s;
|
||||
@ -449,14 +472,15 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
|
||||
m_asm << end.tag();
|
||||
m_asm.donePaths();
|
||||
}
|
||||
else if (us == "WHILE")
|
||||
else if (us == "WHILE" || us == "UNTIL")
|
||||
{
|
||||
requireSize(2);
|
||||
requireDeposit(0, 1);
|
||||
|
||||
auto begin = m_asm.append();
|
||||
m_asm.append(code[0].m_asm);
|
||||
m_asm.append(Instruction::ISZERO);
|
||||
if (us == "WHILE")
|
||||
m_asm.append(Instruction::ISZERO);
|
||||
auto end = m_asm.appendJumpI();
|
||||
m_asm.append(code[1].m_asm, 0);
|
||||
m_asm.appendJump(begin);
|
||||
@ -541,17 +565,6 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
|
||||
// At end now.
|
||||
m_asm.append(end);
|
||||
}
|
||||
else if (us == "~")
|
||||
{
|
||||
requireSize(1);
|
||||
requireDeposit(0, 1);
|
||||
|
||||
m_asm.append(code[0].m_asm, 1);
|
||||
m_asm.append((u256)1);
|
||||
m_asm.append((u256)0);
|
||||
m_asm.append(Instruction::SUB);
|
||||
m_asm.append(Instruction::SUB);
|
||||
}
|
||||
else if (us == "SEQ")
|
||||
{
|
||||
unsigned ii = 0;
|
||||
@ -567,6 +580,10 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
|
||||
m_asm.append(i.m_asm);
|
||||
m_asm.popTo(1);
|
||||
}
|
||||
else if (us == "PANIC")
|
||||
{
|
||||
m_asm.appendJump(m_asm.errorTag());
|
||||
}
|
||||
else if (us.find_first_of("1234567890") != 0 && us.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNM1234567890_") == string::npos)
|
||||
m_asm.append((u256)varAddress(s));
|
||||
else
|
||||
|
@ -349,11 +349,14 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe
|
||||
return commonType;
|
||||
if (Token::isBooleanOp(_operator))
|
||||
return TypePointer();
|
||||
// Nothing else can be done with addresses
|
||||
if (auto intType = dynamic_pointer_cast<IntegerType const>(commonType))
|
||||
{
|
||||
// Nothing else can be done with addresses
|
||||
if (intType->isAddress())
|
||||
return TypePointer();
|
||||
// Signed EXP is not allowed
|
||||
if (Token::Exp == _operator && intType->isSigned())
|
||||
return TypePointer();
|
||||
}
|
||||
else if (auto fixType = dynamic_pointer_cast<FixedPointType const>(commonType))
|
||||
if (Token::Exp == _operator)
|
||||
|
@ -231,10 +231,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
|
||||
m_context
|
||||
<< (u256(0x1) << (256 - 8 * dynamic_cast<FixedBytesType const&>(*m_dataType).numBytes()))
|
||||
<< Instruction::SWAP1 << Instruction::DIV;
|
||||
else if (
|
||||
m_dataType->category() == Type::Category::Integer &&
|
||||
dynamic_cast<IntegerType const&>(*m_dataType).isSigned()
|
||||
)
|
||||
else
|
||||
// remove the higher order bits
|
||||
m_context
|
||||
<< (u256(1) << (8 * (32 - m_dataType->storageBytes())))
|
||||
@ -242,9 +239,6 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
|
||||
<< Instruction::DUP2
|
||||
<< Instruction::MUL
|
||||
<< Instruction::DIV;
|
||||
else if (m_dataType->category() == Type::Category::FixedPoint)
|
||||
// implementation should be very similar to the integer case.
|
||||
solAssert(false, "Not yet implemented - FixedPointType.");
|
||||
m_context << Instruction::MUL << Instruction::OR;
|
||||
// stack: value storage_ref updated_value
|
||||
m_context << Instruction::SWAP1 << Instruction::SSTORE;
|
||||
|
@ -41,6 +41,7 @@ void help()
|
||||
<< " -x,--hex Parse, compile and assemble; output byte code in hex." << endl
|
||||
<< " -a,--assembly Only parse and compile; show assembly." << endl
|
||||
<< " -t,--parse-tree Only parse; show parse tree." << endl
|
||||
<< " -o,--optimise Turn on/off the optimiser; off by default." << endl
|
||||
<< " -h,--help Show this help message and exit." << endl
|
||||
<< " -V,--version Show the version and exit." << endl;
|
||||
exit(0);
|
||||
@ -81,7 +82,7 @@ enum Mode { Binary, Hex, Assembly, ParseTree, Disassemble };
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
setDefaultOrCLocale();
|
||||
unsigned optimise = 1;
|
||||
unsigned optimise = 0;
|
||||
string infile;
|
||||
Mode mode = Hex;
|
||||
|
||||
@ -98,8 +99,8 @@ int main(int argc, char** argv)
|
||||
mode = Assembly;
|
||||
else if (arg == "-t" || arg == "--parse-tree")
|
||||
mode = ParseTree;
|
||||
else if ((arg == "-o" || arg == "--optimise") && argc > i + 1)
|
||||
optimise = atoi(argv[++i]);
|
||||
else if (arg == "-o" || arg == "--optimise")
|
||||
optimise = 1;
|
||||
else if (arg == "-d" || arg == "--disassemble")
|
||||
mode = Disassemble;
|
||||
else if (arg == "-V" || arg == "--version")
|
||||
|
@ -7533,6 +7533,26 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers)
|
||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(true));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(packed_storage_overflow)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
uint16 x = 0x1234;
|
||||
uint16 a = 0xffff;
|
||||
uint16 b;
|
||||
function f() returns (uint, uint, uint, uint) {
|
||||
a++;
|
||||
uint c = b;
|
||||
delete b;
|
||||
a -= 2;
|
||||
return (x, c, b, a);
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x1234), u256(0), u256(0), u256(0xfffe)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -2098,6 +2098,22 @@ BOOST_AUTO_TEST_CASE(integer_boolean_operators)
|
||||
BOOST_CHECK(expectError(sourceCode3) == Error::Type::TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(exp_signed_variable)
|
||||
{
|
||||
char const* sourceCode1 = R"(
|
||||
contract test { function() { uint x = 3; int y = -4; x ** y; } }
|
||||
)";
|
||||
BOOST_CHECK(expectError(sourceCode1) == Error::Type::TypeError);
|
||||
char const* sourceCode2 = R"(
|
||||
contract test { function() { uint x = 3; int y = -4; y ** x; } }
|
||||
)";
|
||||
BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError);
|
||||
char const* sourceCode3 = R"(
|
||||
contract test { function() { int x = -3; int y = -4; x ** y; } }
|
||||
)";
|
||||
BOOST_CHECK(expectError(sourceCode3) == Error::Type::TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(reference_compare_operators)
|
||||
{
|
||||
char const* sourceCode1 = R"(
|
||||
|
Loading…
Reference in New Issue
Block a user