GitLab Commit is coming up on August 3-4. Learn how to innovate together using GitLab, the DevOps platform. Register for free: gitlabcommitvirtual2021.com

Commit 22c00572 authored by Kohei Yoshida's avatar Kohei Yoshida
Browse files

Handle out-of-bound range values gracefully, as originally intended.

This used to cause segfaults when position hints are passed, which is
now fixed.
parent 0d840a43
......@@ -675,6 +675,15 @@ private:
void destroy();
/**
* Check and optionally adjust the start and end key values if one of them
* is out-of-bound.
*
* @return true if the start and end key values are valid, either with or
* without adjustments, otherwise false.
*/
bool adjust_segment_range(key_type& start_key, key_type& end_key) const;
private:
std::vector<nonleaf_node> m_nonleaf_node_pool;
......
......@@ -130,21 +130,9 @@ template<typename _Key, typename _Value>
::std::pair<typename flat_segment_tree<_Key, _Value>::const_iterator, bool>
flat_segment_tree<_Key, _Value>::insert_segment_impl(key_type start_key, key_type end_key, value_type val, bool forward)
{
typedef ::std::pair<typename flat_segment_tree<_Key, _Value>::const_iterator, bool> ret_type;
typedef std::pair<typename flat_segment_tree<_Key, _Value>::const_iterator, bool> ret_type;
if (end_key < m_left_leaf->value_leaf.key || start_key > m_right_leaf->value_leaf.key)
// The new segment does not overlap the current interval.
return ret_type(const_iterator(this, true), false);
if (start_key < m_left_leaf->value_leaf.key)
// The start value should not be smaller than the current minimum.
start_key = m_left_leaf->value_leaf.key;
if (end_key > m_right_leaf->value_leaf.key)
// The end value should not be larger than the current maximum.
end_key = m_right_leaf->value_leaf.key;
if (start_key >= end_key)
if (!adjust_segment_range(start_key, end_key))
return ret_type(const_iterator(this, true), false);
// Find the node with value that either equals or is greater than the
......@@ -325,6 +313,12 @@ flat_segment_tree<_Key, _Value>::insert(
return insert_front(start_key, end_key, val);
}
if (!adjust_segment_range(start_key, end_key))
{
typedef std::pair<typename flat_segment_tree<_Key, _Value>::const_iterator, bool> ret_type;
return ret_type(const_iterator(this, true), false);
}
p = get_insertion_pos_leaf(start_key, p);
node_ptr start_pos(const_cast<node*>(p));
return insert_to_pos(start_pos, start_key, end_key, val);
......@@ -763,4 +757,26 @@ flat_segment_tree<_Key, _Value>::destroy()
m_root_node = nullptr;
}
template<typename _Key, typename _Value>
bool flat_segment_tree<_Key, _Value>::adjust_segment_range(key_type& start_key, key_type& end_key) const
{
if (start_key >= end_key)
// Invalid order of segment range.
return false;
if (end_key < m_left_leaf->value_leaf.key || start_key > m_right_leaf->value_leaf.key)
// The new segment does not overlap the current interval.
return false;
if (start_key < m_left_leaf->value_leaf.key)
// The start value should not be smaller than the current minimum.
start_key = m_left_leaf->value_leaf.key;
if (end_key > m_right_leaf->value_leaf.key)
// The end value should not be larger than the current maximum.
end_key = m_right_leaf->value_leaf.key;
return true;
}
}
......@@ -1949,6 +1949,44 @@ void fst_test_non_numeric_value()
assert(db == db2);
}
void fst_test_insert_out_of_bound()
{
stack_printer __stack_printer__("::fst_test_insert_out_of_bound");
typedef flat_segment_tree<int, bool> db_type;
db_type db(0, 10, false);
// An out-of-bound range, whether it's in part or in its entirety, should
// be handled gracefully without throwing exceptions or causing segfaults.
// ranges that are entirely out-of-bound.
auto ret = db.insert_front(-10, -8, false);
assert(!ret.second);
db.insert_back(12, 13, false);
assert(!ret.second);
db_type::const_iterator pos = db.end();
ret = db.insert(pos, -10, -8, false);
assert(!ret.second);
pos = ret.first;
ret = db.insert(pos, 12, 13, false);
assert(!ret.second);
pos = ret.first;
// partial overflows.
ret = db.insert(pos, -2, 2, true);
assert(ret.second); // content modified
pos = ret.first;
ret = db.insert(pos, 8, 20, true);
assert(ret.second); // content modified
pos = ret.first;
}
int main (int argc, char **argv)
{
try
......@@ -2004,6 +2042,7 @@ int main (int argc, char **argv)
fst_test_clear();
fst_test_assignment();
fst_test_non_numeric_value();
fst_test_insert_out_of_bound();
}
if (opt.test_perf)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment