ubsan: check type_info equality via strcmp

Stephan Bergmann sbergman at redhat.com
Fri Aug 16 02:38:54 PDT 2013


I was trying out -fsanitizer=undefined on the LibreOffice code base 
(with a recent Clang trunk build), and ran into false positives claiming 
member calls were made on base class subobjects of wrong type.

Turns out LibreOffice is somewhat over-eager with -fvisibility=hidden, 
leading to some classes that are used across multiple dynamic libraries 
nevertheless having their RTTI name symbols bound locally per library. 
While that is in violation of the Itanium ABI, it at least works with 
recent libstdc++ (which resorts to strcmp rather than pointer comparison 
these days, see [1])---and wouldn't normally get noticed anyway as there 
should not be uses of dynamic_cast involving those classes in the 
LibreOffice code base.

Scenarios like this would easily be catered for in the ubsan code, by 
conservatively using strcmp rather than pointer comparison to determine 
type_info equality:

> Index: lib/ubsan/ubsan_type_hash.cc
> ===================================================================
> --- lib/ubsan/ubsan_type_hash.cc	(revision 188367)
> +++ lib/ubsan/ubsan_type_hash.cc	(working copy)
> @@ -13,6 +13,8 @@
>  //
>  //===----------------------------------------------------------------------===//
>
> +#include <cstring>
> +
>  #include "ubsan_type_hash.h"
>
>  #include "sanitizer_common/sanitizer_common.h"
> @@ -116,7 +118,7 @@
>  static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived,
>                                    const abi::__class_type_info *Base,
>                                    sptr Offset) {
> -  if (Derived->__type_name == Base->__type_name)
> +  if (std::strcmp(Derived->__type_name, Base->__type_name) == 0)
>      return Offset == 0;
>
>    if (const abi::__si_class_type_info *SI =

Stephan


For [1], see libstdc++-v3/libsupc++/typeinfo comment:

> // Determine whether typeinfo names for the same type are merged (in which
> // case comparison can just compare pointers) or not (in which case strings
> // must be compared), and whether comparison is to be implemented inline or
> // not.  We used to do inline pointer comparison by default if weak symbols
> // are available, but even with weak symbols sometimes names are not merged
> // when objects are loaded with RTLD_LOCAL, so now we always use strcmp by
> // default.  For ABI compatibility, we do the strcmp inline if weak symbols
> // are available, and out-of-line if not.  Out-of-line pointer comparison
> // is used where the object files are to be portable to multiple systems,
> // some of which may not be able to use pointer comparison, but the
> // particular system for which libstdc++ is being built can use pointer
> // comparison; in particular for most ARM EABI systems, where the ABI
> // specifies out-of-line comparison.  The compiler's target configuration
> // can override the defaults by defining __GXX_TYPEINFO_EQUALITY_INLINE to
> // 1 or 0 to indicate whether or not comparison is inline, and
> // __GXX_MERGED_TYPEINFO_NAMES to 1 or 0 to indicate whether or not pointer
> // comparison can be used.



More information about the cfe-commits mailing list