2
0
mirror of https://github.com/boostorg/json.git synced 2026-02-10 23:42:19 +00:00

limits tests

This commit is contained in:
Vinnie Falco
2019-11-11 20:40:31 -08:00
parent 68f3df0403
commit 9da2877b28
24 changed files with 403 additions and 337 deletions

View File

@@ -1688,8 +1688,7 @@ private:
value* src,
std::size_t n) noexcept;
class undo_create;
class undo_assign;
class undo_construct;
class undo_insert;
storage_ptr sp_; // must come first

View File

@@ -83,6 +83,10 @@
# define BOOST_JSON_NO_MAX_STRING_SIZE
# define BOOST_JSON_MAX_STRING_SIZE 0x7ffffffe
#endif
#ifndef BOOST_JSON_MAX_STACK_SIZE
# define BOOST_JSON_NO_MAX_STACK_SIZE
# define BOOST_JSON_MAX_STACK_SIZE ((std::size_t)(-1))
#endif
namespace boost {
namespace json {

View File

@@ -16,6 +16,22 @@ namespace boost {
namespace json {
namespace detail {
inline
std::length_error
object_too_large_exception() noexcept
{
return std::length_error(
"object too large");
}
inline
std::length_error
array_too_large_exception() noexcept
{
return std::length_error(
"array too large");
}
inline
std::length_error
string_too_large_exception() noexcept
@@ -24,6 +40,14 @@ string_too_large_exception() noexcept
"string too large");
}
inline
std::out_of_range
string_pos_too_large() noexcept
{
return std::out_of_range(
"pos > size()");
}
inline
std::length_error
key_too_large_exception() noexcept
@@ -32,14 +56,6 @@ key_too_large_exception() noexcept
"key too large");
}
inline
std::length_error
object_too_large_exception() noexcept
{
return std::length_error(
"object too large");
}
inline
std::length_error
stack_overflow_exception() noexcept

View File

@@ -113,7 +113,7 @@ private:
std::size_t
max_size() noexcept
{
return std::size_t(-1);
return BOOST_JSON_MAX_STACK_SIZE;
}
BOOST_JSON_DECL

View File

@@ -22,7 +22,7 @@ void
raw_stack::
grow(std::size_t n)
{
if(n > max_size() - size_)
if(n > max_size() - capacity_)
BOOST_JSON_THROW(
stack_overflow_exception());
auto new_capacity = capacity_ + n;
@@ -37,7 +37,7 @@ grow(std::size_t n)
if(base_)
{
std::memcpy(base, base_, size_);
sp_->deallocate(base_, size_);
sp_->deallocate(base_, capacity_);
}
base_ = base;
capacity_ = new_capacity;

View File

@@ -11,6 +11,7 @@
#define BOOST_JSON_IMPL_ARRAY_HPP
#include <boost/json/value.hpp>
#include <boost/json/detail/except.hpp>
#include <algorithm>
#include <stdexcept>
#include <type_traits>
@@ -54,7 +55,7 @@ index_of(value const* pos) const noexcept ->
//----------------------------------------------------------
class array::undo_create
class array::undo_construct
{
array& self_;
@@ -62,10 +63,10 @@ public:
bool commit = false;
BOOST_JSON_DECL
~undo_create();
~undo_construct();
explicit
undo_create(
undo_construct(
array& self) noexcept
: self_(self)
{
@@ -74,24 +75,6 @@ public:
//----------------------------------------------------------
class array::undo_assign
{
array& self_;
impl_type impl_;
public:
bool commit = false;
explicit
BOOST_JSON_DECL
undo_assign(array& self);
BOOST_JSON_DECL
~undo_assign();
};
//----------------------------------------------------------
class array::undo_insert
{
array& self_;
@@ -404,7 +387,7 @@ array(
std::input_iterator_tag)
: sp_(std::move(sp))
{
undo_create u(*this);
undo_construct u(*this);
while(first != last)
{
if(impl_.size >= impl_.capacity)
@@ -424,14 +407,13 @@ array(
std::forward_iterator_tag)
: sp_(std::move(sp))
{
undo_create u(*this);
undo_construct u(*this);
auto const n =
static_cast<std::size_t>(
std::distance(first, last));
if(n > max_size())
BOOST_JSON_THROW(
std::length_error(
"n > max_size"));
detail::array_too_large_exception());
reserve(static_cast<std::size_t>(n));
while(impl_.size < n)
{
@@ -481,8 +463,7 @@ insert(
std::distance(first, last));
if(n > max_size())
BOOST_JSON_THROW(
std::length_error(
"n > max_size"));
detail::array_too_large_exception());
undo_insert u(pos, static_cast<
std::size_t>(n), *this);
while(first != last)

View File

@@ -33,7 +33,7 @@ impl_type(
{
if(capacity_ > max_size())
BOOST_JSON_THROW(
detail::object_too_large_exception());
detail::array_too_large_exception());
if(capacity_ > 0)
vec = reinterpret_cast<value*>(
sp->allocate(
@@ -102,8 +102,8 @@ destroy(
//----------------------------------------------------------
array::
undo_create::
~undo_create()
undo_construct::
~undo_construct()
{
if(! commit)
self_.impl_.destroy(self_.sp_);
@@ -111,25 +111,6 @@ undo_create::
//----------------------------------------------------------
array::
undo_assign::
undo_assign(array& self)
: self_(self)
, impl_(std::move(self.impl_))
{
}
array::
undo_assign::
~undo_assign()
{
if(! commit)
impl_.swap(self_.impl_);
impl_.destroy(self_.sp_);
}
//----------------------------------------------------------
array::
undo_insert::
undo_insert(
@@ -142,8 +123,7 @@ undo_insert(
{
if(n > max_size())
BOOST_JSON_THROW(
std::length_error(
"size > max_size()"));
detail::array_too_large_exception());
self_.reserve(
self_.impl_.size + n_);
// (iterators invalidated now)
@@ -192,7 +172,7 @@ array(
storage_ptr sp)
: sp_(std::move(sp))
{
undo_create u(*this);
undo_construct u(*this);
reserve(count);
while(impl_.size < count)
{
@@ -210,7 +190,7 @@ array(
storage_ptr sp)
: sp_(std::move(sp))
{
undo_create u(*this);
undo_construct u(*this);
reserve(count);
while(impl_.size < count)
{
@@ -226,7 +206,7 @@ array::
array(array const& other)
: sp_(other.sp_)
{
undo_create u(*this);
undo_construct u(*this);
copy(other);
u.commit = true;
}
@@ -237,7 +217,7 @@ array(
storage_ptr sp)
: sp_(std::move(sp))
{
undo_create u(*this);
undo_construct u(*this);
copy(other);
u.commit = true;
}
@@ -269,7 +249,7 @@ array(
}
else
{
undo_create u(*this);
undo_construct u(*this);
copy(other);
u.commit = true;
}
@@ -281,7 +261,7 @@ array(
storage_ptr sp)
: sp_(std::move(sp))
{
undo_create u(*this);
undo_construct u(*this);
copy(init);
u.commit = true;
}

View File

@@ -115,22 +115,19 @@ bucket_begin() const noexcept ->
begin() + capacity());
}
auto
object::
impl_type::
bucket_end() const noexcept ->
value_type**
{
return bucket_begin() + buckets();
}
//----------------------------------------------------------
struct object::undo_construct
{
object* self;
explicit
undo_construct(
object* self_)
: self(self_)
{
}
~undo_construct()
{
if(self)
@@ -170,7 +167,7 @@ object(
storage_ptr sp)
: sp_(std::move(sp))
{
undo_construct u{this};
undo_construct u(this);
insert_range(
first, last,
min_capacity);

View File

@@ -110,14 +110,13 @@ build() noexcept
--end;
if(p != end)
{
auto& head = bucket(end->key());
remove(head, end);
end->next_ = head;
head = p;
std::memcpy(
reinterpret_cast<void*>(p),
reinterpret_cast<void const*>(end),
sizeof(*p));
auto& head = bucket(p->key());
p->next_ = head;
head = p;
}
}
}
@@ -234,7 +233,7 @@ object(
}
else
{
undo_construct u{this};
undo_construct u(this);
insert_range(
other.begin(),
other.end(), 0);
@@ -254,7 +253,7 @@ object(
object const& other)
: sp_(other.sp_)
{
undo_construct u{this};
undo_construct u(this);
insert_range(
other.begin(),
other.end(), 0);
@@ -267,7 +266,7 @@ object(
storage_ptr sp)
: sp_(std::move(sp))
{
undo_construct u{this};
undo_construct u(this);
insert_range(
other.begin(),
other.end(), 0);
@@ -281,7 +280,7 @@ object(
storage_ptr sp)
: sp_(std::move(sp))
{
undo_construct u{this};
undo_construct u(this);
insert_range(
init.begin(),
init.end(),

View File

@@ -248,21 +248,16 @@ emplace(Args&&... args)
~U(){}
};
U u;
// perform stack reallocation up-front
// VFALCO This is more than we need
rs_.prepare(sizeof(u.v));
std::size_t key_size;
pop(key_size);
// remember the offset in case
// the stack is reallocated.
auto const offset =
rs_.pop(key_size) -
rs_.begin();
auto const key =
pop_chars(key_size);
st_ = state::obj;
// prevent splits from exceptions
rs_.prepare(2 * sizeof(u.v));
::new(&u.v) object::value_type(
string_view(
rs_.begin() + offset,
key_size),
std::forward<Args>(args)...);
key, std::forward<Args>(args)...);
rs_.subtract(sizeof(u.v));
push(u.v);
rs_.add(sizeof(u.v));

View File

@@ -158,7 +158,7 @@ loop_init:
case kind::uint64:
if(p1 - p >= detail::max_number_chars)
{
p += detail::format_int64(
p += detail::format_uint64(
p, *jv.if_uint64());
stack_.pop();
goto loop;
@@ -370,7 +370,6 @@ loop_str:
std::memcpy(p, ss, n);
ss = s;
p += n;
//*p++ = ch;
*p++ = '\\';
*p++ = c;
if(c != 'u')

View File

@@ -11,6 +11,7 @@
#define BOOST_JSON_IMPL_STRING_IPP
#include <boost/json/detail/assert.hpp>
#include <boost/json/detail/except.hpp>
#include <algorithm>
#include <new>
#include <ostream>
@@ -54,8 +55,7 @@ growth(
{
if(new_size > max_size())
BOOST_JSON_THROW(
std::length_error(
"size > max_size()"));
detail::string_too_large_exception());
new_size |= mask_;
if( new_size > max_size())
return static_cast<
@@ -109,8 +109,7 @@ append(
{
if(n > max_size() - size)
BOOST_JSON_THROW(
std::length_error(
"size > max_size()"));
detail::string_too_large_exception());
if(n <= capacity - size)
{
term(size + n);
@@ -136,8 +135,7 @@ insert(
{
if(pos > size)
BOOST_JSON_THROW(
std::out_of_range(
"pos > size()"));
detail::string_pos_too_large());
if(n <= capacity - size)
{
auto const dest =
@@ -152,8 +150,7 @@ insert(
}
if(n > max_size() - size)
BOOST_JSON_THROW(
std::length_error(
"size > max_size()"));
detail::string_too_large_exception());
impl tmp(growth(
size + n, capacity), sp);
tmp.size = size + static_cast<
@@ -352,10 +349,9 @@ insert(
char const* s,
size_type count)
{
if(pos >= impl_.size)
if(pos > impl_.size)
BOOST_JSON_THROW(
std::out_of_range(
"pos >= size()"));
detail::string_pos_too_large());
if(count > impl_.capacity - impl_.size)
{
traits_type::copy(
@@ -412,8 +408,7 @@ erase(
{
if(pos > impl_.size)
BOOST_JSON_THROW(
std::out_of_range(
"pos > size()"));
detail::string_pos_too_large());
if( count > impl_.size - pos)
count = impl_.size - pos;
traits_type::move(

View File

@@ -184,7 +184,7 @@ value_type(
{
if(key.size() > BOOST_JSON_MAX_STRING_SIZE)
BOOST_JSON_THROW(
detail::string_too_large_exception());
detail::key_too_large_exception());
auto s = reinterpret_cast<
char*>(value_.get_storage()->
allocate(key.size() + 1));

View File

@@ -219,10 +219,6 @@ private:
inline
value_type**
bucket_begin() const noexcept;
inline
value_type**
bucket_end() const noexcept;
};
struct undo_construct;