In perl.git, the branch blead has been updated

<https://perl5.git.perl.org/perl.git/commitdiff/f966a6e60c5062904734d261eea96ba070f47fdb?hp=a4eb0505c203b947fe64e98ace1af076f4c12153>

- Log -----------------------------------------------------------------
commit f966a6e60c5062904734d261eea96ba070f47fdb
Author: Karl Williamson <[email protected]>
Date:   Sat Feb 16 11:44:56 2019 -0700

    malloc.c: Limit malloc size to PTRDIFF_MAX
    
    Without doing this, it is possible that the behavior is undefined when
    subtracting two pointers that point to the same object.
    
    See thread beginning at
    http://nntp.perl.org/group/perl.perl5.porters/251541
    
    In particular this from Tomasz Konojacki
    
    C11 says:
    
    > When two pointers are subtracted, both shall point to elements of the
    > same array object, or one past the last element of the array object;
    > the result is the difference of the subscripts of the two array
    > elements. The size of the result is implementation-defined, and its
    > type (a signed integer type) is ptrdiff_t defined in the <stddef.h>
    > header.  If the result is not representable in an object of that type,
    > the behavior is undefined.
    
    There are many ways to interpret this passage, but according to (most?)
    C compilers developers, it means that no object can be larger than
    PTRDIFF_MAX. For example, gcc's optimizer assummes that strlen() will
    never return anything larger than PTRDIFF_MAX [1].
    
    There's also a blogpost[2] on this topic, which IMO is a very
    interesting read.
    
    If gcc and clang can assume that all objects won't be larger than
    PTRDIFF_MAX, so can we. Also, in practice, ssize_t and ptrdiff_t on most
    (all?) platforms are defined as exactly the same type.
    
    BTW, the fact that compilers assume that objects can't be larger than
    PTRDIFF_MAX has very dangerous implications on 32-bit platforms. Is it
    possible to create string longer than PTRDIFF_MAX on 32-bit perls?. It
    shouldn't be allowed.
    
    [1] - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78153
    [2] - https://trust-in-soft.com/objects-larger-than-ptrdiff_max-bytes/

-----------------------------------------------------------------------

Summary of changes:
 malloc.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/malloc.c b/malloc.c
index 53835e1f47..72cf2cd307 100644
--- a/malloc.c
+++ b/malloc.c
@@ -1230,6 +1230,18 @@ Perl_malloc(size_t nbytes)
        union overhead *p;
        int bucket;
 
+        /* A structure that has more than PTRDIFF_MAX bytes is unfortunately
+         * legal in C, but in such, if two elements are far enough apart, we
+         * can't legally find out how far apart they are.  Limit the size of a
+         * malloc so that pointer subtraction in the same structure is always
+         * well defined */
+        if (nbytes > PTRDIFF_MAX) {
+            MYMALLOC_WRITE2STDERR("Memory requests are limited to PTRDIFF_MAX"
+                                  " bytes to prevent possible undefined"
+                                  " behavior");
+            return NULL;
+        }
+
 #if defined(DEBUGGING) || defined(RCHECK)
        MEM_SIZE size = nbytes;
 #endif

-- 
Perl5 Master Repository

Reply via email to