-
-
Notifications
You must be signed in to change notification settings - Fork 664
Implement null dereference check #22040
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
base: master
Are you sure you want to change the base?
Conversation
|
Thanks for your pull request and interest in making D better, @rikkimax! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + dmd#22040" |
1ca48e7 to
c0d2c45
Compare
|
Fun fact, lazy parameters can have a null object. Oh well we just can't check for null on the object of a delegate prior to a call. |
86f1e3b to
05957b2
Compare
|
So a |
It is an Error. Something has to die in response, like all Error's. |
05957b2 to
7f74a82
Compare
|
Is the plan to have |
|
There's no technical reason why you can't recover from a NullPointerError in general, though you may choose not to as it can indicate you don't understand program state. |
Possibly. I intend to wire up the fast DFA engine to elide the checks. But can't do it until what does exist is proven to work. |
|
The performance impact is very small. The cpu's branch predictor handles it well and ldc's code generator is decent at removing dead checks and arranging the code blocks in a cache-friendly manner. (dmd's isn't so good but ldc is known to optimize better than dmd in many ways) |
|
So a single unittest in libdparse at https://buildkite.com/dlang/dmd/builds/43787/steps/canvas?sid=019a2b1c-9d02-4993-b9df-dfb58a18783d fails buildkite/dmd. The unittest
{
version (53056)[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
union {}
Klse
gosh ÿ� 'A+ SPL : tape];
}
}
}. Could the CI failure be caused by the compiler existing with error code other than what the tests expects? I also wonder how these seemingly random test cases where deduced... |
|
I'm aware, but the problem will be in the compiled libdparse, and without compiling it locally I won't be figuring out which emitted hook did it. As far as I know this could be related to XMM intrinsics, and since those are more of a known problem they're up first. |
7f74a82 to
0686734
Compare
2930e3d to
f241687
Compare
|
I just spent a good 8 hours debugging automem, thinking it wasn't supposed to fail. I wasn't even looking in the right library, thought it was Phobos's one lol. |
32c1384 to
5ee989a
Compare
|
For the record, here is a known good implementation for delegate function pointer check. The reason I'm not using that is because I think it can be improved quite significantly. |
eb4a825 to
57ed5c1
Compare
The test tests exactly that |
57ed5c1 to
47116b7
Compare
Let's just say I was barely seeing water at 3am, that's how deep I was into CI failures problems I was trying to fix! However, on the plus side, I like the solution a lot better than we came up with previously. |
|
This is much cleaner than the previous one. Thank you for the work. |
47116b7 to
8db71ae
Compare
|
CI has done the correct, thing. Anything else you need @WalterBright before I turn it off and take it out of draft? |
changelog/dmd.nullderefcheck.dd
Outdated
| @@ -0,0 +1,8 @@ | |||
| On null dereference check is now available | |||
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 optional check for a null dereference is added.
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.
changelog/dmd.nullderefcheck.dd
Outdated
| @@ -0,0 +1,8 @@ | |||
| On null dereference check is now available | |||
|
|
|||
| A new check is implemented for when a null dereference occurs. | |||
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 don't understand that sentence. Perhaps: "code is inserted to check a reference for null before it is dereferenced."
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.
| This can be enabled by using ``-check=nullderef=on`` | ||
| What happens may be customized by the ``-checkaction`` switch and by setting a new handler in ``core.exception``. | ||
|
|
||
| Due to issues in dmd's backend, not all pointer dereferences are guaranteed to get a check. |
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 does that mean?
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.
Disabling of intrinsics and their arguments.
I don't particularly want to explain this in a changelog as it won't impact everyone, but it does need acknowledgment that dmd specifically can't check all pointer dereferences.
I can disable the intrinsic check in a follow-up PR for you to look into.
| A new check is implemented for when a null dereference occurs. | ||
|
|
||
| This can be enabled by using ``-check=nullderef=on`` | ||
| What happens may be customized by the ``-checkaction`` switch and by setting a new handler in ``core.exception``. |
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 mention of what the default behavior is.
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.
Could add a brief discussion of why one would want this feature.
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.
compiler/src/dmd/astenums.d
Outdated
| /// What should happen when a dereference on null happens | ||
| enum CHECKACTIONDEREF : ubyte | ||
| { | ||
| D, /// call D hook 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.
What is the "D hook function"?
compiler/src/dmd/astenums.d
Outdated
| { | ||
| D, /// call D hook function | ||
| Assert, /// lower to an assert | ||
| Ignore /// ignore |
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 happens if one turns on checking and then ignores it? What is the purpose of that?
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.
Dead code, removed.
8db71ae to
7e31fd7
Compare
7e31fd7 to
773864e
Compare
|
I've turned this off now, will need confirmation that @WalterBright doesn't want any more changes. |
Approved work: https://forum.dlang.org/post/[email protected]
Currently turned on to see what the CI does.
Will request Walter to review once I'm happy with CI.
Heavily inspired by OpenD with thanks to @adamdruppe.
EDIT: Special thanks to @limepoutine for helping to get both function pointers and delegate function pointers to be null checked!