Skip to content
This repository has been archived by the owner on Sep 1, 2022. It is now read-only.

Core: create buffer utility class + buffer unit-test + RI buffer refactor #926

Merged
merged 3 commits into from
Jun 30, 2018

Conversation

anonimal
Copy link
Collaborator


By submitting this pull-request, I confirm the following:

  • I have read and understood the developer guide in kovri-docs.
  • I have checked that another pull-request for this purpose does not exist.
  • I have considered and confirmed that this submission will be valuable to others.
  • I accept that this submission may not be used and that this pull-request may be closed by the will of the maintainer.
  • I give this submission freely under the BSD 3-clause license.

This was getting in the way of me finishing my bandcaps branch. Otherwise, I'd have left the TODO.

RouterInfo is still very messy. Pulling it apart and a writing unit-test will be beneficial. Referencing #627.

Copy link
Contributor

@coneiric coneiric left a comment

Choose a reason for hiding this comment

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

This implementation is a great improvement over what is currently in place.

Other than the overwrite case, which may only be fixable in how the buffer is used, these changes LGTM.

reinterpret_cast<std::uint8_t*>(m_Buffer.get()) + m_BufferLen);
m_Buffer.data(),
m_Buffer.size(),
m_Buffer.data() + m_Buffer.size());
Copy link
Contributor

Choose a reason for hiding this comment

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

These changes are definitely better that what's currently in place.

This is potentially dangerous if router_info.Str().size() + private_keys.GetPublic().GetSignatureLen() is greater than Size::MaxBuffer, since it would write past the end of the buffer, without throwing an error. With the changes in #917, this will be a non-issue here, but may come up in other places.

See my comment about a suggested test for proof of a SIGABRT.

Copy link
Contributor

Choose a reason for hiding this comment

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

This bug pre-existed the buffer util changes, and buffer util makes the situation better. With the changes in the signature PR, on top of this PR, this bug will no longer exist.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this is a dangerous and stupid way to do things, but this applies to any underlying pointer handling (and this is legacy code btw). I imagined you'd rebase #917 and that's good because RI needs further refactoring.

Copy link
Contributor

Choose a reason for hiding this comment

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

I imagined you'd rebase #917 and that's good because RI needs further refactoring.

This is exactly what I intend to do. Happy to be helping fix the legacy code.


buf(data.data(), data.size());
BOOST_CHECK(buf.get() == data);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure how to catch the stack smashing error with Boost.Test, but wanted to simulate the exceptional case of an overwrite during RouterInfo signing.

Here is the test case that produces the error:

diff --git a/tests/unit_tests/core/util/buffer.cc b/tests/unit_tests/core/util/buffer.cc
index fbed86ef..88fa4721 100644
--- a/tests/unit_tests/core/util/buffer.cc
+++ b/tests/unit_tests/core/util/buffer.cc
@@ -97,6 +97,15 @@ BOOST_AUTO_TEST_CASE(Data)
   BOOST_CHECK(buf.get() == data);
 }
 
+BOOST_AUTO_TEST_CASE(DataOverwrite)
+{
+  std::array<std::uint8_t, Max> data{{}};
+  std::array<std::uint8_t, 64> extra{{}};
+
+  BOOST_CHECK_NO_THROW(buf(data.data(), data.size()));
+  memcpy(buf.data() + buf.size(), extra.data(), extra.size());
+}
+

the output from the suite:

Running 166 test cases...
*** stack smashing detected ***: <unknown> terminated
unknown location(0): fatal error: in "Buffer/DataOverwrite": signal: SIGABRT (application abort requested)
/kovri/tests/unit_tests/core/util/buffer.cc(100): last checkpoint: "DataOverwrite" fixture dtor

*** 1 failure is detected in the test module "Master Test Suite"

The same error occurs using PrivateKeys::Sign like in the RouterInfo impl.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can't reproduce. What compiler are you using?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Note: none of the buildbot compilers (the ones that are online) can reproduce the issue. I can't reproduce with clang6. After testing with gcc8 though, I can reproduce.

buf.data() + buf.size()

But what do you expect, you're telling the compiler to do a raw copy beyond the bounds of the buffer... You will get the same thing with this:

std::array<std::uint8_t, Max> arr{{}};
std::array<std::uint8_t, Max> data{{}};
std::memcpy(arr.data() + arr.size(), data.data(), data.size());

Are you sure you weren't trying to do this?:

diff --git a/tests/unit_tests/core/util/buffer.cc b/tests/unit_tests/core/util/buffer.cc
index fbed86ef..911948f1 100644
--- a/tests/unit_tests/core/util/buffer.cc
+++ b/tests/unit_tests/core/util/buffer.cc
@@ -121,4 +121,11 @@ BOOST_AUTO_TEST_CASE(InvalidBuffer)
   BOOST_CHECK_THROW(core::Buffer<> buf(Max + 1), std::exception);
 }
 
+BOOST_AUTO_TEST_CASE(DataOverwrite)
+{
+  core::Buffer<0, 32> bad;
+  std::array<std::uint8_t, Max> data{{}};
+  BOOST_CHECK_THROW(bad(data.data(), data.size()), std::exception);
+}
+
 BOOST_AUTO_TEST_SUITE_END()

Copy link
Contributor

Choose a reason for hiding this comment

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

That case shows the expected failure much better. The one I posted was to show the danger of the previous impl, and why resolving the signature TODO is important.

Resolving the signature TODO will be much safer and straightforward with this buffer util.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've added my test case (thanks for pointing that out, I thought I had checked the functor in one of the previous cases).

The one I posted was to show the danger of the previous impl

Raw pointers are gonna raw point. Let's get rid of them when possible. This buffer util unfortunately only bandaids the problem because we really need to use pure containers whenever possible (even when interfacing with legacy code).

namespace core
{
// TODO(anonimal): Boost.Buffer?
// TODO(anonimal): SecBlock buffer
Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, my vote is for SecBlock, then we could also use this class for PrivateKeys.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes. The SecBlock family was a definitive yes (#784). As for the boost.buffer question, that's for this underlying non-SecBlock implementation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, that makes sense.

Copy link
Contributor

@coneiric coneiric left a comment

Choose a reason for hiding this comment

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

Rebased #917 with these changes, and everything works great. 👍

@anonimal anonimal merged commit c175fbf into monero-project:master Jun 30, 2018
anonimal added a commit that referenced this pull request Jun 30, 2018
c175fbf RouterInfo: buffer refactor (anonimal)
695c911 Tests: create buffer utility class unit-test (anonimal)
5e2897c Core: create buffer utility class (anonimal)
@anonimal anonimal deleted the ri-buffer branch June 30, 2018 04:05
anonimal added a commit to anonimal/kovri that referenced this pull request Jun 30, 2018
Was not rebased after the buffer refactor in monero-project#926
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants