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 )
{
if ( list_size > 0 )
{
pile_list->clear();
pile_list->resize ( OrganicMatLookup::food_max_size ( cat ), '\0' );
for ( size_t i = 0; i < list_size; ++i )
{
@ -700,11 +699,6 @@ private:
pile_list->at ( idx ) = 1;
}
}
else
{
pile_list->clear();
}
}
/**
* @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 )
{
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;
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 )
{
const std::string token = read_value ( i );
@ -753,11 +750,6 @@ private:
pile_list->at ( idx ) = 1;
}
}
else
{
pile_list->clear();
}
}
/**
* @see serialize_list_organic_mat
@ -781,8 +773,6 @@ private:
* @see serialize_list_organic_mat
*/
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,
// then all other not-allowed values to 1
@ -791,7 +781,8 @@ private:
std::set<int32_t> idx_set;
pile_list->clear();
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;
}
@ -810,11 +801,6 @@ private:
pile_list->at ( mi.index ) = 1;
}
}
else
{
pile_list->clear();
}
}
/**
* @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 )
{
if ( list_size > 0 )
{
pile_list->clear();
pile_list->resize ( other_mats.size(), '\0' );
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;
continue;
}
pile_list->at ( idx ) = 1;
}
}
else
{
pile_list->clear();
}
}
/**
* @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 )
{
if ( list_size > 0 )
{
pile_list->clear();
pile_list->resize ( Items::getSubtypeCount ( type ), '\0' );
for ( int i = 0; i < list_size; ++i )
{
@ -966,11 +945,6 @@ private:
pile_list->at ( ii.subtype ) = 1;
}
}
else
{
pile_list->clear();
}
}
/**
* Given a list of other_materials and an index, return its corresponding token
@ -1419,11 +1393,12 @@ private:
mPile->settings.furniture.sand_bags = false;
// type
if ( furniture.type_size() > 0 )
{
using df::enums::furniture_type::furniture_type;
df::enum_traits<furniture_type> type_traits;
mPile->settings.furniture.type.clear();
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 )
{
const std::string type = furniture.type ( i );
@ -1437,8 +1412,6 @@ private:
mPile->settings.furniture.type.at ( idx ) = 1;
}
}
else
mPile->settings.furniture.type.clear();
FuncMaterialAllowed filter = std::bind ( &StockpileSerializer::furniture_mat_is_allowed, this, _1 );
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 )
{
pile_list->clear();
pile_list->resize ( world->raws.creatures.all.size(), '\0' );
if ( list_size > 0 )
{
pile_list->resize ( world->raws.creatures.all.size(), '\0' );
for ( size_t i = 0; i < list_size; ++i )
{
const std::string creature_id = get_value ( i );
@ -1592,10 +1566,6 @@ private:
pile_list->at ( idx ) = 1;
}
}
else
{
pile_list->clear();
}
}
@ -1799,10 +1769,11 @@ private:
}, ammo.mats_size(), &mPile->settings.ammo.mats );
// others
mPile->settings.ammo.other_mats.clear();
mPile->settings.ammo.other_mats.resize ( 2, '\0' );
if ( ammo.other_mats_size() > 0 )
{
// TODO remove hardcoded value
mPile->settings.ammo.other_mats.resize ( 2, '\0' );
for ( int i = 0; i < ammo.other_mats_size(); ++i )
{
const std::string token = ammo.other_mats ( i );
@ -1812,8 +1783,6 @@ private:
mPile->settings.ammo.other_mats.at ( idx ) = 1;
}
}
else
mPile->settings.ammo.other_mats.clear();
// core quality
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;
// 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' );
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;
mPile->settings.gems.rough_other_mats.at ( mi.type ) = 1;
}
}
else
mPile->settings.gems.rough_other_mats.clear();
// 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' );
for ( int i = 0; i < gems.cut_other_mats_size(); ++i )
{
@ -2086,11 +2050,7 @@ private:
continue;
}
debug() << " cut_other mats " << mi.type << " is " << token << endl;
mPile->settings.gems.cut_other_mats.at ( mi.type ) = 1;
}
}
else
mPile->settings.gems.cut_other_mats.clear();
mPile->settings.gems.cut_other_mats.at ( mi.type ) = 1; }
}
else
{
@ -2420,8 +2380,7 @@ private:
const StockpileSettings::WoodSet wood = mBuffer.wood();
debug() << "wood: " <<endl;
if ( wood.mats_size() > 0 )
{
mPile->settings.wood.mats.clear();
mPile->settings.wood.mats.resize ( world->raws.plants.all.size(), '\0' );
for ( int i = 0; i < wood.mats_size(); ++i )
{
@ -2436,9 +2395,6 @@ private:
mPile->settings.wood.mats.at ( idx ) = 1;
}
}
else
mPile->settings.wood.mats.clear();
}
else
{
mPile->settings.flags.bits.wood = 0;