Skip to content

[BUG] HIGH: LAGr_PartitionQuality mutates caller's graph adjacency matrix in place #405

@gkorland

Description

@gkorland

Summary

Severity: HIGH
Category: Input mutation / cached-state corruption
Location: experimental/algorithm/LAGr_PartitionQuality.c lines 88–91

Trigger

Call LAGr_PartitionQuality on any graph that has self-edges.

Root Cause

GrB_Matrix A = G->A creates a direct alias to the graph's adjacency matrix. Line 91 then calls:

GRB_TRY(GrB_select(A, NULL, NULL, GrB_OFFDIAG, A, 0, NULL));

GrB_select with output == input performs an in-place operation, permanently deleting self-edges from G->A as a side effect of computing what is supposed to be a read-only quality metric. The cached fields (G->nself_edges, G->out_degree, etc.) are not invalidated afterward.

Compare with LAGr_Modularity, which correctly creates a local copy of G->A before removing self-edges.

Proof / Trace

  1. Caller holds graph G with self-loop (0,0) and cached G->nself_edges = 1.
  2. LAGr_PartitionQuality is called; line 91 runs GrB_select(A, NULL, NULL, GrB_OFFDIAG, A, ...).
  3. Self-edge (0,0) is permanently removed from G->A.
  4. After return, G->A no longer contains (0,0), but G->nself_edges still reports 1.
  5. Subsequent calls that rely on cached state (e.g., algorithms that skip self-edge removal because nself_edges == 0) produce wrong results or crash.

Impact

Silent, permanent graph corruption. The bug violates the caller's expectation that a quality-metric function is read-only. Cache inconsistency cascades to every subsequent operation on the graph object.

Suggested Fix

Work on a local copy of the adjacency matrix, exactly as LAGr_Modularity already does:

GrB_Matrix A = NULL;
GRB_TRY(GrB_Matrix_dup(&A, G->A));
// ... use A locally, free at end

Alternatively, document the mutation and fully invalidate all affected cached fields (nself_edges, degree vectors, etc.) before returning.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions