Skip to content

Commit bf1bcb6

Browse files
arichardsonldionne
andcommitted
[libc++] Use intptr_t instead of ptrdiff_t for messages_base::catalog
On GLibc, FreeBSD and macOS systems nl_catd is a pointer type, and round-tripping this in a variable of ptrdiff_t is not portable. In fact such a round-trip yields a non-dereferenceable pointer on CHERI-enabled architectures such as Arm Morello. There pointers (and therefore intptr_t) are twice the size of ptrdiff_t, which means casting to ptrdiff_t strips the high (metadata) bits (as well as a hidden pointer validity bit). Since catalog is now guaranteed to be the same size or larger than nl_catd, we can store all return values safely and the shifting workaround from commit 0c68ed0 should not be needed anymore (this is also not portable to CHERI systems on since shifting a valid pointer right will create a massively out-of-bounds pointer that may not be representable). This can be fixed by using intptr_t which should be the same type as ptrdiff_t on all currently supported architectures. See also: https://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2028 Differential Revision: https://reviews.llvm.org/D134420 Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
1 parent dd5af89 commit bf1bcb6

File tree

2 files changed

+16
-15
lines changed

2 files changed

+16
-15
lines changed

libcxx/include/locale

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,7 +3455,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>;
34553455
class _LIBCPP_EXPORTED_FROM_ABI messages_base
34563456
{
34573457
public:
3458-
typedef ptrdiff_t catalog;
3458+
typedef intptr_t catalog;
34593459

34603460
_LIBCPP_INLINE_VISIBILITY messages_base() {}
34613461
};
@@ -3512,10 +3512,7 @@ typename messages<_CharT>::catalog
35123512
messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
35133513
{
35143514
#ifdef _LIBCPP_HAS_CATOPEN
3515-
catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
3516-
if (__cat != -1)
3517-
__cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3518-
return __cat;
3515+
return (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
35193516
#else // !_LIBCPP_HAS_CATOPEN
35203517
(void)__nm;
35213518
return -1;
@@ -3532,9 +3529,8 @@ messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
35323529
__narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(std::back_inserter(__ndflt),
35333530
__dflt.c_str(),
35343531
__dflt.c_str() + __dflt.size());
3535-
if (__c != -1)
3536-
__c <<= 1;
35373532
nl_catd __cat = (nl_catd)__c;
3533+
static_assert(sizeof(catalog) >= sizeof(nl_catd), "Unexpected nl_catd type");
35383534
char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
35393535
string_type __w;
35403536
__widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(std::back_inserter(__w),
@@ -3553,10 +3549,7 @@ void
35533549
messages<_CharT>::do_close(catalog __c) const
35543550
{
35553551
#ifdef _LIBCPP_HAS_CATOPEN
3556-
if (__c != -1)
3557-
__c <<= 1;
3558-
nl_catd __cat = (nl_catd)__c;
3559-
catclose(__cat);
3552+
catclose((nl_catd)__c);
35603553
#else // !_LIBCPP_HAS_CATOPEN
35613554
(void)__c;
35623555
#endif // _LIBCPP_HAS_CATOPEN

libcxx/test/std/localization/locale.categories/category.messages/locale.messages/messages_base.pass.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,22 @@
1414
// typedef unspecified catalog;
1515
// };
1616

17+
#include <cstdint>
1718
#include <locale>
1819
#include <type_traits>
1920

20-
#include "test_macros.h"
21+
#include "assert_macros.h"
2122

22-
int main(int, char**)
23-
{
24-
std::messages_base mb;
23+
#ifdef _LIBCPP_VERSION
24+
ASSERT_SAME_TYPE(std::messages_base::catalog, std::intptr_t);
25+
#endif
26+
27+
// Check that we implement LWG2028
28+
static_assert(std::is_signed<std::messages_base::catalog>::value, "");
29+
static_assert(std::is_integral<std::messages_base::catalog>::value, "");
30+
31+
int main(int, char**) {
32+
std::messages_base mb;
2533

2634
return 0;
2735
}

0 commit comments

Comments
 (0)