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

Fix negative denominator in boost::rational during exponentiation. #5348

Merged
merged 1 commit into from
Nov 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions libsolidity/ast/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,10 +1144,10 @@ TypePointer RationalNumberType::binaryOperatorResult(Token _operator, TypePointe
bigint denominator = optimizedPow(m_value.denominator(), absExp);

if (exp >= 0)
value = rational(numerator, denominator);
value = makeRational(numerator, denominator);
else
// invert
value = rational(denominator, numerator);
value = makeRational(denominator, numerator);
}
break;
}
Expand Down
9 changes: 9 additions & 0 deletions libsolidity/ast/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ using FunctionTypePointer = std::shared_ptr<FunctionType const>;
using TypePointers = std::vector<TypePointer>;
using rational = boost::rational<dev::bigint>;

inline rational makeRational(bigint const& _numerator, bigint const& _denominator)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this would be better suited in an anonymous namespace inside the cpp file or in a more central place inside libdevcore.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, I don't think so - in this header we introduce the rational alias and - if we want to stay compatible with the buggy boost version - we will always want to use makeRational, when we create a rational from a numerator and denominator, so I think it makes a lot of sense to have it right here below the using rational = ......

Copy link
Member Author

Choose a reason for hiding this comment

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

Or if we want to move it, I'd at least move the using rational = ... part as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

Cleanly moving using rational = ... to libdevcore would require changing it's namespace, though - which we could do, but which may have side-effects. So actually I think right here is not too bad of a place for this for now :-).

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok!

Copy link
Contributor

Choose a reason for hiding this comment

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

I think Types.h would need some cleanup at some point anyway....

{
solAssert(_denominator != 0, "division by zero");
// due to a bug in certain versions of boost the denominator has to be positive
if (_denominator < 0)
return rational(-_numerator, -_denominator);
else
return rational(_numerator, _denominator);
}

enum class DataLocation { Storage, CallData, Memory };

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
contract C {
function f() public pure returns (int) {
return (-1 / 2) ** -1;
}
}