This is an archive of the discontinued LLVM Phabricator instance.

Guard against overflow in span::subspan
AbandonedPublic

Authored by miscco on Oct 26 2019, 1:31 PM.

Details

Event Timeline

miscco created this revision.Oct 26 2019, 1:31 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 26 2019, 1:31 PM

I am just getting used to arcanist so I messed up and created a new revision. What to do here?

Also Can we actually test runtime behavior where there is an assert rather than a static_assert?

miscco updated this revision to Diff 226719.Oct 28 2019, 11:34 AM
  • Fix incorrect return type of span::subspan
  • Guard against overflow in span::subspan
miscco updated this revision to Diff 226723.Oct 28 2019, 12:00 PM
  • Add failing tests for span::first
  • Add fail tests for span::last
  • Add fail tests for element access of span and improve the error message
  • SFINAE span default constructor on Extent == 0

I have added some additional unit tests that should statically fail.

I also SFINAEd out the default constructor if Extent != 0. I did learn how to do that from microsofts STL. Is that a licensing problem @CaseyCarter?

I also believe that we should add a static assert to operator[] similar to front() and back(). Unfortunately there are multiple tests that rely on operator[] of a statically empty span. Thoughts?

miscco updated this revision to Diff 228587.Nov 9 2019, 10:46 AM
  • Implement P1872R0

Gentle Ping

Some small comments as I read it again

libcxx/include/span
305

The first condition is trivially true due to the change to size_t (__idx >= 0)

305

We should add a static_assert for _Extent > 0 similar to front() and back()

317

I should remove "[]" same for front()

474

Same here, __idx is a size_tso __idx >= 0 is always true

libcxx/test/std/containers/views/span.elem/elem.fail.cpp
34 ↗(On Diff #228587)

Should adopt the error message with something like span<T,0>::back()

miscco updated this revision to Diff 234058.Dec 16 2019, 7:11 AM
  • [span] Improve eror messages and remove tautological comparison

There's at least three things going on in this patch; and that makes it harder to review:

  • Rename all the index_types to size_type.
  • Add static_assert to several cases
  • Guard against overflow in span::subspan (ostensibly the purpose of this patch).

In the future, this should be three patches.

I also believe that we should add a static assert to operator[] similar to front() and back(). Unfortunately there are multiple tests that rely on operator[] of a statically empty span. Thoughts?

I assume that you're talking about the case where _Extent == 0 - is that correct?
If the tests are calling operator[] on a span<T, 0>, then they are incorrect and should be changed.

mclow.lists added a comment.EditedDec 16 2019, 9:23 AM

If the tests are calling operator[] on a span<T, 0>, then they are incorrect and should be changed.

Note that this is independent of whether or not we should add a static_assert to operator[].

Scrap my comment about invalid access to an empty span. Adding a static assert to operator[] fails due to evaulation of both branches during compilation:

cpp
    if (s.empty())
    {
        ret = ret &&  ( b ==  s.end());
        ret = ret &&  (cb == s.cend());
    }
    else
    {
        ret = ret &&  (  *b ==  s[0]);
        ret = ret &&  ( &*b == &s[0]);
        ret = ret &&  ( *cb ==  s[0]);
        ret = ret &&  (&*cb == &s[0]);
    }

The code in question is obviously correct. So I guess one would need to guard such checks with if (!std::is_constant_evaluated()) which seems a bit over the top.

Otherwise, I would need to revert the static_asserts in front() and back() as they would also trigger in a similar case.

Thoughts?

miscco updated this revision to Diff 234518.Dec 18 2019, 5:02 AM
  • [libcxx] span: Remove incorrect static_asserts

I removed the static_assert from the front() and back() method and added the appropriate _LIBCPP_ASSERT instead.

The problem is that the following code would otherwise break:

if (!s.empty()) {
    s.front()
}

As far as I understand we cannot use is_constant_evaluated() as that would still require the compiler to process the branch and trigger the static_assert

miscco abandoned this revision.Dec 30 2019, 5:31 AM

In order to facilitate the adoption of the changes I have created atomic revisions of the individual changes and will drop this one.