stockpiles: fix empty list crash

I was clear()ing all empty stockpile index vectors , but DF expects them
to be initialized with '\0' despite the fact they aren't used.

To keep DF happy and prevent segfaults, we now initialize all lists to
their appropriate sizes with a sane default value.
develop
Casey Link 2014-11-22 18:25:00 +01:00
parent 869a92dfc5
commit f2d4bf53bd
1 changed files with 118 additions and 162 deletions

@ -684,8 +684,7 @@ private:
*/ */
void unserialize_list_organic_mat ( FuncReadImport get_value, size_t list_size, std::vector<char> *pile_list, organic_mat_category::organic_mat_category cat ) void unserialize_list_organic_mat ( FuncReadImport get_value, size_t list_size, std::vector<char> *pile_list, organic_mat_category::organic_mat_category cat )
{ {
if ( list_size > 0 ) pile_list->clear();
{
pile_list->resize ( OrganicMatLookup::food_max_size ( cat ), '\0' ); pile_list->resize ( OrganicMatLookup::food_max_size ( cat ), '\0' );
for ( size_t i = 0; i < list_size; ++i ) for ( size_t i = 0; i < list_size; ++i )
{ {
@ -700,11 +699,6 @@ private:
pile_list->at ( idx ) = 1; pile_list->at ( idx ) = 1;
} }
} }
else
{
pile_list->clear();
}
}
/** /**
* @see serialize_list_organic_mat * @see serialize_list_organic_mat
@ -732,11 +726,14 @@ private:
*/ */
void unserialize_list_item_type ( FuncItemAllowed is_allowed, FuncReadImport read_value, int32_t list_size, std::vector<char> *pile_list ) void unserialize_list_item_type ( FuncItemAllowed is_allowed, FuncReadImport read_value, int32_t list_size, std::vector<char> *pile_list )
{ {
if ( list_size > 0 ) pile_list->clear();
pile_list->resize ( 112, '\0' ); // TODO remove hardcoded list size value
for ( int i = 0; i < pile_list->size(); ++i )
{ {
pile_list->at ( i ) = is_allowed ( ( item_type::item_type ) i ) ? 0 : 1;
}
using df::enums::item_type::item_type; using df::enums::item_type::item_type;
df::enum_traits<item_type> type_traits; df::enum_traits<item_type> type_traits;
pile_list->resize ( 112, '\0' ); // TODO remove hardcoded list size value
for ( int32_t i = 0; i < list_size; ++i ) for ( int32_t i = 0; i < list_size; ++i )
{ {
const std::string token = read_value ( i ); const std::string token = read_value ( i );
@ -753,11 +750,6 @@ private:
pile_list->at ( idx ) = 1; pile_list->at ( idx ) = 1;
} }
} }
else
{
pile_list->clear();
}
}
/** /**
* @see serialize_list_organic_mat * @see serialize_list_organic_mat
@ -781,8 +773,6 @@ private:
* @see serialize_list_organic_mat * @see serialize_list_organic_mat
*/ */
void unserialize_list_material ( FuncMaterialAllowed is_allowed, FuncReadImport read_value, int32_t list_size, std::vector<char> *pile_list ) void unserialize_list_material ( FuncMaterialAllowed is_allowed, FuncReadImport read_value, int32_t list_size, std::vector<char> *pile_list )
{
if ( list_size > 0 )
{ {
// we initialize all possible (allowed) values to 0, // we initialize all possible (allowed) values to 0,
// then all other not-allowed values to 1 // then all other not-allowed values to 1
@ -791,9 +781,10 @@ private:
std::set<int32_t> idx_set; std::set<int32_t> idx_set;
pile_list->clear(); pile_list->clear();
pile_list->resize ( world->raws.inorganics.size(), 0 ); pile_list->resize ( world->raws.inorganics.size(), 0 );
for ( int i = 0; i < pile_list->size(); ++i ) { for ( int i = 0; i < pile_list->size(); ++i )
MaterialInfo mi(0, i); {
pile_list->at(i) = is_allowed ( mi ) ? 0 : 1; MaterialInfo mi ( 0, i );
pile_list->at ( i ) = is_allowed ( mi ) ? 0 : 1;
} }
for ( int i = 0; i < list_size; ++i ) for ( int i = 0; i < list_size; ++i )
{ {
@ -810,11 +801,6 @@ private:
pile_list->at ( mi.index ) = 1; pile_list->at ( mi.index ) = 1;
} }
} }
else
{
pile_list->clear();
}
}
/** /**
* @see serialize_list_organic_mat * @see serialize_list_organic_mat
@ -896,8 +882,7 @@ private:
*/ */
void unserialize_list_other_mats ( const std::map<int, std::string> other_mats, FuncReadImport read_value, int32_t list_size, std::vector<char> *pile_list ) void unserialize_list_other_mats ( const std::map<int, std::string> other_mats, FuncReadImport read_value, int32_t list_size, std::vector<char> *pile_list )
{ {
if ( list_size > 0 ) pile_list->clear();
{
pile_list->resize ( other_mats.size(), '\0' ); pile_list->resize ( other_mats.size(), '\0' );
for ( int i = 0; i < list_size; ++i ) for ( int i = 0; i < list_size; ++i )
{ {
@ -914,15 +899,10 @@ private:
debug() << "error other_mats index too large! idx[" << idx << "] max_size[" << pile_list->size() << "]" << endl; debug() << "error other_mats index too large! idx[" << idx << "] max_size[" << pile_list->size() << "]" << endl;
continue; continue;
} }
pile_list->at ( idx ) = 1; pile_list->at ( idx ) = 1;
} }
} }
else
{
pile_list->clear();
}
}
/** /**
* @see serialize_list_organic_mat * @see serialize_list_organic_mat
@ -949,8 +929,7 @@ private:
*/ */
void unserialize_list_itemdef ( FuncReadImport read_value, int32_t list_size, std::vector<char> *pile_list, item_type::item_type type ) void unserialize_list_itemdef ( FuncReadImport read_value, int32_t list_size, std::vector<char> *pile_list, item_type::item_type type )
{ {
if ( list_size > 0 ) pile_list->clear();
{
pile_list->resize ( Items::getSubtypeCount ( type ), '\0' ); pile_list->resize ( Items::getSubtypeCount ( type ), '\0' );
for ( int i = 0; i < list_size; ++i ) for ( int i = 0; i < list_size; ++i )
{ {
@ -966,11 +945,6 @@ private:
pile_list->at ( ii.subtype ) = 1; pile_list->at ( ii.subtype ) = 1;
} }
} }
else
{
pile_list->clear();
}
}
/** /**
* Given a list of other_materials and an index, return its corresponding token * Given a list of other_materials and an index, return its corresponding token
@ -1419,11 +1393,12 @@ private:
mPile->settings.furniture.sand_bags = false; mPile->settings.furniture.sand_bags = false;
// type // type
if ( furniture.type_size() > 0 )
{
using df::enums::furniture_type::furniture_type; using df::enums::furniture_type::furniture_type;
df::enum_traits<furniture_type> type_traits; df::enum_traits<furniture_type> type_traits;
mPile->settings.furniture.type.clear();
mPile->settings.furniture.type.resize ( type_traits.last_item_value+1, '\0' ); mPile->settings.furniture.type.resize ( type_traits.last_item_value+1, '\0' );
if ( furniture.type_size() > 0 )
{
for ( int i = 0; i < furniture.type_size(); ++i ) for ( int i = 0; i < furniture.type_size(); ++i )
{ {
const std::string type = furniture.type ( i ); const std::string type = furniture.type ( i );
@ -1437,8 +1412,6 @@ private:
mPile->settings.furniture.type.at ( idx ) = 1; mPile->settings.furniture.type.at ( idx ) = 1;
} }
} }
else
mPile->settings.furniture.type.clear();
FuncMaterialAllowed filter = std::bind ( &StockpileSerializer::furniture_mat_is_allowed, this, _1 ); FuncMaterialAllowed filter = std::bind ( &StockpileSerializer::furniture_mat_is_allowed, this, _1 );
unserialize_list_material ( filter, [=] ( const size_t & idx ) -> const std::string& unserialize_list_material ( filter, [=] ( const size_t & idx ) -> const std::string&
@ -1575,9 +1548,10 @@ private:
void refuse_read_helper ( std::function<std::string ( const size_t& ) > get_value, size_t list_size, std::vector<char>* pile_list ) void refuse_read_helper ( std::function<std::string ( const size_t& ) > get_value, size_t list_size, std::vector<char>* pile_list )
{ {
pile_list->clear();
pile_list->resize ( world->raws.creatures.all.size(), '\0' );
if ( list_size > 0 ) if ( list_size > 0 )
{ {
pile_list->resize ( world->raws.creatures.all.size(), '\0' );
for ( size_t i = 0; i < list_size; ++i ) for ( size_t i = 0; i < list_size; ++i )
{ {
const std::string creature_id = get_value ( i ); const std::string creature_id = get_value ( i );
@ -1592,10 +1566,6 @@ private:
pile_list->at ( idx ) = 1; pile_list->at ( idx ) = 1;
} }
} }
else
{
pile_list->clear();
}
} }
@ -1799,10 +1769,11 @@ private:
}, ammo.mats_size(), &mPile->settings.ammo.mats ); }, ammo.mats_size(), &mPile->settings.ammo.mats );
// others // others
mPile->settings.ammo.other_mats.clear();
mPile->settings.ammo.other_mats.resize ( 2, '\0' );
if ( ammo.other_mats_size() > 0 ) if ( ammo.other_mats_size() > 0 )
{ {
// TODO remove hardcoded value // TODO remove hardcoded value
mPile->settings.ammo.other_mats.resize ( 2, '\0' );
for ( int i = 0; i < ammo.other_mats_size(); ++i ) for ( int i = 0; i < ammo.other_mats_size(); ++i )
{ {
const std::string token = ammo.other_mats ( i ); const std::string token = ammo.other_mats ( i );
@ -1812,8 +1783,6 @@ private:
mPile->settings.ammo.other_mats.at ( idx ) = 1; mPile->settings.ammo.other_mats.at ( idx ) = 1;
} }
} }
else
mPile->settings.ammo.other_mats.clear();
// core quality // core quality
unserialize_list_quality ( [=] ( const size_t & idx ) -> const std::string& unserialize_list_quality ( [=] ( const size_t & idx ) -> const std::string&
@ -2051,8 +2020,7 @@ private:
const size_t builtin_size = std::extent<decltype ( world->raws.mat_table.builtin ) >::value; const size_t builtin_size = std::extent<decltype ( world->raws.mat_table.builtin ) >::value;
// rough other // rough other
if ( gems.rough_other_mats_size() > 0 ) mPile->settings.gems.rough_other_mats.clear();
{
mPile->settings.gems.rough_other_mats.resize ( builtin_size, '\0' ); mPile->settings.gems.rough_other_mats.resize ( builtin_size, '\0' );
for ( int i = 0; i < gems.rough_other_mats_size(); ++i ) for ( int i = 0; i < gems.rough_other_mats_size(); ++i )
{ {
@ -2067,13 +2035,9 @@ private:
debug() << " rough_other mats " << mi.type << " is " << token << endl; debug() << " rough_other mats " << mi.type << " is " << token << endl;
mPile->settings.gems.rough_other_mats.at ( mi.type ) = 1; mPile->settings.gems.rough_other_mats.at ( mi.type ) = 1;
} }
}
else
mPile->settings.gems.rough_other_mats.clear();
// cut other // cut other
if ( gems.cut_other_mats_size() > 0 ) mPile->settings.gems.cut_other_mats.clear();
{
mPile->settings.gems.cut_other_mats.resize ( builtin_size, '\0' ); mPile->settings.gems.cut_other_mats.resize ( builtin_size, '\0' );
for ( int i = 0; i < gems.cut_other_mats_size(); ++i ) for ( int i = 0; i < gems.cut_other_mats_size(); ++i )
{ {
@ -2086,11 +2050,7 @@ private:
continue; continue;
} }
debug() << " cut_other mats " << mi.type << " is " << token << endl; debug() << " cut_other mats " << mi.type << " is " << token << endl;
mPile->settings.gems.cut_other_mats.at ( mi.type ) = 1; mPile->settings.gems.cut_other_mats.at ( mi.type ) = 1; }
}
}
else
mPile->settings.gems.cut_other_mats.clear();
} }
else else
{ {
@ -2420,8 +2380,7 @@ private:
const StockpileSettings::WoodSet wood = mBuffer.wood(); const StockpileSettings::WoodSet wood = mBuffer.wood();
debug() << "wood: " <<endl; debug() << "wood: " <<endl;
if ( wood.mats_size() > 0 ) mPile->settings.wood.mats.clear();
{
mPile->settings.wood.mats.resize ( world->raws.plants.all.size(), '\0' ); mPile->settings.wood.mats.resize ( world->raws.plants.all.size(), '\0' );
for ( int i = 0; i < wood.mats_size(); ++i ) for ( int i = 0; i < wood.mats_size(); ++i )
{ {
@ -2436,9 +2395,6 @@ private:
mPile->settings.wood.mats.at ( idx ) = 1; mPile->settings.wood.mats.at ( idx ) = 1;
} }
} }
else
mPile->settings.wood.mats.clear();
}
else else
{ {
mPile->settings.flags.bits.wood = 0; mPile->settings.flags.bits.wood = 0;