Skip to content

Commit

Permalink
basic_parser: make sentinel() return a unique pointer
Browse files Browse the repository at this point in the history
Right now, sentinel() casts the `basic_parser` pointer (`this`) to
`const char *`, but that pointer is not unique if the input buffer
happens to be placed right before the `basic_parser_impl` instance -
the end of that buffer then has the same address as `basic_parser`.

Example code:

```
  struct {
    char buffer[8]{"{\"12345\""};
    boost::json::stream_parser p;
  } s;
  s.p.write(s.buffer, sizeof(s.buffer));
  s.p.write(":0}", 3);
```

This stops parsing at the end of the buffer, and then the
`incomplete()` check in `parse_string()` will return true; the second
`write()` call will crash with assertion failure:

> boost/json/basic_parser_impl.hpp:1016: const char* boost::json::basic_parser<Handler>::parse_unescaped(const char*, std::integral_constant<bool, StackEmpty_>, std::integral_constant<bool, AllowComments_>, bool) [with bool StackEmpty_ = true; bool IsKey_ = true; Handler = boost::json::detail::handler]: Assertion `*cs == '\x22'' failed.

This changes `sentinel()` by adding 1 to guaranteed that the sentinel
pointer is unique even if the input buffers borders on this object.
  • Loading branch information
MaxKellermann committed Nov 22, 2022
1 parent 893df14 commit 062b93d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 1 deletion.
4 changes: 3 additions & 1 deletion include/boost/json/basic_parser_impl.hpp
Expand Up @@ -217,8 +217,10 @@ const char*
basic_parser<Handler>::
sentinel()
{
// the "+1" ensures that the returned pointer is unique even if
// the given input buffer borders on this object
return reinterpret_cast<
const char*>(this);
const char*>(this) + 1;
}

template<class Handler>
Expand Down
15 changes: 15 additions & 0 deletions test/stream_parser.cpp
Expand Up @@ -17,6 +17,7 @@

#include <sstream>
#include <iostream>
#include <cstring>

#include "parse-vectors.hpp"
#include "test.hpp"
Expand Down Expand Up @@ -1253,6 +1254,19 @@ R"xx({
BOOST_TEST(serialize(t.jv) == "[]");
}

// https://github.com/boostorg/json/pull/814
void
testSentinelOverlap()
{
struct {
char buffer[8];
boost::json::stream_parser p;
} s;
memcpy(s.buffer, "{\"12345\"", 8);
s.p.write(s.buffer, sizeof(s.buffer));
s.p.write(":0}", 3);
}

//------------------------------------------------------

void
Expand All @@ -1276,6 +1290,7 @@ R"xx({
testDupeKeys();
testIssue15();
testIssue45();
testSentinelOverlap();
}
};

Expand Down

0 comments on commit 062b93d

Please sign in to comment.