Skip to content

Commit

Permalink
GMP: New version 6.3.0 (#7872)
Browse files Browse the repository at this point in the history
* GMP: New version 6.3.0

* GMP: Don't use clang_use_lld

* GMP: Update patches

* GMP: Update patches for overflow handling

* [GMP] Make copy of files verbose, to ease debugging

---------

Co-authored-by: Mosè Giordano <[email protected]>
  • Loading branch information
eschnett and giordano authored Jan 27, 2024
1 parent 386a0f8 commit 622d39e
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 6 deletions.
9 changes: 9 additions & 0 deletions G/GMP/[email protected]/build_tarballs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version = v"6.3.0"

llvm_version = v"13.0.1"

include("../common.jl")

# Build the tarballs!
build_tarballs(ARGS, configure(version, llvm_version)...;
clang_use_lld=false, julia_compat="1.6", preferred_gcc_version=v"6", preferred_llvm_version=llvm_version)
10 changes: 10 additions & 0 deletions G/GMP/[email protected]/bundled/patches/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Julia applies a patch to GMP that handles "overflow" (out of memory)
via a callback function. GMP 6.3.0 introduced its own mechanism to
handle overflows via an error code.

Since Julia Base calls `__gmp_set_alloc_overflow_function` I
(@eschnett) chose to overwrite the changes to GMP that now handle
overflow in favour of the old mechanism introduced via Julia's
patches. The main reasons are: (a) this works for Julia right away (no
changes to Base necessary), and (b) Julia's patches handle more cases,
i.e. more places where an overflow can occur.
206 changes: 206 additions & 0 deletions G/GMP/[email protected]/bundled/patches/gmp-alloc_overflow.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
diff -ru gmp-6.3.0/gmp-h.in gmp-6.3.0.new/gmp-h.in
--- gmp-6.3.0/gmp-h.in 2023-07-29 09:42:16
+++ gmp-6.3.0.new/gmp-h.in 2023-12-29 15:33:34
@@ -487,6 +487,12 @@
void *(**) (void *, size_t, size_t),
void (**) (void *, size_t)) __GMP_NOTHROW;

+#define mp_set_alloc_overflow_function __gmp_set_alloc_overflow_function
+__GMP_DECLSPEC void mp_set_alloc_overflow_function (void (*) (void)) __GMP_NOTHROW;
+
+#define mp_get_alloc_overflow_function __gmp_get_alloc_overflow_function
+__GMP_DECLSPEC void mp_get_alloc_overflow_function (void (**) (void)) __GMP_NOTHROW;
+
#define mp_bits_per_limb __gmp_bits_per_limb
__GMP_DECLSPEC extern const int mp_bits_per_limb;

diff -ru gmp-6.3.0/gmp-impl.h gmp-6.3.0.new/gmp-impl.h
--- gmp-6.3.0/gmp-impl.h 2023-07-29 09:42:16
+++ gmp-6.3.0.new/gmp-impl.h 2023-12-30 16:02:36
@@ -58,6 +58,8 @@
short can be 24, 32, 46 or 64 bits, and different for ushort. */

#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>

/* For fat.h and other fat binary stuff.
No need for __GMP_ATTRIBUTE_PURE or __GMP_NOTHROW, since functions
@@ -699,14 +701,22 @@
__GMP_DECLSPEC extern void * (*__gmp_allocate_func) (size_t);
__GMP_DECLSPEC extern void * (*__gmp_reallocate_func) (void *, size_t, size_t);
__GMP_DECLSPEC extern void (*__gmp_free_func) (void *, size_t);
+__GMP_DECLSPEC extern void (*__gmp_alloc_overflow_func)(void);

__GMP_DECLSPEC void *__gmp_default_allocate (size_t);
__GMP_DECLSPEC void *__gmp_default_reallocate (void *, size_t, size_t);
__GMP_DECLSPEC void __gmp_default_free (void *, size_t);
+__GMP_DECLSPEC void __gmp_default_alloc_overflow (void);

#define __GMP_ALLOCATE_FUNC_TYPE(n,type) \
((type *) (*__gmp_allocate_func) ((n) * sizeof (type)))
#define __GMP_ALLOCATE_FUNC_LIMBS(n) __GMP_ALLOCATE_FUNC_TYPE (n, mp_limb_t)
+#define __GMP_ALLOC_OVERFLOW_FUNC() \
+ do { \
+ (*__gmp_alloc_overflow_func) (); \
+ fprintf (stderr, "unexpected return from alloc_overflow\n"); \
+ abort (); \
+ } while (0)

#define __GMP_REALLOCATE_FUNC_TYPE(p, old_size, new_size, type) \
((type *) (*__gmp_reallocate_func) \
diff -ru gmp-6.3.0/memory.c gmp-6.3.0.new/memory.c
--- gmp-6.3.0/memory.c 2023-07-29 09:42:16
+++ gmp-6.3.0.new/memory.c 2023-12-29 15:43:27
@@ -37,6 +37,7 @@
void * (*__gmp_allocate_func) (size_t) = __gmp_default_allocate;
void * (*__gmp_reallocate_func) (void *, size_t, size_t) = __gmp_default_reallocate;
void (*__gmp_free_func) (void *, size_t) = __gmp_default_free;
+void (*__gmp_alloc_overflow_func) (void) = __gmp_default_alloc_overflow;


/* Default allocation functions. In case of failure to allocate/reallocate
@@ -142,4 +143,11 @@
}
#endif
free (blk_ptr);
+}
+
+void
+__gmp_default_alloc_overflow(void)
+{
+ fprintf (stderr, "gmp: overflow in mpz type\n");
+ abort();
}
diff -ru gmp-6.3.0/mp_get_fns.c gmp-6.3.0.new/mp_get_fns.c
--- gmp-6.3.0/mp_get_fns.c 2023-07-29 09:42:16
+++ gmp-6.3.0.new/mp_get_fns.c 2023-12-29 15:43:27
@@ -45,3 +45,11 @@
if (free_func != NULL)
*free_func = __gmp_free_func;
}
+
+void
+mp_get_alloc_overflow_function(
+ void (**alloc_overflow_func) (void)) __GMP_NOTHROW
+{
+ if (alloc_overflow_func != NULL)
+ *alloc_overflow_func = __gmp_alloc_overflow_func;
+}
diff -ru gmp-6.3.0/mp_set_fns.c gmp-6.3.0.new/mp_set_fns.c
--- gmp-6.3.0/mp_set_fns.c 2023-07-29 09:42:16
+++ gmp-6.3.0.new/mp_set_fns.c 2023-12-29 15:43:27
@@ -47,3 +47,12 @@
__gmp_reallocate_func = realloc_func;
__gmp_free_func = free_func;
}
+
+void
+mp_set_alloc_overflow_function(
+ void (*alloc_overflow_func) (void)) __GMP_NOTHROW
+{
+ if (alloc_overflow_func == 0)
+ alloc_overflow_func = __gmp_default_alloc_overflow;
+ __gmp_alloc_overflow_func = alloc_overflow_func;
+}
diff -ru gmp-6.3.0/mpz/init2.c gmp-6.3.0.new/mpz/init2.c
--- gmp-6.3.0/mpz/init2.c 2023-07-29 09:42:17
+++ gmp-6.3.0.new/mpz/init2.c 2023-12-30 12:22:34
@@ -41,7 +41,7 @@
if (sizeof (unsigned long) > sizeof (int)) /* param vs _mp_size field */
{
if (UNLIKELY (new_alloc > INT_MAX))
- MPZ_OVERFLOW;
+ __GMP_ALLOC_OVERFLOW_FUNC ();
}

PTR(x) = __GMP_ALLOCATE_FUNC_LIMBS (new_alloc);
diff -ru gmp-6.3.0/mpz/realloc.c gmp-6.3.0.new/mpz/realloc.c
--- gmp-6.3.0/mpz/realloc.c 2023-07-29 09:42:17
+++ gmp-6.3.0.new/mpz/realloc.c 2023-12-30 12:22:47
@@ -42,12 +42,12 @@
if (sizeof (mp_size_t) == sizeof (int))
{
if (UNLIKELY (new_alloc > ULONG_MAX / GMP_NUMB_BITS))
- MPZ_OVERFLOW;
+ __GMP_ALLOC_OVERFLOW_FUNC ();
}
else
{
if (UNLIKELY (new_alloc > INT_MAX))
- MPZ_OVERFLOW;
+ __GMP_ALLOC_OVERFLOW_FUNC ();
}

if (ALLOC (m) == 0)
diff -ru gmp-6.3.0/mpz/realloc2.c gmp-6.3.0.new/mpz/realloc2.c
--- gmp-6.3.0/mpz/realloc2.c 2023-07-29 09:42:17
+++ gmp-6.3.0.new/mpz/realloc2.c 2023-12-30 12:22:59
@@ -42,7 +42,7 @@
if (sizeof (unsigned long) > sizeof (int)) /* param vs _mp_size field */
{
if (UNLIKELY (new_alloc > INT_MAX))
- MPZ_OVERFLOW;
+ __GMP_ALLOC_OVERFLOW_FUNC ();
}

