Skip to content

feat: add map/unordered_map bounds checking #3671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 52 commits into
base: develop
Choose a base branch
from

Conversation

arng40
Copy link
Contributor

@arng40 arng40 commented May 16, 2025

This PR adds further bounds checking in GEOS.

  • std::map/unordered_map wrapper that has bounds checking for ::operator
  • disallow use of map/unordered_map::operator[] to perform insertion.
    the new wrappers are preprocessor guarded with aliases s.t. they alias to the std::container in the non-bounds checking case.

@arng40 arng40 self-assigned this May 16, 2025
@arng40 arng40 added the type: feature New feature or request label May 16, 2025
@arng40 arng40 changed the title Improve map/unordered_map bound checking Improve map/unordered_map bounds checking May 16, 2025
@arng40 arng40 changed the title Improve map/unordered_map bounds checking feat: add map/unordered_map bounds checking May 19, 2025
@arng40 arng40 added ci: run CUDA builds Allows to triggers (costly) CUDA jobs ci: run integrated tests Allows to run the integrated tests in GEOS CI flag: no rebaseline Does not require rebaseline labels May 19, 2025
@arng40
Copy link
Contributor Author

arng40 commented Jun 3, 2025

I think that the compil issue might be related to inheriting constructors

Copy link
Contributor

@MelReyCG MelReyCG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it normal that there still are some direct usage of std::vector & std::map? (unitTests/, event/, fileIO/...)

@MelReyCG
Copy link
Contributor

MelReyCG commented Jun 5, 2025

I think we will need one more PR for std::array<>.
@arng40 @rrsettgast

@@ -22,6 +22,7 @@
#include "xmlWrapper.hpp"

#include "common/format/StringUtilities.hpp"
#include "common/StdContainerWrappers.hpp"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why adding this header here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Comment on lines 177 to 180
string_array & phaseNames = group.getReference< string_array >( MultiFluidBase::viewKeyStruct::phaseNamesString() );
phaseNames = {"gas", "liquid"};

auto & compNames = group.getReference< string_array >( MultiFluidBase::viewKeyStruct::componentNamesString() );
string_array & compNames = group.getReference< string_array >( MultiFluidBase::viewKeyStruct::componentNamesString() );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we found the compilation issue, I think you can revert that.

Comment on lines 18 to 21
testMultiFluidBlackOil.cpp
testMultiFluidCO2Brine.cpp
testMultiFluidTwoPhaseCompositionalMultiphase.cpp
testMultiFluidCO2Brine.cpp
testMultiFluidDeadOil.cpp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C < T

Comment on lines 132 to 133
* Access element at index with bounds checking if USE_STD_CONTAINER_BOUNDS_CHECKING is true.
* Otherwise, uses operator[] for unchecked access.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Access element at index with bounds checking if USE_STD_CONTAINER_BOUNDS_CHECKING is true.
* Otherwise, uses operator[] for unchecked access.
* Access element at index with bounds checking if USE_BOUNDS_CHECKING is true.
* Otherwise, uses operator[] for unchecked access.
* @throws std::out_of_range if index is out of bounds.

(and same below)

Comment on lines 272 to 288
template< typename TKEY, typename TVAL, typename SORTED >
class mapBase
{};

/// @cond DO_NOT_DOCUMENT
template< typename TKEY, typename TVAL >
class mapBase< TKEY, TVAL, std::integral_constant< bool, true > > : public stdMap< TKEY, TVAL >
{
public:
using stdMap< TKEY, TVAL >::stdMap;
};

template< typename TKEY, typename TVAL >
class mapBase< TKEY, TVAL, std::integral_constant< bool, false > > : public stdUnorderedMap< TKEY, TVAL >
{
using stdUnorderedMap< TKEY, TVAL >::stdUnorderedMap;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could simplify this part:

  • about the mapBase naming, there is no real "base" concept here, nor need for a class here,
  • why not simplifying the std::integral_constant to a simple bool?
  • a pattern like the std::*_t would be more standard.

I would suggest:

namespace internal
{

template< typename TKEY, typename TVAL, bool SORTED >
struct stdMapTypeDefinition
{};

template<typename TKEY, typename TVAL>
struct stdMapTypeDefinition< TKEY, TVAL,true >
{ using Type = stdMap< TKEY, TVAL >; };

template<typename TKEY, typename TVAL>
struct stdMapTypeDefinition< TKEY, TVAL,false >
{ using Type = stdUnorderedMap< TKEY, TVAL >; };

} // namespace internal

/**
 * @brief templated type for ordered and unordered maps.
 * @tparam TKEY key type
 * @tparam TVAL value type
 * @tparam SORTED a bool indicating whether map is ordered
 */
template< typename TKEY, typename TVAL, bool SORTED >
using stdMapType = internal::stdMapTypeDefinition<TKEY,TVAL,SORTED>::Type;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They would be a lot of changements in BufferOps.hpp imo

Copy link
Contributor Author

@arng40 arng40 Jun 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed mapBase to mapType
I can't change typename SORTED to bool SORTED, I tried and it required a lot of work for this PR and maybe when we will jump into c++20 for concepts

Comment on lines 189 to 191
template< typename MapType,
bool USE_BOUNDS_CHECKING = false
>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template< typename MapType,
bool USE_BOUNDS_CHECKING = false
>
template< typename MapType,
bool USE_BOUNDS_CHECKING = false >

Comment on lines 203 to 226
// Override operator[]
MappedType & operator[]( KeyType const & key )
{
if constexpr (USE_BOUNDS_CHECKING)
{
return this->at( key ); // Throws std::out_of_range if key is missing
}
else
{
return Base::operator[]( key ); // Inserts default-constructed value if missing
}
}

MappedType const & operator[]( KeyType const & key ) const
{
if constexpr (USE_BOUNDS_CHECKING)
{
return this->at( key );
}
else
{
return Base::operator[]( key );
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where the behaviour of these operators is tested in fonction of all possible USE_BOUNDS_CHECKING values? (same remark for stdVector, except that it cannot be tested against USE_BOUNDS_CHECKING=false)
If they are not tested, we can add them in testDataTypes.cpp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a test in testDataTypes.cpp

@arng40 arng40 requested a review from MelReyCG June 13, 2025 09:25
@rrsettgast
Copy link
Member

@arng40 Do you think it would be good idea to introduce the aliases (i.e. stdUnorderedMap, stdMap) in a separate PR which just aliases to std::unordered_map, and std::map so that we can review the actual changes independently from this swap...which should result in no behavioral changes with develop?

@arng40
Copy link
Contributor Author

arng40 commented Jun 18, 2025

@arng40 Do you think it would be good idea to introduce the aliases (i.e. stdUnorderedMap, stdMap) in a separate PR which just aliases to std::unordered_map, and std::map so that we can review the actual changes independently from this swap...which should result in no behavioral changes with develop?

@rrsettgast
I don't see any problem in splitting into 2 PR. I wond if in the 2nd PR we shouldn't use map and unordered_map as alias (stdMap cannot be converted to a map) to avoid confusion for when we use stdMap or map.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci: run CUDA builds Allows to triggers (costly) CUDA jobs ci: run integrated tests Allows to run the integrated tests in GEOS CI flag: no rebaseline Does not require rebaseline type: feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants