cpp-netlib/uri

Incorrect port information after applying uri's assignment operator

Closed this issue · 2 comments

After overriding an URI that has port info with an URI that does not have port info, the URI object still tells that it has port info. I guess there is a bug in the implementation of network::uri's assignment operator.

Furthermore, when I pass this re-assigned URI object into the network::uri_builder constructor, the constructed new URI not only still tells it has port info, but also creates a broken URI string when calling network::uri::string(). Checking with Google's AddressSanitizer it reports a heap-use-after-free error. It seems that the string_view that points to the port info is dangling.

Some unit tests for reproduction:

#include <gtest/gtest.h>
#include "network/uri/uri_builder.hpp"

TEST(UriTest, AssignmentOperator) {
  network::uri a("http://a.com:1234");
  ASSERT_TRUE(a.has_port());

  const network::uri b("http://b.com");
  ASSERT_FALSE(b.has_port());

  a = b;
  ASSERT_FALSE(a.has_port()) << a.string();
}

TEST(UriTest, CopyConstructor) {
  network::uri a("http://a.com:1234");
  const network::uri b("http://b.com");
  a = b;

  const network::uri c(a);
  ASSERT_FALSE(c.has_port()) << c.string();
}

TEST(UriBuilderTest, ConstructFromUri) {
  network::uri a("http://a.com:1234");
  const network::uri b("http://b.com");
  a = b;

  network::uri_builder ub(a);  // ASAN reports heap-use-after-free here
  const network::uri c(ub.uri());
  ASSERT_FALSE(c.has_port()) << c.string();
}

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

Output

[==========] Running 3 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 2 tests from UriTest
[ RUN      ] UriTest.AssignmentOperator
src/uri_test.cc:12: Failure
Value of: a.has_port()
  Actual: true
Expected: false
http://b.com
[  FAILED  ] UriTest.AssignmentOperator (0 ms)
[ RUN      ] UriTest.CopyConstructor
src/uri_test.cc:21: Failure
Value of: c.has_port()
  Actual: true
Expected: false
http://b.com
[  FAILED  ] UriTest.CopyConstructor (0 ms)
[----------] 2 tests from UriTest (0 ms total)

[----------] 1 test from UriBuilderTest
[ RUN      ] UriBuilderTest.ConstructFromUri
src/uri_test.cc:31: Failure
Value of: c.has_port()
  Actual: true
Expected: false
http://b.com:1234
[  FAILED  ] UriBuilderTest.ConstructFromUri (0 ms)
[----------] 1 test from UriBuilderTest (0 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 2 test cases ran. (0 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 3 tests, listed below:
[  FAILED  ] UriTest.AssignmentOperator
[  FAILED  ] UriTest.CopyConstructor
[  FAILED  ] UriBuilderTest.ConstructFromUri

 3 FAILED TESTS

I can also provide ASAN output if needed. My compiler is gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10) and I use the latest code from the master branch. Thank you for developing cppnetlib, btw -- it's awesome!

Thanks for the report, I will investigate. I also suspect the assignment operator is buggy.

Thanks for the fix. I can confirm my tests and ASan are happy now.