if (ALLOC (m) == 0)
diff -ru gmp-6.3.0/tal-reent.c gmp-6.3.0.new/tal-reent.c
--- gmp-6.3.0/tal-reent.c 2023-07-29 09:42:17
+++ gmp-6.3.0.new/tal-reent.c 2023-12-30 12:19:40
@@ -61,6 +61,10 @@

total_size = size + HSIZ;
p = __GMP_ALLOCATE_FUNC_TYPE (total_size, char);
+ if (!p)
+ {
+ __GMP_ALLOC_OVERFLOW_FUNC ();
+ }
P->size = total_size;
P->next = *markp;
*markp = P;
diff -ru gmp-6.3.0/tests/mpz/t-pow.c gmp-6.3.0.new/tests/mpz/t-pow.c
--- gmp-6.3.0/tests/mpz/t-pow.c 2023-07-29 09:42:17
+++ gmp-6.3.0.new/tests/mpz/t-pow.c 2023-12-30 15:57:58
@@ -194,6 +194,33 @@
mpz_clear (want);
}

+jmp_buf env;
+
+void
+alloc_overflow_handler (void)
+{
+ longjmp(env, 1);
+}
+
+void
+check_overflow (void)
+{
+ mpz_t x;
+ mpz_init (x);
+ int overflow_intercepted = 0;
+ if (setjmp (env) == 0) {
+ mp_set_alloc_overflow_function (&alloc_overflow_handler);
+ mpz_ui_pow_ui (x, 3, 7625597484987LL);
+ } else {
+ ++overflow_intercepted;
+ }
+ if (overflow_intercepted != 1) {
+ printf ("overflow not intercepted\n");
+ abort ();
+ }
+ mpz_clear (x);
+}
+
int
main (int argc, char **argv)
{
@@ -211,6 +238,7 @@

check_various ();
check_random (reps);
+ check_overflow ();

tests_end ();
exit (0);
13 changes: 7 additions & 6 deletions G/GMP/common.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using BinaryBuilder
using BinaryBuilder, Pkg
using BinaryBuilderBase: sanitize

function configure(version)
function configure(version, llvm_version)
name = "GMP"

hash = Dict(
v"6.1.2" => "5275bb04f4863a13516b2f39392ac5e272f5e1bb8057b18aec1c9b79d73d8fb2",
v"6.2.0" => "f51c99cb114deb21a60075ffb494c1a210eb9d7cb729ed042ddb7de9534451ea",
v"6.2.1" => "eae9326beb4158c386e39a356818031bd28f3124cf915f8c5b1dc4c7a36b4d7c",
v"6.3.0" => "ac28211a7cfb609bae2e2c8d6058d66c8fe96434f740cf6fe2e47b000d1c20cb",
)

# Collection of sources required to complete build
Expand Down Expand Up @@ -37,7 +38,7 @@ fi
if [[ ${bb_full_target} == *-sanitize+memory* ]]; then
# Install msan runtime (for clang)
cp -rL ${libdir}/linux/* /opt/x86_64-linux-musl/lib/clang/*/lib/linux/
cp -vrL ${libdir}/linux/* /opt/x86_64-linux-musl/lib/clang/*/lib/linux/
fi
autoreconf
./configure --prefix=$prefix --build=${MACHTYPE} --host=${target} ${flags[@]}
Expand All @@ -55,20 +56,20 @@ fi
install_license COPYING*
"""

# We enable experimental platforms as this is a core Julia dependency
platforms = supported_platforms()
push!(platforms, Platform("x86_64", "linux"; sanitize="memory"))
platforms = expand_cxxstring_abis(platforms)

products = [
LibraryProduct("libgmp", :libgmp),
LibraryProduct("libgmpxx", :libgmpxx),
]

# Dependencies that must be installed before this package can be built
dependencies = [
BuildDependency("LLVMCompilerRT_jll", platforms=filter(p -> sanitize(p)=="memory", platforms)),
BuildDependency(PackageSpec(name="LLVMCompilerRT_jll", uuid="4e17d02c-6bf5-513e-be62-445f41c75a11", version=llvm_version);
platforms=filter(p -> sanitize(p)=="memory", platforms)),
]

return name, version, sources, script, platforms, products, dependencies
end

0 comments on commit 622d39e

Please sign in to comment.