#13731: Fix libsingular memory management
--------------------------------------------------------------+-------------
       Reporter:  nbruin                                      |         Owner:  
rlm         
           Type:  defect                                      |        Status:  
needs_review
       Priority:  major                                       |     Milestone:  
sage-5.6    
      Component:  memleak                                     |    Resolution:  
            
       Keywords:                                              |   Work issues:  
            
Report Upstream:  Fixed upstream, in a later stable release.  |     Reviewers:  
            
        Authors:  Nils Bruin, Simon King                      |     Merged in:  
            
   Dependencies:                                              |      Stopgaps:  
            
--------------------------------------------------------------+-------------

Comment (by nbruin):

 Valgrind gives suspicious records for two of these tests:

 `sage -t --valgrind "devel/sage/sage/schemes/toric/fano_variety.py"`

 {{{
 ==20768== Syscall param open(filename) points to unaddressable byte(s)
 ==20768==    at 0x31CFEE41F0: __open_nocancel (in /lib64/libc-2.14.90.so)
 ==20768==    by 0x31CFE79508: _IO_file_fopen@@GLIBC_2.2.5 (in
 /lib64/libc-2.14.90.so)
 ==20768==    by 0x31CFE6E265: __fopen_internal (in /lib64/libc-2.14.90.so)
 ==20768==    by 0x31D6275A06: std::__basic_file<char>::open(char const*,
 std::_Ios_Openmode, int) (in /usr/lib64/libstdc++.so.6.0.16)
 ==20768==    by 0x31D627947B: std::basic_filebuf<char,
 std::char_traits<char> >::open(char const*, std::_Ios_Openmode) (in
 /usr/lib64/libstdc++.so.6.0.16)
 ==20768==    by 0x31D627A9D2: std::basic_ofstream<char,
 std::char_traits<char> >::basic_ofstream(char const*, std::_Ios_Openmode)
 (in /usr/lib64/libstdc++.so.6.0.16)
 ==20768==    by 0x2D69E6E2: LinBox::commentator() (commentator.h:857)
 ==20768==    by 0x2D7BF15E: unsigned long&
 LinBox::rank<LinBox::BlasMatrix<LinBox::PID_integer>,
 LinBox::HybridSpecifier>(unsigned long&,
 LinBox::BlasMatrix<LinBox::PID_integer> const&,
 LinBox::RingCategories::IntegerTag const&, LinBox::HybridSpecifier const&)
 (rank.h:629)
 ==20768==    by 0x2D6A864C: linbox_integer_dense_rank(__mpz_struct (**)
 [1], unsigned long, unsigned long) (rank.h:110)
 ==20768==    by 0x2B4B25FC:
 
__pyx_pf_4sage_6matrix_20matrix_integer_dense_20Matrix_integer_dense_100_rank_linbox
 (matrix_integer_dense.c:25464)
 ==20768==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==20768==    by 0x2B4BFC5E:
 __pyx_pw_4sage_6matrix_20matrix_integer_dense_20Matrix_integer_dense_99rank
 (matrix_integer_dense.c:25357)
 ==20768==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==20768==    by 0x2BB90582:
 __pyx_pw_4sage_6matrix_21matrix_rational_dense_21Matrix_rational_dense_83rank
 (matrix_rational_dense.c:21989)
 ==20768==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==20768==    by 0x2973737D:
 __pyx_pw_4sage_6matrix_7matrix2_6Matrix_7solve_right (matrix2.c:4604)
 ==20768==    by 0x4CFC624: PyEval_EvalFrameEx (ceval.c:4021)
 ==20768==    by 0x4CFE274: PyEval_EvalCodeEx (ceval.c:3253)
 ==20768==    by 0x4CFC69F: PyEval_EvalFrameEx (ceval.c:4117)
 ==20768==    by 0x4CFE274: PyEval_EvalCodeEx (ceval.c:3253)
 ==20768==    by 0x4CFC69F: PyEval_EvalFrameEx (ceval.c:4117)
 ==20768==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
 }}}
 I don't know how serious it is to call open with a zero pointer. Probably
 not at all...


 `sage -t  "devel/sage/sage/schemes/toric/library.py"`:
 {{{
 ==21248== Invalid read of size 8
 ==21248==    at 0x3432C24F:
 __pyx_f_4sage_9functions_8prime_pi_7PrimePi_prime_phi_small
 (prime_pi.c:2190)
 ==21248==    by 0x3432A937:
 __pyx_f_4sage_9functions_8prime_pi_7PrimePi_prime_phi_large
 (prime_pi.c:1624)
 ==21248==    by 0x3432B349:
 __pyx_pf_4sage_9functions_8prime_pi_7PrimePi_4__call__ (prime_pi.c:1489)
 ==21248==    by 0x3432BBBC:
 __pyx_pw_4sage_9functions_8prime_pi_7PrimePi_5__call__ (prime_pi.c:1202)
 ==21248==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==21248==    by 0x2ADCA63A:
 __pyx_pw_4sage_3ext_13multi_modular_22MultiModularBasis_base_5__init__
 (multi_modular.c:4498)
 ==21248==    by 0x4CB5DC7: type_call (typeobject.c:737)
 ==21248==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==21248==    by 0x2B4CCDF4:
 
__pyx_pw_4sage_6matrix_20matrix_integer_dense_20Matrix_integer_dense_45_multiply_multi_modular
 (matrix_integer_dense.c:12884)
 ==21248==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==21248==    by 0x2B4BE7C6:
 
__pyx_f_4sage_6matrix_20matrix_integer_dense_20Matrix_integer_dense__matrix_times_matrix_
 (matrix_integer_dense.c:10112)
 ==21248==    by 0x43DCC37E:
 __pyx_f_4sage_6matrix_6action_18MatrixMatrixAction__call_ (action.c:3179)
 ==21248==    by 0x151550FE:
 __pyx_f_4sage_9structure_6coerce_24CoercionModel_cache_maps_bin_op
 (coerce.c:6785)
 ==21248==    by 0x14CE7775:
 __pyx_pw_4sage_9structure_7element_6Matrix_5__mul__ (element.c:19222)
 ==21248==    by 0x4C5435E: binary_op1 (abstract.c:945)
 ==21248==    by 0x4C572A7: PyNumber_Multiply (abstract.c:1216)
 ==21248==    by 0x4CFA2F0: PyEval_EvalFrameEx (ceval.c:1264)
 ==21248==    by 0x4CFE274: PyEval_EvalCodeEx (ceval.c:3253)
 ==21248==    by 0x4CFC69F: PyEval_EvalFrameEx (ceval.c:4117)
 ==21248==    by 0x4CFD3CA: PyEval_EvalFrameEx (ceval.c:4107)
 ==21248==    by 0x4CFD3CA: PyEval_EvalFrameEx (ceval.c:4107)
 ==21248==    by 0x4CFE274: PyEval_EvalCodeEx (ceval.c:3253)
 ==21248==    by 0x4CFC69F: PyEval_EvalFrameEx (ceval.c:4117)
 ==21248==    by 0x4CFD3CA: PyEval_EvalFrameEx (ceval.c:4107)
 ==21248==    by 0x4CFE274: PyEval_EvalCodeEx (ceval.c:3253)
 ==21248==  Address 0x3f42f390 is 0 bytes after a block of size 336 alloc'd
 ==21248==    at 0x4A0762F: malloc (vg_replace_malloc.c:270)
 ==21248==    by 0x3432B173:
 __pyx_pf_4sage_9functions_8prime_pi_7PrimePi_4__call__ (memory.h:32)
 ==21248==    by 0x3432BBBC:
 __pyx_pw_4sage_9functions_8prime_pi_7PrimePi_5__call__ (prime_pi.c:1202)
 ==21248==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==21248==    by 0x2ADCA63A:
 __pyx_pw_4sage_3ext_13multi_modular_22MultiModularBasis_base_5__init__
 (multi_modular.c:4498)
 ==21248==    by 0x4CB5DC7: type_call (typeobject.c:737)
 ==21248==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==21248==    by 0x2B4CCDF4:
 
__pyx_pw_4sage_6matrix_20matrix_integer_dense_20Matrix_integer_dense_45_multiply_multi_modular
 (matrix_integer_dense.c:12884)
 ==21248==    by 0x4C59402: PyObject_Call (abstract.c:2529)
 ==21248==    by 0x2B4BE7C6:
 
__pyx_f_4sage_6matrix_20matrix_integer_dense_20Matrix_integer_dense__matrix_times_matrix_
 (matrix_integer_dense.c:10112)
 ==21248==    by 0x43DCC37E:
 __pyx_f_4sage_6matrix_6action_18MatrixMatrixAction__call_ (action.c:3179)
 ==21248==    by 0x151550FE:
 __pyx_f_4sage_9structure_6coerce_24CoercionModel_cache_maps_bin_op
 (coerce.c:6785)
 ==21248==    by 0x14CE7775:
 __pyx_pw_4sage_9structure_7element_6Matrix_5__mul__ (element.c:19222)
 ==21248==    by 0x4C5435E: binary_op1 (abstract.c:945)
 ==21248==    by 0x4C572A7: PyNumber_Multiply (abstract.c:1216)
 ==21248==    by 0x4CFA2F0: PyEval_EvalFrameEx (ceval.c:1264)
 ==21248==    by 0x4CFE274: PyEval_EvalCodeEx (ceval.c:3253)
 ==21248==    by 0x4CFC69F: PyEval_EvalFrameEx (ceval.c:4117)
 ==21248==    by 0x4CFD3CA: PyEval_EvalFrameEx (ceval.c:4107)
 ==21248==    by 0x4CFD3CA: PyEval_EvalFrameEx (ceval.c:4107)
 ==21248==    by 0x4CFE274: PyEval_EvalCodeEx (ceval.c:3253)
 ==21248==    by 0x4CFC69F: PyEval_EvalFrameEx (ceval.c:4117)
 ==21248==    by 0x4CFD3CA: PyEval_EvalFrameEx (ceval.c:4107)
 ==21248==    by 0x4CFE274: PyEval_EvalCodeEx (ceval.c:3253)
 ==21248==    by 0x4CFC69F: PyEval_EvalFrameEx (ceval.c:4117)
 }}}
 This looks like an off-by-one on an array of small primes. Indeed, in

 `sage/functions/prime_pi.pyx`:196
 {{{
         self.primes = <long*> sage_malloc(self.primeCount*sizeof(long))
 }}}

 whereas in

 `sage/functions/prime_pi.pyx`:263
 {{{
         for i in range(4, self.primeCount):
             if prime >= m_max: break
             x = N / prime
             if preTransition:
                 if prime*prime <= x:
                     sum -= self.prime_phi_small(x, prime) - i
                 else:
                     sum -= self.prime_phi_small(x) - i
                     preTransition = False
             else:
                 sum -= self.prime_phi_small(x) - i
             prime = self.primes[i + 1]
         return sum
 }}}
 The last line indeed gets `prime` from an unallocated address. However,
 that value doesn't get used. So if this instruction succeeds I don't think
 it'll do harm, but in extremely unlucky situations (when `self.primes` is
 just at the edge of a page) this could lead to a segfault. The same thing
 happens at other places in this file too.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/13731#comment:119>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to