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 issue 15889 - Array bounds check should report index and length #12871

Merged
merged 2 commits into from
Aug 3, 2021

Conversation

dkorpel
Copy link
Contributor

@dkorpel dkorpel commented Jul 14, 2021

Uses the ArrayIndexError and ArraySliceError instead of RangeError for array index / slice operations.
Depends on this druntime PR: dlang/druntime#3517

I still need to decide when to use them:

  • always
  • with -checkaction=context
  • in debug builds
  • in unoptimized builds
  • ...?

@dlang-bot
Copy link
Contributor

dlang-bot commented Jul 14, 2021

Thanks for your pull request and interest in making D better, @dkorpel! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

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 references

Auto-close Bugzilla Severity Description
15889 enhancement Array bounds check should report index and length

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#12871"

@dkorpel dkorpel changed the title Add informative range errors for arrays Fix issue 15889 - Array bounds check should report index and length Jul 14, 2021
@MoonlightSentinel
Copy link
Contributor

I still need to decide when to use them:

IMO the bounds should always be reported when a RangeError is thrown. They can provide vital information for a neglegible cost (in contrast to the whole RangeError construction + throwing).

@RazvanN7
Copy link
Contributor

The vision document for druntime states that implementing druntime hooks as templates is a major objective. Would it make sense for these hooks to be implemented as templates? (the main advantage would be that the associated druntime functions will not be part of the executable if not used.)

@dkorpel
Copy link
Contributor Author

dkorpel commented Jul 14, 2021

The vision document for druntime states that implementing druntime hooks as templates is a major objective. Would it make sense for these hooks to be implemented as templates?

I thought the idea was to replace functions taking TypeInfo with functions templated on the type. In this case, since range errors don't depend on the array type, a normal function works fine. The linker can still strip _d_arraybounds_indexp if it's not used (though I think very few D projects don't use bounds checks).

@dkorpel
Copy link
Contributor Author

dkorpel commented Jul 20, 2021

/home/runner/work/dmd/dmd/dmd/test/test_results/runnable_cxx/cppa_0: symbol lookup error: /home/runner/work/dmd/dmd/dmd/test/test_results/runnable_cxx/cppa_0: undefined symbol: _d_arraybounds_slicep

Looks like the C++ interop tests with GCC aren't linking with the newest druntime, does anyone know how to fix it?

@dkorpel dkorpel marked this pull request as ready for review July 24, 2021 17:38
@dkorpel dkorpel force-pushed the range-error branch 2 times, most recently from 38b353c to 191d3dd Compare August 2, 2021 08:43
@dkorpel
Copy link
Contributor Author

dkorpel commented Aug 2, 2021

Looks like the C++ interop tests with GCC aren't linking with the newest druntime, does anyone know how to fix it?

It turns out the checkout is fine, but it doesn't seem to be linking with druntime to begin with. I worked around it by adding -checkaction=C to the cppa.d test. Thanks to @Geod24 for his assistance!

Copy link
Member

@Geod24 Geod24 left a comment

Choose a reason for hiding this comment

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

Can you merge the second commit ("Add runnable test...") with the fix ? A fix / new feature should come with tests in the same commit. Also, could you swap the order of the commits so that the last commit comes first ? Each commit should be atomic, which means they should compile and pass the test-suite on their own, and the last commit is required for your feature to pass the test suite (but the last commit makes sense on its own, as the same problem would arise if, e.g. -checkaction=context was made the default, so 👍 for having it as a separate commit).

The code LGTM, and so does the changelog. Thanks for putting time to make it both informative and appealing, and for tackling that feature, it'll make a huge difference in usability.

@@ -0,0 +1,54 @@
Out of bounds array access now gives a fluent error message
Copy link
Member

Choose a reason for hiding this comment

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

POV: "fluent" is a bit vague, I would advise to either phrase it as "now includes indices" or mention "better" or "improved" error message. But that's POV, I think the message is good enough as-is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I borrowed the term 'fluent' from the common 'fluent asserts' you find in unit testing packages, but I agree it's not the best word. I'm thinking changing it to "informative" or, indeed, "better".

??:? _Dmain [0x5647250b9751]
)

The error message for indexing a non-existent key in an Associative Array has not been updated.
Copy link
Member

Choose a reason for hiding this comment

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

Not sure why this mention was warranted ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I figured people might wonder if all range errors are improved, so I'm stating a known limitation here.

Comment on lines +19 to +25
$(CONSOLE
> dmd -run main.d
core.exception.RangeError@main.d(4): Range violation
$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)
??:? _d_arrayboundsp [0x555765c167f9]
??:? _Dmain [0x555765c16752]
)
Copy link
Member

Choose a reason for hiding this comment

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

The changelog doesn't mention the two new classes derived from Error, except for the implicit mentions in the code sample. Not sure if you want to add it here or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I mentioned them at first, but I removed it because I don't want to encourage D users to catch range errors.

@dkorpel
Copy link
Contributor Author

dkorpel commented Aug 2, 2021

Each commit should be atomic, which means they should compile and pass the test-suite on their own

Thanks for the advice, I don't know a good commit separation policy so I was just winging it. I will change it.

@Geod24 Geod24 merged commit 05d2188 into dlang:master Aug 3, 2021
@ibuclaw
Copy link
Member

ibuclaw commented Aug 24, 2021

This PR made RangeErrors with pointer slices more confusing, not less.

void main()
{
    int* a = [1,2,3,4,5,6,7,8,9,10].ptr;
    a[1..5] = a[3..7];
}
core.exception.ArrayIndexError@range.d(4): index [4] exceeds array of length 4

Array length hasn't been exceeded, it just overlaps.

Edit: Same is with overlapping arrays too.

    int[] b = [1,2,3,4,5,6,7,8,9,10];
    b[1..5] = b[3..7];

@dkorpel
Copy link
Contributor Author

dkorpel commented Aug 24, 2021

I'll look into it

@@ -2246,7 +2246,7 @@ extern (C++) class ToElemVisitor : Visitor
}

// Construct: (c || arrayBoundsError)
echeck = el_bin(OPoror, TYvoid, c, buildArrayBoundsError(irs, ae.loc, null, el_copytree(eleny), el_copytree(elen)));
echeck = el_bin(OPoror, TYvoid, c, buildArrayIndexError(irs, ae.loc, el_copytree(eleny), el_copytree(elen)));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This makes no sense, this is not an index error but a slice copy error.

@dkorpel dkorpel deleted the range-error branch August 31, 2021 19:12
MoonlightSentinel added a commit to MoonlightSentinel/LWDR that referenced this pull request Mar 19, 2022
dlang/dmd#12871 implemented more informational error messages for
invalid array bounds using new hooks. This commit adds stubs that simply
forward to the existing `_d_arraybounds` for now.

See dlang/druntime#3562
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.

6 participants