fixed: in BaseExpression::put_field_value_list_model() model_env_local.model pointer was not set to the child object

reported by clang with -fsanitize=undefined
main.cpp:55:63: runtime error: member access within address 0x614000000040 which does not point to an object of type 'Krolik'
0x614000000040: note: object is of type 'Item'
 02 00 00 73  00 4e 75 00 00 00 00 00  a0 b9 ff ff ff 7f 00 00  c0 80 ff ff ff 7f 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'Item'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior main.cpp:55:63 in
main.cpp:55:97: runtime error: member access within address 0x614000000040 which does not point to an object of type 'Krolik'
0x614000000040: note: object is of type 'Item'
 02 00 00 73  00 4e 75 00 00 00 00 00  a0 b9 ff ff ff 7f 00 00  c0 80 ff ff ff 7f 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'Item'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior main.cpp:55:97 in
This commit is contained in:
2021-07-01 22:39:50 +02:00
parent 097c09b9e3
commit 84fd351bfc
2 changed files with 1 additions and 0 deletions

426
src/modelcontainerwrapper.h Normal file
View File

@@ -0,0 +1,426 @@
/*
* This file is a part of morm
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_morm_modelwrapper
#define headerfile_morm_modelwrapper
#include <map>
#include <vector>
#include <list>
#include <string>
#include <limits>
#include "space/space.h"
namespace morm
{
class Model;
class ModelWrapper
{
public:
ModelWrapper()
{
auto_remove = true;
}
virtual ~ModelWrapper()
{
clear_childs();
}
virtual bool should_be_auto_removed()
{
return auto_remove;
}
virtual Model * get_model()
{
return nullptr;
}
virtual pt::Space * get_space()
{
return nullptr;
}
virtual bool is_container()
{
return false;
}
virtual bool is_container_empty()
{
return true;
}
virtual void increment_iterator()
{
}
virtual void increment_iterator(size_t space_index, size_t table_size)
{
}
virtual size_t space_indices_table_size()
{
return 0;
}
virtual bool is_iterator_correct()
{
return false;
}
virtual size_t get_space_iterator_value(size_t space_index)
{
return std::numeric_limits<size_t>::max();
}
virtual void clear_childs()
{
for(auto & map_item : childs_map)
{
if( map_item.second->should_be_auto_removed() )
{
delete map_item.second;
map_item.second = nullptr;
}
}
childs_map.clear();
}
virtual void add_child(const std::wstring & child_name, ModelWrapper * models_base)
{
childs_map[child_name] = models_base;
}
virtual ModelWrapper * find_child(const std::wstring & child_name)
{
auto i = childs_map.find(child_name);
if( i != childs_map.end() )
{
return i->second;
}
return nullptr;
}
protected:
bool auto_remove;
std::map<std::wstring, ModelWrapper*> childs_map;
private:
ModelWrapper(const ModelWrapper &)
{
auto_remove = false;
}
ModelWrapper & operator=(const ModelWrapper &)
{
return *this;
}
};
class ModelWrapperModel : public ModelWrapper
{
public:
ModelWrapperModel(Model * model)
{
this->model = model;
}
Model * get_model()
{
return model;
}
protected:
Model * model;
};
class ModelWrapperSpace : public ModelWrapper
{
public:
ModelWrapperSpace(pt::Space * space)
{
this->space = space;
initialize_indices();
}
pt::Space * get_space()
{
return space;
}
size_t space_indices_table_size()
{
return MODEL_WRAPPER_SPACE_INDICES_TABLE_SIZE;
}
void increment_iterator(size_t space_index, size_t table_size)
{
if( space_index < indices.size() )
{
if( indices[space_index] >= table_size )
{
indices[space_index] = 0;
}
else
{
indices[space_index] += 1;
}
}
}
size_t get_space_iterator_value(size_t space_index)
{
if( space_index < indices.size() )
{
return indices[space_index];
}
return std::numeric_limits<size_t>::max();
}
protected:
const size_t MODEL_WRAPPER_SPACE_INDICES_TABLE_SIZE = 32;
pt::Space * space;
std::vector<size_t> indices;
void initialize_indices()
{
indices.resize(MODEL_WRAPPER_SPACE_INDICES_TABLE_SIZE);
for(size_t & val : indices)
{
val = std::numeric_limits<size_t>::max();
}
}
};
template<typename ContainerType>
class ModelWrapperBaseContainer : public ModelWrapper
{
public:
ModelWrapperBaseContainer(ContainerType * container)
{
this->container = container;
iterator = container->end();
}
bool is_container()
{
return true;
}
bool is_container_empty()
{
return container->empty();
}
void increment_iterator()
{
if( iterator == container->end() )
{
iterator = container->begin();
}
else
{
++iterator;
}
}
bool is_iterator_correct()
{
return iterator != container->end();
}
protected:
ContainerType * container;
typename ContainerType::iterator iterator;
};
template<typename VectorType>
class ModelWrapperVector : public ModelWrapperBaseContainer<std::vector<VectorType>>
{
public:
using ModelWrapperBaseContainer<std::vector<VectorType>>::container;
using ModelWrapperBaseContainer<std::vector<VectorType>>::iterator;
ModelWrapperVector(std::vector<VectorType> * container) : ModelWrapperBaseContainer<std::vector<VectorType>>(container)
{
}
Model * get_model()
{
if( iterator != container->end() )
{
return &(*iterator);
}
return nullptr;
}
};
template<typename VectorType>
class ModelWrapperVectorPointer : public ModelWrapperBaseContainer<std::vector<VectorType*>>
{
public:
using ModelWrapperBaseContainer<std::vector<VectorType*>>::container;
using ModelWrapperBaseContainer<std::vector<VectorType*>>::iterator;
ModelWrapperVectorPointer(std::vector<VectorType*> * container) : ModelWrapperBaseContainer<std::vector<VectorType*>>(container)
{
}
Model * get_model()
{
if( iterator != container->end() )
{
return (*iterator);
}
return nullptr;
}
};
template<typename ListType>
class ModelWrapperList : public ModelWrapperBaseContainer<std::list<ListType>>
{
public:
using ModelWrapperBaseContainer<std::list<ListType>>::container;
using ModelWrapperBaseContainer<std::list<ListType>>::iterator;
ModelWrapperList(std::list<ListType> * container): ModelWrapperBaseContainer<std::list<ListType>>(container)
{
}
Model * get_model()
{
if( iterator != container->end() )
{
return &(*iterator);
}
return nullptr;
}
};
template<typename ListType>
class ModelWrapperListPointer : public ModelWrapperBaseContainer<std::list<ListType*>>
{
public:
using ModelWrapperBaseContainer<std::list<ListType*>>::container;
using ModelWrapperBaseContainer<std::list<ListType*>>::iterator;
ModelWrapperListPointer(std::list<ListType*> * container): ModelWrapperBaseContainer<std::list<ListType*>>(container)
{
}
Model * get_model()
{
if( iterator != container->end() )
{
return (*iterator);
}
return nullptr;
}
};
}
#endif