NationalSecurityAgency/ghidra · error · LSHException

Cannot commit self-score with the matrix scorer

Error message

Cannot commit self-score with the matrix scorer

What it means

Thrown by the no-arg commitSelfScore() on the base ExecutableScorer class, which implements many-to-many matrix scoring. The matrix scorer holds scores only in an in-memory float[][] array and has no ScoreCaching backing store, so persisting a self-score is architecturally unsupported. Only the subclass ExecutableScorerSingle overrides this method to delegate to a ScoreCaching implementation (e.g. FileScoreCaching).

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/ExecutableScorer.java:284

		return score[a - 1][b - 1];
	}

	/**
	 * Retrieve the similarity score of an executable with itself
	 * @param a is the index of the executable
	 * @return its self-similarity score
	 * @throws LSHException if the score is not accessible
	 */
	public float getSelfScore(int a) throws LSHException {
		return score[a - 1][a - 1];
	}

	/**
	 * Commit the singled out executables self-significance score to permanent storage
	 * @throws LSHException if there's a problem writing, or the operation isn't supported
	 */
	public void commitSelfScore() throws LSHException {
		throw new LSHException("Cannot commit self-score with the matrix scorer");
	}

	/**
	 * Commit a self-significance score for a specific executable to permanent storage
	 * @param md5 is the 32-character md5 hash of the executable
	 * @param selfScore is the self-significance score
	 * @throws LSHException if there's a problem writing, or the operation isn't supported
	 */
	protected void commitSelfScore(String md5, float selfScore) throws LSHException {
		throw new LSHException("Cannot commit self-score with the matrix scorer");
	}

	/**
	 * Get score of executable (as compared to our singled out executable)
	 * @param a is the index of the executable
	 * @return the score
	 */
	public float getScore(int a) {

View on GitHub (pinned to d5f144c24d)

Solutions

  1. If you need to persist self-scores, construct an ExecutableScorerSingle (passing a ScoreCaching such as FileScoreCaching) instead of the base ExecutableScorer.
  2. If you intentionally use the matrix scorer, remove the commitSelfScore() call — the matrix stores all scores in memory and does not need persistence for its own operation.
  3. If you must persist from a matrix context, extract the self-score via getSelfScore(int) and write it to your own ScoreCaching implementation manually.

Example fix

// before
ExecutableScorer scorer = new ExecutableScorer();
scorer.setSingleExecutable(md5);
scorer.commitSelfScore(); // throws LSHException

// after
ExecutableScorerSingle scorer =
    new ExecutableScorerSingle(new FileScoreCaching(cachePath));
scorer.setSingleExecutable(md5);
scorer.commitSelfScore(); // delegates to FileScoreCaching
Defensive patterns

Strategy: type-guard

Validate before calling

if (scorer instanceof ExecutableScorerSingle) {
    ((ExecutableScorerSingle) scorer).commitSelfScore();
} else {
    // matrix scorer: no persistence; read scores in-memory only
    float selfScore = scorer.getSelfScore(scorer.getSingleExeXref());
}

Type guard

public static boolean canCommitSelfScore(ExecutableScorer scorer) {
    return scorer instanceof ExecutableScorerSingle;
}

Try / catch

try {
    scorer.commitSelfScore();
} catch (LSHException e) {
    if (e.getMessage().contains("matrix scorer")) {
        // expected for base ExecutableScorer; no action needed
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling scorer.commitSelfScore() (the no-arg overload) on an ExecutableScorer instance whose runtime type is the base ExecutableScorer rather than ExecutableScorerSingle. This happens when code instantiates ExecutableScorer directly for many-to-many comparison and then attempts to persist the singled-out executable's self-significance score.

Common situations: A developer copies code from a one-to-many (ExecutableScorerSingle) workflow into a many-to-many (ExecutableScorer) workflow and forgets that persistence is only available on the single scorer. Also seen when a generic method accepts an ExecutableScorer reference and calls commitSelfScore() without checking the concrete subclass.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/1206225b31af4885. Report an issue: GitHub.