java/non-final-call-in-constructor: a call made inside a lambda in the constructor is not reported

Offen
#22,970 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
45/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
java
Bereich
security

Rechercherichtung

The report points at the unqualifiedCallToNonAbstractMethod predicate, which requires the call's enclosing callable to be the constructor (result.getEnclosingCallable() = c), so a call inside a lambda is missed. Start from the query java/non-final-call-in-constructor and the two seed files, CtorSeed.java and CtorVariant.java, and run the query on each database to confirm the gap. Done means the lambda case is reported at line 6 of CtorVariant.java while the existing results on CtorSeed.java stay the same.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Description of the issue

The query reports toString() in the constructor of CtorSeed.Senior: Junior overrides it, the override reads name, and name is only assigned after super() returns, so new Junior() throws. Move the call into a lambda that the constructor runs right away (CtorVariant) and nothing is reported, though the call still happens during construction with the same effect.

Probably unqualifiedCallToNonAbstractMethod, which requires the call's enclosing callable to be the constructor (result.getEnclosingCallable() = c). Inside the lambda the enclosing callable is the lambda's own method.

Query: java/non-final-call-in-constructor (codeql/java-queries 1.1.10)

CodeQL CLI: 2.27.2

Code samples

seed/CtorSeed.java:

public class CtorSeed {

    public static class Senior {
        public Senior() {
            toString();                        // overridden in Junior, reads a field not yet set
        }
        public String toString() {
            return "Senior";
        }
    }

    public static class Junior extends Senior {
        private String name;
        public Junior() {
            super();
            name = "Junior";
        }
        public String toString() {
            return name.toUpperCase();         // NullPointerException when called from Senior()
        }
    }
}

variant/CtorVariant.java:

public class CtorVariant {

    public static class Senior {
        public Senior() {
            Runnable r = () -> {
                toString();                    // the same call, inside a lambda run at once; not reported
            };
            r.run();
        }
        public String toString() {
            return "Senior";
        }
    }

    public static class Junior extends Senior {
        private String name;
        public Junior() {
            super();
            name = "Junior";
        }
        public String toString() {
            return name.toUpperCase();
        }
    }
}

How to reproduce

codeql database create db --language=java --build-mode=none \
    --source-root=<one directory> --overwrite
codeql database analyze db \
    codeql/java-queries:codeql-suites/java-security-and-quality.qls \
    --format=csv --output=out.csv
# one database per directory

Expected result

"Non-final method invocation in constructor" on the toString() call inside the lambda in CtorVariant.java (line 6), as on CtorSeed.java (line 5).

Output of the commands above:

### CodeQL 2.27.2  query: java/non-final-call-in-constructor
### suite: java-security-and-quality.qls, --build-mode=none, per-file isolated databases
### extraction JDK: openjdk version "21.0.11" 2026-04-21 LTS

--- SEED -- expected: query fires (seed/)
"Non-final method invocation in constructor","If a constructor calls a method that is overridden in a subclass

--- VARIANT -- expected: query fires, actual: not reported (the bug) (variant/)
    (query reported nothing)
Vorherrschende Sprache
CodeQL
Sterne
10.3k
Forks
2.1k
Ø Merge
1 T. 22 Std.
Gemergte PRs (30 T.)
126

Entwicklungsumgebung

In Codespaces öffnen

Startet den Dev-Container des Projekts im Browser, mit Ihrem eigenen GitHub-Konto.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus github/codeql

Alle Issues in github/codeql

Ähnliche Issues

Weitere Issues zu Security

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.