Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking: overflow detection for SDIV - minInt / (-1) #1091

Closed
wants to merge 10 commits into from

Conversation

pirapira
Copy link
Member

Trying to fix #1087.

First I'm trying to catch this in the CI servers.

// Test for (minInt) / (-1)
if (c_isSigned && _operator == Token::Div)
{
m_context << Instruction::DUP1 << Instruction::NOT // ~x
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is faster, but you might want to use the new inline assembly here:

m_context.appendInlineAssembly(R"(
  and(
    eq(x, exp(2, 255)), // x == 2**256 (min int)
    iszero(not(y)) // y == -1
  )
)",
// names of variables already on the stack
{"y", "x"});
m_context.appendConditionalJumpTo(m_context.errorTag());

Oh by the way, in all other comments of the code generator, the stack grows to the right, I think yours grows to the left.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I'll change the stack growing direction.

@chriseth
Copy link
Contributor

Please don't miss my comment above.

pirapira added a commit to pirapira/solidity that referenced this pull request Sep 13, 2016
@pirapira
Copy link
Member Author

No, no, they arrive in my mailbox.

@pirapira pirapira force-pushed the minint_div_negone branch 2 times, most recently from b680363 to 5717205 Compare September 13, 2016 20:25
@pirapira
Copy link
Member Author

@chriseth The inline assembly caused an exception (possibly because the compiler tried to reduce every constant number, and hit the case?) So I reverted to the old fashioned EVM writing.

@pirapira
Copy link
Member Author

This is done on my side.

@pirapira pirapira changed the title [WIP] minInt / (-1) minInt / (-1) Sep 23, 2016
@chriseth chriseth changed the title minInt / (-1) Breaking: overflow detection for SDIV - minInt / (-1) Oct 4, 2016
Copy link
Contributor

@chriseth chriseth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add an entry into the changelog (not for the current version, this has to go into 0.5.0) and also add some documentation ("places where solidity throws").

Note that this PR is only one part of the general "throw on arithmetic overflow" task.

if (c_isSigned && _operator == Token::Div)
{
m_context << Instruction::DUP1 // x
<< u256(255) << u256(2) << Instruction::EXP // 2 ** 255
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use (u256(1) << 255), the optimizer knows how to represent that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the optimizer use EXP, PUSH32 directly, or a much better way? I will do an experiment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It tries various different ways to represent constants and compares the creation-time costs against the execution-time costs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK --optimize does the same thing as I do. I'll change this.

m_context << Instruction::AND;
m_context.appendConditionalJumpTo(m_context.errorTag());
}

if (_operator == Token::Div)
m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV);
else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there also a special case for smod?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SMOD specification is ambiguous. I created a separate issue about this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My conclusion is that SMOD has no overflows.

@pirapira
Copy link
Member Author

pirapira commented Oct 5, 2016

Mentioning #796 for cross-referencing.

pirapira added a commit to pirapira/solidity that referenced this pull request Oct 5, 2016
@pirapira
Copy link
Member Author

pirapira commented Oct 5, 2016

I've dealt with all comments.

@axic
Copy link
Member

axic commented Oct 6, 2016

Can we pull out the "When Solidity Throws" change into a separate PR and merge it?

@pirapira
Copy link
Member Author

pirapira commented Oct 6, 2016

@axic that's a good idea. I start the separation.

pirapira added a commit to pirapira/solidity that referenced this pull request Oct 6, 2016
@pirapira
Copy link
Member Author

pirapira commented Oct 6, 2016

@axic I separated #1167 and rebased this one on top of it.

pirapira added a commit to pirapira/solidity that referenced this pull request Oct 10, 2016
pirapira added a commit to pirapira/solidity that referenced this pull request Mar 10, 2017
@pirapira pirapira force-pushed the minint_div_negone branch from 34b9bff to 6dd48f5 Compare March 13, 2017 17:40
pirapira added a commit to pirapira/solidity that referenced this pull request Mar 13, 2017
@pirapira pirapira force-pushed the minint_div_negone branch from 6dd48f5 to 71cfe63 Compare March 14, 2017 11:32
@pirapira
Copy link
Member Author

Tests pass finally. I'll keep rebasing.

@pirapira pirapira force-pushed the minint_div_negone branch from 71cfe63 to 041fc84 Compare March 22, 2017 10:17
pirapira added a commit to pirapira/solidity that referenced this pull request Mar 22, 2017
@pirapira pirapira force-pushed the minint_div_negone branch from 041fc84 to 87b09e7 Compare April 11, 2017 13:46
pirapira added a commit to pirapira/solidity that referenced this pull request Apr 11, 2017
@pirapira pirapira force-pushed the minint_div_negone branch from 87b09e7 to 8a8b29b Compare April 21, 2017 10:14
pirapira added a commit to pirapira/solidity that referenced this pull request Apr 21, 2017
if (c_isSigned && _operator == Token::Div)
{
m_context.appendInlineAssembly(R"({
jumpi(invalidJumpLabel, and(eq(y, exp(2,255)), iszero(add(x, 1))))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The invalidJumpLabel is gone. This should use something like:

jumpi(safe, iszero(...))
invalid
safe:

Thought not sure if the labels must be unique?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll create something like

invalidLabel:
invalid

once somewhere.

It seems I can do something within 3 weeks.

@pirapira pirapira force-pushed the minint_div_negone branch from 8a8b29b to 2dfdfda Compare June 22, 2017 10:15
@chriseth
Copy link
Contributor

Overflow-detection at runtime is extremely complicated because of the various types we have. I propose to do only compile-time overflow checking and close this pull request.

@pirapira
Copy link
Member Author

@chriseth do you have less number of types at compilation time?

@chriseth
Copy link
Contributor

No, but it is not as complicated and the effects of getting something wrong are not as bad.

@pirapira
Copy link
Member Author

@chriseth really? I think runtime checks are vastly less complicated than compilation time checks.

@pirapira
Copy link
Member Author

@chriseth brought up a convincing argument that all different cases of the runtime overflow checks will not make it until the new intermediate language lands. So I'm closing this.

@pirapira pirapira closed this Jul 12, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Arithmetic overflow for sdiv
3 participants