-
Notifications
You must be signed in to change notification settings - Fork 757
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
sclang: fix hang on floating point arguments to Integer:forBy #3804
sclang: fix hang on floating point arguments to Integer:forBy #3804
Conversation
Previously Integer:forBy would truncate floating point arguments, to integers, which could potentially result in an infinite loop by the Integer:forBy optimized special operation. This modification checks for any of the arguments to be floating point, and if detecting that casts all of the arguments to floating point. It also adds appropriate testing coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! something i just realized -- there's still an infinite loop if you set the step to float or int 0. i think it's reasonable to guard against such cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this @lnihlen ! Sorry it took awhile to get attention on it. Comments below, just style points
lang/LangSource/PyrInterpreter3.cpp
Outdated
dispatch_opcode; | ||
} | ||
case 8 : { | ||
PyrSlot * vars = g->frame->vars; | ||
if ((slotRawInt(&vars[2]) >= 0 && slotRawInt(&vars[4]) <= slotRawInt(&vars[1])) | ||
|| (slotRawInt(&vars[2]) < 0 && slotRawInt(&vars[4]) >= slotRawInt(&vars[1]))) { | ||
bool continue_for_by = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the codebase isn't super consistent but I'd say we generally prefer camelCase naming for local variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lang/LangSource/PyrInterpreter3.cpp
Outdated
error("Integer-forBy : endval or stepval not an Integer.\n"); | ||
// If any argument is floating point we cast all arguments | ||
// to floating point, including the accumulator. This avoids | ||
// potential infinite loops due to integer truncation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
testsuite/sclang/TestInteger.sc
Outdated
@@ -0,0 +1,29 @@ | |||
TestInteger : UnitTest { | |||
test_forby_with_positive_integer_arguments { | |||
var forby_arguments = List.new; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and in sclang code we definitely prefer camelCase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
testsuite/sclang/TestInteger.sc
Outdated
@@ -0,0 +1,29 @@ | |||
TestInteger : UnitTest { | |||
test_forby_with_positive_integer_arguments { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not 100% standardized yet, but I've got a WIP document for the project test suite here. The naming convention I'm trying to adopt is test_methodName_inputConditions[_expectedResult]
, so following that this test should be named something like test_forBy_positiveIntegerArguments
. Also, you can omit the messages if you want, it's nice to have but IMO they're not super helpful beyond the names of the test functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks for the pointer to the guide.
Also responds to style feedback.
Thanks for the feedback. I added error detection for the case of the zero stepval. There's still a possibility of infinite loop by underflow but with 64-bit doubles this seems less troublesome. |
Oh, on the testing - I looked but didn't see any way to assert in testing that a particular operation results in a language error. Something like |
Thanks for that!
We have an open PR for this actually - #3808 . If you don't mind waiting a few days, it should be merged soon and then we rebase this PR and use it! |
In the interest of expedience would it be reasonable for me to accept an open issue to add test coverage for the two failure cases (non-numeric arguments and zero stepval), with the agreement that I would put that up for review once #3808 is in? |
I mean, and then merge this PR in the meantime? |
Not sure. In general our workflow has been to make things like this blocking, which I think helps to cut down on bookkeeping (and because people sometimes forget or fail to follow through on promises). But you've been staying on top of this one and it already has decent tests so let's give it a try. :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved as discussed :)
21.forBy(14.5, -3.125, { | i, j | forByArguments.add([i, j]); }); | ||
this.assertEquals(forByArguments, List[[21.0, 0], [17.875, 1], [14.75, 2]]); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An unfortunate bug that hasn't been addressed - the IDE doesn't append a newline to the end of the final line of a document, so most files edited with it will appear to be missing a final newline in git. I looked into it a couple months ago but didn't really come up with anything, and ended up moving on to other issues. Something to keep in mind for the future
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! looks good
Thanks for the review. In general my inclination is to decouple PRs as much as possible, to avoid possible propagation of delay through the PR dependency chain. Very hand-wavy, and I can't come up with a more concrete reason, so I appreciate the accommodation. |
Regarding #2690.
Previously Integer:forBy would truncate floating point arguments, to integers,
which could potentially result in an infinite loop by the Integer:forBy
optimized special operation. This modification checks for any of the arguments
to be floating point, and if detecting that casts all of the arguments to
floating point. It also adds appropriate testing coverage.