Opened 8 years ago
Closed 6 years ago
#12266 closed defect (fixed)
3^3^3^3 segfaults
Reported by: | vbraun | Owned by: | jason, jkantor |
---|---|---|---|
Priority: | major | Milestone: | sage-duplicate/invalid/wontfix |
Component: | c_lib | Keywords: | |
Cc: | Merged in: | ||
Authors: | Reviewers: | Jeroen Demeyer | |
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description
As reported on http://ask.sagemath.org/question/1031/segmentation-fault-when-evaluating-3333:
sage: 3^3^3^3 --------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) /home/vbraun/<ipython console> in <module>() /home/vbraun/opt/sage-4.8.alpha6/local/lib/python2.6/site-packages/sage/rings/integer.so in sage.rings.integer.Integer.__pow__ (sage/rings/integer.c:12867)() RuntimeError: Segmentation fault
Debugger shows that we call gmp_n_pow_ui
on a non-int:
(gdb) bt #0 0x00007fffed883c14 in __gmp_tmp_reentrant_alloc () from /home/vbraun/opt/sage-4.8.alpha6/local/lib/libgmp.so.8 #1 0x00007fffed897754 in __gmpz_n_pow_ui () from /home/vbraun/opt/sage-4.8.alpha6/local/lib/libgmp.so.8 #2 0x00007fffe75fbce7 in __pyx_pf_4sage_5rings_7integer_7Integer_36__pow__ (__pyx_v_self=0x3e8fe70, __pyx_v_n=0x3e8fbd0, __pyx_v_modulus=<optimized out>) at sage/rings/integer.c:12881 #3 0x00007ffff7c85fe2 in ternary_op (v=0x3e8fe70, w=0x3e8fbd0, z=0x7ffff7fc92a0, op_slot=48, op_name=Unhandled dwarf expression opcode 0xfa
Change History (6)
comment:1 Changed 7 years ago by
comment:2 Changed 7 years ago by
A remark from Bill Hart about what is going on:
Hi William, It appears to eventually call __gmp_tmp_reentrant_alloc. Here is that function: __gmp_tmp_reentrant_alloc (struct tmp_reentrant_t **markp, size_t size) { char *p; size_t total_size; #define P ((struct tmp_reentrant_t *) p) total_size = size + HSIZ; p = (*__gmp_allocate_func) (total_size); P->size = total_size; P->next = *markp; *markp = P; return p + HSIZ; } As you can see, there is no state stored here. It merely calls __gmp_allocate_func. Here is that latter function: void * (*__gmp_allocate_func) _PROTO ((size_t)) = __gmp_default_allocate; void * __gmp_default_allocate (size_t size) { void *ret; #ifdef DEBUG size_t req_size = size; size += 2 * BYTES_PER_MP_LIMB; #endif ret = malloc (size); if (ret == 0) { #if defined _MSC_VER && defined _WIN64 fprintf (stderr, "GNU MP: Cannot allocate memory (size=%llu)\n", size); #else fprintf (stderr, "GNU MP: Cannot allocate memory (size=%u)\n", size); #endif abort (); } #ifdef DEBUG { mp_ptr p = ret; p++; p[-1] = (0xdeadbeef << 31) + 0xdeafdeed; if (req_size % BYTES_PER_MP_LIMB == 0) p[req_size / BYTES_PER_MP_LIMB] = ~((0xdeadbeef << 31) + 0xdeafdeed); ret = p; } #endif return ret; } As you can see, it is just a simple call to malloc, plus an abort if malloc fails. So I don't think this is a problem in MPIR, unless MPIR is being built in malloc-notreentrant mode (note that alloca or malloc-reentrant is the default). So I don't know what you mean by "properly dealing with this sort of thing". Did you have something particular in mind?
comment:3 Changed 6 years ago by
- Milestone changed from sage-5.11 to sage-5.12
comment:4 Changed 6 years ago by
- Component changed from numerical to c_lib
- Milestone changed from sage-6.1 to sage-duplicate/invalid/wontfix
- Reviewers set to Jeroen Demeyer
- Status changed from new to needs_review
Fixed by #15363.
comment:5 Changed 6 years ago by
- Status changed from needs_review to positive_review
comment:6 Changed 6 years ago by
- Resolution set to fixed
- Status changed from positive_review to closed
Note: See
TracTickets for help on using
tickets.
It is incorrect to say that this "segfaults". In fact, the relevant code is this from integer.pyx:
What happens is that MPIR can't allocate memory for the answer, this causes a signal, and Sage properly catches the signal. The Sage process does not crash the first time around. But things get left in a screwed up state, so that subsequence calls can totally crash Sage.
On 64-bit OS X I have to use this input to cause the problem:
It would be nice if a MemoryError? is raised instead of a RuntimeError?, of course. I don't know how to put MPIR back in a clean state after this error occurs though. This on OS X:
I don't know if MPIR even provides a way of properly dealing with this sort of thing.