diff --git a/common/include/fwd-valptridx.h b/common/include/fwd-valptridx.h index e29337a9b..6424e2a80 100644 --- a/common/include/fwd-valptridx.h +++ b/common/include/fwd-valptridx.h @@ -108,6 +108,11 @@ protected: template class Compare = std::less > static inline index_type check_index_range(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS index_type, const array_managed_type *); + template < + typename handle_index_range_error, + template class Compare = std::less + > + static inline index_type check_index_range_size(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS std::size_t, const array_managed_type *); template static inline void check_explicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, std::size_t, const array_managed_type &); template diff --git a/common/include/valptridx.h b/common/include/valptridx.h index 5e71536c0..11fb36eb4 100644 --- a/common/include/valptridx.h +++ b/common/include/valptridx.h @@ -210,11 +210,30 @@ typename valptridx::index_type valptridx::check_inde si = static_cast(i); else si = i; - const std::size_t ss = si; - DXX_VALPTRIDX_CHECK(Compare()(ss, array_size), handle_index_range_error, "invalid index used in array subscript", a, ss); + check_index_range_size(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS si, a); return i; } +template +template class Compare> +typename valptridx::index_type valptridx::check_index_range_size(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const std::size_t s, const array_managed_type *const a) +{ + DXX_VALPTRIDX_CHECK(Compare()(s, array_size), handle_index_range_error, "invalid index used in array subscript", a, s); + /* This cast will truncate the value to fit in index_type, which is + * normally smaller than std::size_t. However, truncation is legal + * here, because (1) DXX_VALPTRIDX_CHECK would trap on an index that + * was outside the array size and (2) index_type can represent any + * valid size in the array. Thus, if DXX_VALPTRIDX_CHECK did not + * trap[1], the truncation cannot change the value of the index. + * + * [1] If valptridx was built without index validation, then no trap + * would be issued even for invalid data. Validation-disabled builds + * are permitted to exhibit undefined behavior in cases where the + * validation-enabled build would have trapped. + */ + return static_cast(s); +} + template template void valptridx::check_null_pointer_conversion(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_pointer_type p) @@ -241,7 +260,7 @@ template void valptridx::check_explicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type &r, std::size_t i, const array_managed_type &a) { check_index_match(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS r, i, a); - check_index_range(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS i, &a); + check_index_range_size(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS i, &a); } template