[libcxx] r220702 - PR #21321 talked about implementation-defined behavior of realloc. I poo-poohed it, and was wrong. Fix the call in <locale>. Review the others, refactored some duplicated code, and found overflow bugs (and __event_cap_ was never getting updated, either).

Marshall Clow mclow.lists at gmail.com
Mon Oct 27 12:08:10 PDT 2014


Author: marshall
Date: Mon Oct 27 14:08:10 2014
New Revision: 220702

URL: http://llvm.org/viewvc/llvm-project?rev=220702&view=rev
Log:
PR #21321 talked about implementation-defined behavior of realloc. I poo-poohed it, and was wrong. Fix the call in <locale>. Review the others, refactored some duplicated code, and found overflow bugs (and __event_cap_ was never getting updated, either).

Modified:
    libcxx/trunk/include/locale
    libcxx/trunk/src/ios.cpp

Modified: libcxx/trunk/include/locale
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/locale?rev=220702&r1=220701&r2=220702&view=diff
==============================================================================
--- libcxx/trunk/include/locale (original)
+++ libcxx/trunk/include/locale Mon Oct 27 14:08:10 2014
@@ -2970,6 +2970,8 @@ __double_or_nothing(unique_ptr<_Tp, void
     size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
     size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
                        2 * __cur_cap : numeric_limits<size_t>::max();
+    if (__new_cap == 0)
+        __new_cap = sizeof(_Tp);
     size_t __n_off = static_cast<size_t>(__n - __b.get());
     _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
     if (__t == 0)

Modified: libcxx/trunk/src/ios.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/ios.cpp?rev=220702&r1=220701&r2=220702&view=diff
==============================================================================
--- libcxx/trunk/src/ios.cpp (original)
+++ libcxx/trunk/src/ios.cpp Mon Oct 27 14:08:10 2014
@@ -154,6 +154,16 @@ atomic<int> ios_base::__xindex_ = ATOMIC
 int ios_base::__xindex_ = 0;
 #endif
 
+template <typename _Tp>
+static size_t __ios_new_cap(size_t __req_size, size_t __current_cap)
+{ // Precondition: __req_size > __current_cap
+	const size_t mx = std::numeric_limits<size_t>::max() / sizeof(_Tp);
+	if (__req_size < mx/2)
+		return _VSTD::max(2 * __current_cap, __req_size);
+	else
+		return mx;
+}
+
 int
 ios_base::xalloc()
 {
@@ -166,14 +176,8 @@ ios_base::iword(int index)
     size_t req_size = static_cast<size_t>(index)+1;
     if (req_size > __iarray_cap_)
     {
-        size_t newcap;
-        const size_t mx = std::numeric_limits<size_t>::max();
-        if (req_size < mx/2)
-            newcap = _VSTD::max(2 * __iarray_cap_, req_size);
-        else
-            newcap = mx;
-        size_t newsize = newcap * sizeof(long);
-        long* iarray = static_cast<long*>(realloc(__iarray_, newsize));
+        size_t newcap = __ios_new_cap<long>(req_size, __iarray_cap_);
+        long* iarray = static_cast<long*>(realloc(__iarray_, newcap * sizeof(long)));
         if (iarray == 0)
         {
             setstate(badbit);
@@ -182,8 +186,9 @@ ios_base::iword(int index)
             return error;
         }
         __iarray_ = iarray;
-        for (long* p = __iarray_ + __iarray_size_; __iarray_cap_ < newcap; ++__iarray_cap_, ++p)
+        for (long* p = __iarray_ + __iarray_size_; p < __iarray_ + newcap; ++p)
             *p = 0;
+        __iarray_cap_ = newcap;
     }
     __iarray_size_ = max<size_t>(__iarray_size_, req_size);
     return __iarray_[index];
@@ -195,14 +200,8 @@ ios_base::pword(int index)
     size_t req_size = static_cast<size_t>(index)+1;
     if (req_size > __parray_cap_)
     {
-        size_t newcap;
-        const size_t mx = std::numeric_limits<size_t>::max();
-        if (req_size < mx/2)
-            newcap = _VSTD::max(2 * __parray_cap_, req_size);
-        else
-            newcap = mx;
-        size_t newsize = newcap * sizeof(void*);
-        void** parray = static_cast<void**>(realloc(__parray_, newsize));
+        size_t newcap = __ios_new_cap<void *>(req_size, __iarray_cap_);
+        void** parray = static_cast<void**>(realloc(__parray_, newcap * sizeof(void *)));
         if (parray == 0)
         {
             setstate(badbit);
@@ -211,8 +210,9 @@ ios_base::pword(int index)
             return error;
         }
         __parray_ = parray;
-        for (void** p = __parray_ + __parray_size_; __parray_cap_ < newcap; ++__parray_cap_, ++p)
+        for (void** p = __parray_ + __parray_size_; p < __parray_ + newcap; ++p)
             *p = 0;
+        __parray_cap_ = newcap;
     }
     __parray_size_ = max<size_t>(__parray_size_, req_size);
     return __parray_[index];
@@ -226,22 +226,16 @@ ios_base::register_callback(event_callba
     size_t req_size = __event_size_ + 1;
     if (req_size > __event_cap_)
     {
-        size_t newcap;
-        const size_t mx = std::numeric_limits<size_t>::max();
-        if (req_size < mx/2)
-            newcap = _VSTD::max(2 * __event_cap_, req_size);
-        else
-            newcap = mx;
-        size_t newesize = newcap * sizeof(event_callback);
-        event_callback* fns = static_cast<event_callback*>(realloc(__fn_, newesize));
+        size_t newcap = __ios_new_cap<event_callback>(req_size, __event_cap_);
+        event_callback* fns = static_cast<event_callback*>(realloc(__fn_, newcap * sizeof(event_callback)));
         if (fns == 0)
             setstate(badbit);
         __fn_ = fns;
-        size_t newisize = newcap * sizeof(int);
-        int* indxs = static_cast<int *>(realloc(__index_, newisize));
+        int* indxs = static_cast<int *>(realloc(__index_, newcap * sizeof(int)));
         if (indxs == 0)
             setstate(badbit);
         __index_ = indxs;
+        __event_cap_ = newcap;
     }
     __fn_[__event_size_] = fn;
     __index_[__event_size_] = index;





More information about the cfe-commits mailing list