Skip to content

Sparse echelon form over QQ is mutable and shared with the cache (#10543 was fixed for dense only) #42531

Description

@cxzhong

Steps To Reproduce

This is #10543 ("Echelon form over QQ is mutable"), which was fixed for dense rational matrices only. Matrix_rational_sparse was never updated and still has the bug — with the extra consequence, not present in the original report, that the mutable result is shared with the cache, so modifying it corrupts the source matrix.

Matrix_rational_sparse.echelon_form caches its result and returns it mutable. The caller can therefore modify the matrix that the cache hands out, and every later call returns the corrupted object:

sage: A = matrix(QQ, [[1, 2], [3, 4]], sparse=True)
sage: E = A.echelon_form()
sage: E.is_mutable()
True
sage: E[0, 0] = 0
sage: A.echelon_form()
[0 0]
[0 1]          # not the echelon form of A

The dense class does not have this problem, because it calls set_immutable() on the result before caching it:

sage: matrix(QQ, [[1, 2], [3, 4]]).echelon_form().is_mutable()
False

Expected Behavior

echelon_form() should return an immutable matrix, as it does for dense matrices over QQ (since #10543) and for matrices over ZZ. A caller who wants to modify the result should have to copy it.

Actual Behavior

The sparse result is mutable and shared with the cache, so mutating it silently corrupts the source matrix's cached echelon form (and its cached pivots).

Additional Information

In src/sage/matrix/matrix_rational_sparse.pyx, echelon_form ends with

        E, pivots = self._echelon_form_multimodular(height_guess, proof=proof)

        self.cache(label, E)
        self.cache('pivots', pivots)
        return E

with no E.set_immutable(), whereas Matrix_rational_dense.echelon_form does call it.

There is a second, related leak of the same invariant a few lines up: when self is already in echelon form, the sparse method returns self — which may be mutable — instead of an immutable copy.

Found while working on #42417 (multimodular echelon form over QQ); this bug is independent of that PR and develop behaves the same way, so it is filed separately rather than fixed there.

Environment

  • OS: Linux (Ubuntu, WSL2)
  • Sage Version: 10.10.beta5

Checklist

  • I have searched the existing issues for a bug report that matches the one I want to file, without success.
  • I have verified the problem exists in the latest development version.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions