From c258b231c0737ac02ddba88ab0e54a96ab9c04b4 Mon Sep 17 00:00:00 2001 From: Jakob Hasse <0xjakob@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:03:47 +0800 Subject: [PATCH] libstdc++-v3: Check for ptr in __pbase_type_info::__do_catch() [105387] PR libstdc++/105387 __pbase_type_info::__do_catch(), used to catch pointer type exceptions, did not check if the type info object to compare against is a pointer type info object before doing a static down-cast to a pointer type info object. Since a pointer type info object has additional fields, they would end up being undefined if the actual type info object was not a pointer type info object. A simple check has been added before the down-cast happens. In case RTTI is enabled, this does not seem to be a problem because RTTI-based checks would run before and prevent running into the bad down-cast. However, since the check is very simple and I'm not 100% sure about the RTTI-case, it has been left for both cases (RTTI and no-RTTI). libstdc++-v3/ChangeLog: * libsupc++/pbase_type_info.cc (__do_catch): * testsuite/18_support/105387.cc: New test. --- libstdc++-v3/libsupc++/pbase_type_info.cc | 5 ++- libstdc++-v3/testsuite/18_support/105387.cc | 46 +++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/18_support/105387.cc diff --git a/libstdc++-v3/libsupc++/pbase_type_info.cc b/libstdc++-v3/libsupc++/pbase_type_info.cc index ed1ad3da98a..d06dc11e460 100644 --- a/libstdc++-v3/libsupc++/pbase_type_info.cc +++ b/libstdc++-v3/libsupc++/pbase_type_info.cc @@ -74,7 +74,10 @@ __do_catch (const type_info *thr_type, // Therefore there must at least be a qualification conversion involved // But for that to be valid, our outer pointers must be const qualified. return false; - + + if (!thr_type->__is_pointer_p ()) + return false; + const __pbase_type_info *thrown_type = static_cast (thr_type); diff --git a/libstdc++-v3/testsuite/18_support/105387.cc b/libstdc++-v3/testsuite/18_support/105387.cc new file mode 100644 index 00000000000..b099814847c --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/105387.cc @@ -0,0 +1,46 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include + +// This test case checks that __pbase_type_info::__do_catch() behaves +// correctly when called with a non-pointer type info object as argument. +// In particular, __pbase_type_info::__do_catch() should not cast +// the given type object into a pointer type and try to access the +// extended fields. +int main(int argc, char **argv) +{ + // Create a zero-initialized buffer for allocation of the type object + uint8_t buffer [sizeof(__cxxabiv1::__fundamental_type_info) * 2] = {}; + + // Use placement-new to create the fundamental type info object in the + // first half of the buffer. Whenever that type info object will be + // casted to a pointer type info object, the extended fields of the + // pointer type info object will be in the second half of the buffer + // and hence be guaranteed zero. + __cxxabiv1::__fundamental_type_info *p_fund_info = + new(buffer) __cxxabiv1::__fundamental_type_info("fund_type"); + + __cxxabiv1::__pointer_type_info ptr_info("ptr_type", 0, p_fund_info); + + // __do_catch is declared protected in __pointer_type_info, but public in + // type_info, so we upcast it here + std::type_info *abstract_ptr_info = static_cast(&ptr_info); + VERIFY(abstract_ptr_info->__do_catch(p_fund_info, nullptr, 1) == false); +} -- 2.25.1