]> granicus.if.org Git - php/commitdiff
Expose zend_safe_address() and use it in zend_arena_calloc()
authorDmitry Stogov <dmitry@zend.com>
Thu, 18 Sep 2014 09:31:25 +0000 (13:31 +0400)
committerDmitry Stogov <dmitry@zend.com>
Thu, 18 Sep 2014 09:31:25 +0000 (13:31 +0400)
Zend/zend_alloc.c
Zend/zend_arena.h
Zend/zend_multiply.h

index 8b6a105e98087fcdeba38516f3e5e4589859cb47..751497978ae368857d8580e75fba9ca99c1402a7 100644 (file)
@@ -57,6 +57,7 @@
 #include "zend_alloc.h"
 #include "zend_globals.h"
 #include "zend_operators.h"
+#include "zend_multiply.h"
 
 #ifdef HAVE_SIGNAL_H
 # include <signal.h>
@@ -2121,124 +2122,17 @@ ZEND_API size_t ZEND_FASTCALL _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE
        return zend_mm_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
 }
 
-#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
-
-static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
+static zend_always_inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
 {
-       size_t res = nmemb;
-       zend_ulong overflow = 0;
-
-       __asm__ ("mull %3\n\taddl %4,%0\n\tadcl $0,%1"
-            : "=&a"(res), "=&d" (overflow)
-            : "%0"(res),
-              "rm"(size),
-              "rm"(offset));
+       int overflow;
+       size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
 
        if (UNEXPECTED(overflow)) {
                zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
                return 0;
        }
-       return res;
-}
-
-#elif defined(__GNUC__) && defined(__x86_64__)
-
-static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
-{
-        size_t res = nmemb;
-        zend_ulong overflow = 0;
-
-#ifdef __ILP32__ /* x32 */
-# define LP_SUFF "l"
-#else /* amd64 */
-# define LP_SUFF "q"
-#endif
-
-        __asm__ ("mul" LP_SUFF  " %3\n\t"
-                 "add %4,%0\n\t"
-                 "adc $0,%1"
-             : "=&a"(res), "=&d" (overflow)
-             : "%0"(res),
-               "rm"(size),
-               "rm"(offset));
-
-#undef LP_SUFF
-        if (UNEXPECTED(overflow)) {
-                zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
-                return 0;
-        }
-        return res;
-}
-
-#elif defined(__GNUC__) && defined(__arm__)
-
-static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
-{
-        size_t res;
-        zend_ulong overflow;
-
-        __asm__ ("umlal %0,%1,%2,%3"
-             : "=r"(res), "=r"(overflow)
-             : "r"(nmemb),
-               "r"(size),
-               "0"(offset),
-               "1"(0));
-
-        if (UNEXPECTED(overflow)) {
-                zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
-                return 0;
-        }
-        return res;
-}
-
-#elif defined(__GNUC__) && defined(__aarch64__)
-
-static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
-{
-        size_t res;
-        zend_ulong overflow;
-
-        __asm__ ("mul %0,%2,%3\n\tumulh %1,%2,%3\n\tadds %0,%0,%4\n\tadc %1,%1,xzr"
-             : "=&r"(res), "=&r"(overflow)
-             : "r"(nmemb),
-               "r"(size),
-               "r"(offset));
-
-        if (UNEXPECTED(overflow)) {
-                zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
-                return 0;
-        }
-        return res;
-}
-
-#elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64)
-
-static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
-{
-       zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
-
-       if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
-               zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
-               return 0;
-       }
-       return (size_t) res;
-}
-
-#else
-
-static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
-{
-       size_t res = nmemb * size + offset;
-       double _d  = (double)nmemb * (double)size + (double)offset;
-       double _delta = (double)res - _d;
-
-       if (UNEXPECTED((_d + _delta ) != _d)) {
-               zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
-               return 0;
-       }
-       return res;
+       return ret;
 }
-#endif
 
 
 ZEND_API void* ZEND_FASTCALL _safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
