Jeroen Demeyer on Tue, 04 Oct 2016 16:50:29 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

is_universal_constant() assumes that gen_0 <= ghalf


Dear PARI developers,

Consider src/headers/pariinl.h which has
INLINE int
is_universal_constant(GEN x) { return (x >= gen_0 && x <= ghalf); }

This does not work correctly because the pointers gen_0 and ghalf come from two arrays: In src/language/init.c, there is one array for all constants except ghalf and one array for ghalf. How these arrays are layed out in memory is undefined behaviour. On Cygwin at least, it can happen that ghalf < gen_0 (with certain compilers and compiler flags) such that is_universal_constant(x) is always false. This leads to breakage in the Sage interface, involving closures returning gnil.

The obvious fix is to ensure that all constants come from the same array, see attached patch.


Cheers,
Jeroen
>From f5eb24c73bb0ccd1704754b7b837a84a11bb2c6c Mon Sep 17 00:00:00 2001
From: Jeroen Demeyer <jdemeyer@cage.ugent.be>
Date: Tue, 4 Oct 2016 16:44:05 +0200
Subject: [PATCH] Ensure that all constants come from the same array

This is needed to fix undefined behaviour in is_universal_constant()
---
 src/language/init.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/language/init.c b/src/language/init.c
index 90a3918..d403f35 100644
--- a/src/language/init.c
+++ b/src/language/init.c
@@ -78,8 +78,6 @@ static const ulong readonly_constants[] = {
   evaltyp(t_INT) | _evallg(3),  /* gen_m2 */
   evalsigne(-1) | evallgefint(3),
   2,
-};
-static const long readonly_ghalf[] = {
   evaltyp(t_FRAC) | _evallg(3), /* ghalf */
   (long)(readonly_constants+4),
   (long)(readonly_constants+7)
@@ -496,7 +494,7 @@ init_universal_constants(void)
   gen_2  = (GEN)readonly_constants+7;
   gen_m1 = (GEN)readonly_constants+10;
   gen_m2 = (GEN)readonly_constants+13;
-  ghalf  = (GEN)readonly_ghalf;
+  ghalf  = (GEN)readonly_constants+16;
   err_e_STACK = (GEN)readonly_err_STACK;
 }
 
-- 
2.7.3