-
-
Notifications
You must be signed in to change notification settings - Fork 668
Add Compile-Time Error-Checking and Avoid Boundschecking in Slice Expressions #4351
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
Conversation
src/expression.c
Outdated
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.
looks like
return decl && decl->ident->len == 8 && memcmp(decl->ident->string, "__dollar", decl->ident->len) == 0;to me
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.
You're right. I'll wait and see if any more logic has to be added :) If not I'll change it.
src/expression.c
Outdated
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.
decl->ident == Id::dollar?
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.
Ahh! Great.
src/expression.c
Outdated
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.
a = a || b -> a |= b
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.
No?
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.
Ahh, I get it. I misread -> for a pointer member operator :)
According to
https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Compound_assignment_operators
this does bitwise logic. But for zeros and ones I guess that's ok right?
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.
I would use if(lwrRange.imax <= uprRange.imin) this->lowerIsLessThanUpper = true; here.
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.
this does bitwise logic. But for zeros and ones I guess that's ok right?
Bitwise logic on a bool is boolean logic. It makes sense if you don't think about it too much.
|
|
src/expression.c
Outdated
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.
No comments inside expressions please, move them outside the condition.
0ae7224 to
963e604
Compare
|
For better reuse I broke out logic into AFAIK Step 1, 2, 3 and 4 should now be covered. You are free to express desire in my namings. They are quite arbitrary. BTW: What's the policy on using C++ function out parameter references instead of pointers in DMD? I can't find any usage of it anywhere in expression.c at least. |
src/expression.c
Outdated
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.
This doesn't need to be a member function, and if it's private to this file you can also move Boundness out of the header.
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.
What about lengthVar? How do I get that Without this pointer?
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.
Pass it to the function.
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.
Why is lengthVar a member of OpSlice? Shouldn't it be better to have one global instance of it?
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.
Because each slice has its own length variable. eg x[$-{ return a[$-5..b[$-2]+$/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.
Aha.
The policy is don't. |
|
I'm really not sure that kind of those heuristic checks will be accepted. In #4209, I'm doing similar implementation, but it's currently pending because it's looks dirty. |
|
Are there any relevant dollar expressions for Step 5 (more complex than Step 4)? |
44882c5 to
08c6a20
Compare
|
BTW: How do I handle signed integer literateral offsets, in my case for example |
|
BTW: I'm missing
for simplifying code for pattern matching on subclasses to Why hasn't these been added? Is it ok to add these on demand in this pull? |
|
|
My only conculsion is that something is using a slice bound out of range perhaps in a traits compiles. Infinite range? |
|
From the type in the error it doesn't look a like an infinite range. I don't know why it's happening. |
|
@andralex @WalterBright @9rnsr : Do you have any clues to why all 64-bit builds fail but not the 32-bit ones? |
|
Part of static if (hasSlicing!R)
{
static if (is(typeof(_input[ulong.max .. ulong.max]))) // <---
private alias opSlice_t = ulong;
else
private alias opSlice_t = uint;
static if (hasLength!R)
{
auto opSlice(opSlice_t low, opSlice_t high)
{
return typeof(this)(_input[low .. high]);
}
}
else static if (is(typeof(_input[opSlice_t.max .. $])))
{ |
|
So the natural question now becomes...should we drop bounds checking for these "negative" integer literals or fix Phobos? @andralex ? |
|
No. In that case ( |
|
Don't we have functions in phobos explicitly for use in |
|
@yebblies With |
|
I mean writing |
|
And, I think the |
|
What about index bound expressions such as |
|
Both Maybe I should add unittests :) |
|
If a slice |
|
Also add following case: if (0)
{
int[] arr = [1,2,3];
auto a = arr[size_t.max .. size_t.max]; // should compile
} |
|
So do you all agree on no compile-time error checking here? |
When is |
If it's inside |
|
If we follow the convention of being backwards compatible with |
Why would it be valid inside |
|
Inside typeof, only the expression type is validated. Bounds check doesn't modify the expression type. Therefore it should not work in typeof. |
|
@nordlow - Status update on this? |
Extends dlang#4293, and inspired by dlang#4351.
|
I'm going to say 👎 to this. Though I have taken the inspiration for the idea and put it in a new PR #7677. |
Extends dlang#4293, and inspired by dlang#4351.
The goal here is to avoid boundschecking for slice expression whose lower or/and upper bounds can never be outside of
[0 .. $]. Further, if a slice index can be proven to be outside of bounds an error is issued.Step 1:
Step 2:
where
nis a compile-time constant >= 1Step 3:
where
mandnare compile-time constants both >= 1 andm >= n.Step 4:
where
p,q,randsare compile-time constants both >= 1 andp/q <= r/s,p <= q,r <= s.Step 5 (error reporting only):
I put this out in the open in a very early stage to get feedback as soon as possible. This so I don't diverge in a direction that you dislike.
I use a warning for now for debug purpose.
My prel tests seems to show that the current logic holds water and at least doesn't crash DMD :)
Most of my questions are given as TODO comments.
Specifically I'm curious
class DollarExpinstead ofVarExp. That would have madeisOpDollartrivial.(x->op == TOKdiv)is it guaranteed thatxis of typeDivExp? This seems like an insecure pattern. I see that DMD hasisVarDeclarationso why isn't there correspondingis.*Exp?Note that the naming of the variable
lowerIsLessThanUpperis misleading as it's value is true ifflwr <= upr.lowerIsLessThanOrEqualToUpperorlowerIsLTEToUpperwould be a better name.Update: Another key issue is whether this should include analysis of immutable slice initializations such as, for instance, line 37 to to 46 in std.ascii.
Destroy and thanks in advance!