index 96e18a6910da478d68a3c23f7bf850fdf4cf688c..64fde196199b71032371eb2ec88f7984d1862903 100644 (file)
@@ -80,14 +80,14 @@ static zend_always_inline void* zend_arena_alloc(zend_arena **arena_ptr, size_t
 
 static zend_always_inline void* zend_arena_calloc(zend_arena **arena_ptr, size_t count, size_t unit_size)
 {
-       zend_long overflow;
-       double d;
+       int overflow;
        size_t size;
        void *ret;
 
-       (void)d;
-       ZEND_SIGNED_MULTIPLY_LONG(unit_size, count, size, d, overflow);
-       ZEND_ASSERT(overflow == 0);
+       size = zend_safe_address(unit_size, count, 0, &overflow);
+       if (UNEXPECTED(overflow)) {
+               zend_error(E_ERROR, "Possible integer overflow in zend_arena_calloc() (%zu * %zu)", unit_size, count);
+       }
        ret = zend_arena_alloc(arena_ptr, size);
        memset(ret, 0, size);
        return ret;
index 11744c2699f10faa469f9eb75d4d7c384f542b84..158be22007575a1414354b0d5e39aa6361fd792a 100644 (file)
@@ -19,6 +19,9 @@
 
 /* $Id$ */
 
+#ifndef ZEND_MULTIPLY_H
+#define ZEND_MULTIPLY_H
+
 #if defined(__i386__) && defined(__GNUC__)
 
 #define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do {      \
 } while (0)
 
 #endif
+
+#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
+
+static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, int *overflow)
+{
+       size_t res = nmemb;
+       zend_ulong m_overflow = 0;
+
+       __asm__ ("mull %3\n\taddl %4,%0\n\tadcl $0,%1"
+            : "=&a"(res), "=&d" (m_overflow)
+            : "%0"(res),
+              "rm"(size),
+              "rm"(offset));
+
+       if (UNEXPECTED(m_overflow)) {
+               *overflow = 1;
+               return 0;
+       }
+       *overflow = 0;
+       return res;
+}
+
+#elif defined(__GNUC__) && defined(__x86_64__)
+
+static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, int *overflow)
+{
+       size_t res = nmemb;
+       zend_ulong m_overflow = 0;
+
+#ifdef __ILP32__ /* x32 */
+# define LP_SUFF "l"
+#else /* amd64 */
+# define LP_SUFF "q"
+#endif
+
+       __asm__ ("mul" LP_SUFF  " %3\n\t"
+               "add %4,%0\n\t"
+               "adc $0,%1"
+               : "=&a"(res), "=&d" (m_overflow)
+               : "%0"(res),
+                 "rm"(size),
+                 "rm"(offset));
+
+#undef LP_SUFF
+       if (UNEXPECTED(m_overflow)) {
+               *overflow = 1;
+               return 0;
+       }
+       *overflow = 0;
+       return res;
+}
+
+#elif defined(__GNUC__) && defined(__arm__)
+
+static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, int *overflow)
+{
+       size_t res;
+       zend_ulong m_overflow;
+
+       __asm__ ("umlal %0,%1,%2,%3"
+               : "=r"(res), "=r"(m_overflow)
+               : "r"(nmemb),
+                 "r"(size),
+                 "0"(offset),
+                 "1"(0));
+
+       if (UNEXPECTED(m_overflow)) {
+               *overflow = 1;
+               return 0;
+       }
+       *overflow = 0;
+       return res;
+}
+
+#elif defined(__GNUC__) && defined(__aarch64__)
+
+static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, int *overflow)
+{
+       size_t res;
+       zend_ulong m_overflow;
+
+       __asm__ ("mul %0,%2,%3\n\tumulh %1,%2,%3\n\tadds %0,%0,%4\n\tadc %1,%1,xzr"
+               : "=&r"(res), "=&r"(m_overflow)
+               : "r"(nmemb),
+                 "r"(size),
+                 "r"(offset));
+
+       if (UNEXPECTED(m_overflow)) {
+               *overflow = 1;
+               return 0;
+       }
+       *overflow = 0;
+       return res;
+}
+
+#elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64)
+
+static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, int *overflow)
+{
+       zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
+
+       if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
+               *overflow = 1;
+               return 0;
+       }
+       *overflow = 0;
+       return (size_t) res;
+}
+
+#else
+
+static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, int *overflow)
+{
+       size_t res = nmemb * size + offset;
+       double _d  = (double)nmemb * (double)size + (double)offset;
+       double _delta = (double)res - _d;
+
+       if (UNEXPECTED((_d + _delta ) != _d)) {
+               *overflow = 1;
+               return 0;
+       }
+       *overflow = 0;
+       return res;
+}
+#endif
+
+#endif /* ZEND_MULTIPLY_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */