Automatisches Hinzufügen eines privaten Konstruktors mit Sensei

Veröffentlicht Dez 14, 2020
von Alan Richardson
FALLSTUDIE

Automatisches Hinzufügen eines privaten Konstruktors mit Sensei

Veröffentlicht Dez 14, 2020
von Alan Richardson
Ressource anzeigen
Ressource anzeigen

Automatisches Hinzufügen eines privaten Konstruktors mit Sensei


In einer Utility-Klasse, wenn die Felder und Methoden statisch sind, gibt es keinen offensichtlichen Grund, warum ich sie jemals instanziieren würde.

z. B. UtilityClass utility = new UtilityClass();

Der folgende Code ist eine einfache Implementierung einer Utility-Klasse.

public class UtilityClass {
    public static final Boolean ULTIMATE_TRUTH = true;
    public static boolean getTrue(){
        return ULTIMATE_TRUTH;
    }
}


Dies ist die Art von Codierungsmustern, die Tools für die statische Analyse aufspüren können, aber sie bieten oft nicht die Möglichkeit, das Problem zu beheben.

Ich kann Sensei verwenden, um das Codierungsmuster zu identifizieren und automatisch einen privaten Konstruktor zu generieren, damit ich die Klasse nicht instanziieren kann.

Suche nach der Klasse

Ich werde ein neues Rezept mit dem Namen "Utility class" hinzufügen:

  •  Statische Klassen: privaten Konstruktor anlegen.


Allgemeine Einstellungen für statische Klassen


Und zunächst werde ich einen einfachen Matcher erstellen, um nach einer Klasse zu suchen.

suchen:

  class: {}


Dies passt zu jeder Klasse, was gut genug ist, um mit dem Schreiben eines Quick Fixes zu beginnen. Sobald ich einen Quick Fix habe, der funktioniert, werde ich die Suche so verfeinern, dass sie hervorhebt, wenn es wahrscheinlicher ist, dass es eine Klasse gibt, die einen privaten Konstruktor benötigt.

Schnellbehebung

Für den Quick Fix möchte ich einen privaten Konstruktor erzeugen.

In der Beispielklasse würde dies wie folgt aussehen:

   private UtilityClass(){}

Um den obigen Code zu meiner Klasse hinzuzufügen, wird mein Quick Fix eine Methode hinzufügen, und der Name der Methode wird eine Mustache-Vorlage sein, die den Namen der Klasse verwendet.

availableFixes:

- name: "add private constructor"
  actions:
  - addMethod:
      method: "private {{{ name }}}(){}"


Im GUI-Editor verwende ich die Variablen anzeigen, um die Mustache-Vorlage zu erstellen und bearbeite dann das Feld, um den privaten Modifikator, die Klammern und die geschweiften Klammern hinzuzufügen, damit es syntaktisch korrekt ist.

Privaten Konstrukteur hinzufügen

Dies würde mir nun erlauben, einen privaten Konstruktor zu jeder Klasse hinzuzufügen.

Die QuickFix-Vorschau hilft mir, weil ich den generierten Code sehen kann, während ich die Mustache-Vorlage schreibe.

Dienstprogrammklasse Privater Konstruktor hinzufügen

Da ich nun weiß, dass ich das Problem beheben kann. Ich werde die Suchbedingungen so verfeinern, dass das Rezept angezeigt wird, wenn es am besten geeignet ist.

Suche nach fehlenden Konstrukteuren

Im Idealfall möchte ich nicht ein Rezept erstellen, das bei jeder Klasse einen Fehler meldet. Also füge ich einige zusätzliche Bedingungen in die Suche ein, damit wir nur auf Klassen passen, die keinen Konstruktor haben.

suchen:

  Klasse:
ohne:
Kind:
Methode:
Konstruktor: true


Die YAML ist etwas anders als die GUI.

In der GUI konfiguriere ich es so, dass es nach einer Klasse ohne eine Child-Methode sucht, die ein Konstruktor 'yes' ist. Wir verwenden 'yes' in der GUI anstelle von 'true', um die GUI ein wenig menschenfreundlicher zu gestalten.


Suche nach Klasse im Code


Dieses Rezept zeigt sich nun nur noch bei allen Klassen ohne Konstruktor.

Eingrenzung der Suche nach wahrscheinlichen Verursachern

Ich möchte also vielleicht noch weiter gehen und nach dem Vorhandensein von statischen Methoden oder Feldern suchen.

Ich suche nach einer beliebigen Klasse ohne Konstruktor, die entweder alle öffentlichen statischen Felder oder alle öffentlichen statischen Methoden hat.

suchen:

  Klasse:
mit:
anyOf:
- Kind:
Methode:
allOf:
- Modifikator: "public"
- modifier: "static"
- child:
field:
allOf:
- modifier: "static"
- Modifikator: "public"
ohne:
Kind:
Methode:
Konstruktor: true


Da Sensei dazu dient, mir als Programmierer in der IDE zu helfen, und nicht dazu, den Code statisch zu analysieren und alle Fehler zu melden, ist dieser Filter gut genug, um die meisten Klassen in meiner Codebasis auszuschließen, bei denen ich einen guten Grund haben könnte, einen öffentlichen Standardkonstruktor zu haben.

In einigen Projekten könnte dies ein Schritt zu weit sein, weil die Utility-Klassen private Methoden haben könnten, so dass ich nach dem Vorhandensein von "beliebigen" öffentlichen statischen Methoden suchen könnte, anstatt nach "allen".

       - Kind:
Feld:
anyOf:
- Modifikator: "static"
- modifier: "public"


Hinweise

Sensei ist nicht als Ersatz für ein statisches Analysewerkzeug gedacht. Sensei kann ein statisches Analysewerkzeug bei häufigen Problemen im Zusammenhang mit Ihrem Codierungsprozess oder Ihrer Technologie ergänzen. Durch die Replikation einer ausreichenden Anzahl von Übereinstimmungen wird ein Problem hervorgehoben, und der Entwicklungsprozess wird durch die Generierung des QuickFix-Codes unterstützt.

Was ich versuche, ist ein Rezept zu erstellen, das einfach genug ist, um alle Situationen einzuschließen, in denen ich es brauche, aber es so zu filtern, dass es nicht in jeder Klasse vorgeschlagen wird.

Wenn ich an Rezepten arbeite, versuche ich, das Risiko zu minimieren. In diesem Fall war ich nicht sicher, ob ich den privaten Konstruktor erstellen kann, also habe ich zuerst den QuickFix erstellt. Dann überarbeitete ich die Suchbedingungen, um sie spezifischer zu machen.

Manchmal bin ich bei der Arbeit an Rezepten nicht sicher, wie ich die Suche durchführen soll, also arbeite ich zuerst daran.

Ich finde es einfacher, Rezepte zu erstellen, wenn ich sie inkrementell aufbaue, indem ich zwischen dem Refactoring des QuickFix und der Suche wechsle.

---


Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.


Der Quellcode und die Rezepte dafür befinden sich im `sensei-blog-examples` Repository im Secure Code Warrior GitHub-Konto, im Modul `pojoexamples`.

https://github.com/securecodewarrior/sensei-blog-examples

Ressource anzeigen
Ressource anzeigen

Autor

Alan Richardson

Sie wollen mehr?

Tauchen Sie ein in unsere neuesten Erkenntnisse über sichere Kodierung im Blog.

Unsere umfangreiche Ressourcenbibliothek zielt darauf ab, die menschliche Herangehensweise an eine sichere Weiterbildung im Bereich der Programmierung zu stärken.

Blog ansehen
Sie wollen mehr?

Holen Sie sich die neuesten Forschungsergebnisse zur entwicklergesteuerten Sicherheit

Unsere umfangreiche Ressourcenbibliothek ist voll von hilfreichen Ressourcen, von Whitepapers bis hin zu Webinaren, die Ihnen den Einstieg in die entwicklungsorientierte sichere Programmierung erleichtern. Erforschen Sie sie jetzt.

Ressourcendrehscheibe

Automatisches Hinzufügen eines privaten Konstruktors mit Sensei

Veröffentlicht Dez 14, 2020
Von Alan Richardson

Automatisches Hinzufügen eines privaten Konstruktors mit Sensei


In einer Utility-Klasse, wenn die Felder und Methoden statisch sind, gibt es keinen offensichtlichen Grund, warum ich sie jemals instanziieren würde.

z. B. UtilityClass utility = new UtilityClass();

Der folgende Code ist eine einfache Implementierung einer Utility-Klasse.

public class UtilityClass {
    public static final Boolean ULTIMATE_TRUTH = true;
    public static boolean getTrue(){
        return ULTIMATE_TRUTH;
    }
}


Dies ist die Art von Codierungsmustern, die Tools für die statische Analyse aufspüren können, aber sie bieten oft nicht die Möglichkeit, das Problem zu beheben.

Ich kann Sensei verwenden, um das Codierungsmuster zu identifizieren und automatisch einen privaten Konstruktor zu generieren, damit ich die Klasse nicht instanziieren kann.

Suche nach der Klasse

Ich werde ein neues Rezept mit dem Namen "Utility class" hinzufügen:

  •  Statische Klassen: privaten Konstruktor anlegen.


Allgemeine Einstellungen für statische Klassen


Und zunächst werde ich einen einfachen Matcher erstellen, um nach einer Klasse zu suchen.

suchen:

  class: {}


Dies passt zu jeder Klasse, was gut genug ist, um mit dem Schreiben eines Quick Fixes zu beginnen. Sobald ich einen Quick Fix habe, der funktioniert, werde ich die Suche so verfeinern, dass sie hervorhebt, wenn es wahrscheinlicher ist, dass es eine Klasse gibt, die einen privaten Konstruktor benötigt.

Schnellbehebung

Für den Quick Fix möchte ich einen privaten Konstruktor erzeugen.

In der Beispielklasse würde dies wie folgt aussehen:

   private UtilityClass(){}

Um den obigen Code zu meiner Klasse hinzuzufügen, wird mein Quick Fix eine Methode hinzufügen, und der Name der Methode wird eine Mustache-Vorlage sein, die den Namen der Klasse verwendet.

availableFixes:

- name: "add private constructor"
  actions:
  - addMethod:
      method: "private {{{ name }}}(){}"


Im GUI-Editor verwende ich die Variablen anzeigen, um die Mustache-Vorlage zu erstellen und bearbeite dann das Feld, um den privaten Modifikator, die Klammern und die geschweiften Klammern hinzuzufügen, damit es syntaktisch korrekt ist.

Privaten Konstrukteur hinzufügen

Dies würde mir nun erlauben, einen privaten Konstruktor zu jeder Klasse hinzuzufügen.

Die QuickFix-Vorschau hilft mir, weil ich den generierten Code sehen kann, während ich die Mustache-Vorlage schreibe.

Dienstprogrammklasse Privater Konstruktor hinzufügen

Da ich nun weiß, dass ich das Problem beheben kann. Ich werde die Suchbedingungen so verfeinern, dass das Rezept angezeigt wird, wenn es am besten geeignet ist.

Suche nach fehlenden Konstrukteuren

Im Idealfall möchte ich nicht ein Rezept erstellen, das bei jeder Klasse einen Fehler meldet. Also füge ich einige zusätzliche Bedingungen in die Suche ein, damit wir nur auf Klassen passen, die keinen Konstruktor haben.

suchen:

  Klasse:
ohne:
Kind:
Methode:
Konstruktor: true


Die YAML ist etwas anders als die GUI.

In der GUI konfiguriere ich es so, dass es nach einer Klasse ohne eine Child-Methode sucht, die ein Konstruktor 'yes' ist. Wir verwenden 'yes' in der GUI anstelle von 'true', um die GUI ein wenig menschenfreundlicher zu gestalten.


Suche nach Klasse im Code


Dieses Rezept zeigt sich nun nur noch bei allen Klassen ohne Konstruktor.

Eingrenzung der Suche nach wahrscheinlichen Verursachern

Ich möchte also vielleicht noch weiter gehen und nach dem Vorhandensein von statischen Methoden oder Feldern suchen.

Ich suche nach einer beliebigen Klasse ohne Konstruktor, die entweder alle öffentlichen statischen Felder oder alle öffentlichen statischen Methoden hat.

suchen:

  Klasse:
mit:
anyOf:
- Kind:
Methode:
allOf:
- Modifikator: "public"
- modifier: "static"
- child:
field:
allOf:
- modifier: "static"
- Modifikator: "public"
ohne:
Kind:
Methode:
Konstruktor: true


Da Sensei dazu dient, mir als Programmierer in der IDE zu helfen, und nicht dazu, den Code statisch zu analysieren und alle Fehler zu melden, ist dieser Filter gut genug, um die meisten Klassen in meiner Codebasis auszuschließen, bei denen ich einen guten Grund haben könnte, einen öffentlichen Standardkonstruktor zu haben.

In einigen Projekten könnte dies ein Schritt zu weit sein, weil die Utility-Klassen private Methoden haben könnten, so dass ich nach dem Vorhandensein von "beliebigen" öffentlichen statischen Methoden suchen könnte, anstatt nach "allen".

       - Kind:
Feld:
anyOf:
- Modifikator: "static"
- modifier: "public"


Hinweise

Sensei ist nicht als Ersatz für ein statisches Analysewerkzeug gedacht. Sensei kann ein statisches Analysewerkzeug bei häufigen Problemen im Zusammenhang mit Ihrem Codierungsprozess oder Ihrer Technologie ergänzen. Durch die Replikation einer ausreichenden Anzahl von Übereinstimmungen wird ein Problem hervorgehoben, und der Entwicklungsprozess wird durch die Generierung des QuickFix-Codes unterstützt.

Was ich versuche, ist ein Rezept zu erstellen, das einfach genug ist, um alle Situationen einzuschließen, in denen ich es brauche, aber es so zu filtern, dass es nicht in jeder Klasse vorgeschlagen wird.

Wenn ich an Rezepten arbeite, versuche ich, das Risiko zu minimieren. In diesem Fall war ich nicht sicher, ob ich den privaten Konstruktor erstellen kann, also habe ich zuerst den QuickFix erstellt. Dann überarbeitete ich die Suchbedingungen, um sie spezifischer zu machen.

Manchmal bin ich bei der Arbeit an Rezepten nicht sicher, wie ich die Suche durchführen soll, also arbeite ich zuerst daran.

Ich finde es einfacher, Rezepte zu erstellen, wenn ich sie inkrementell aufbaue, indem ich zwischen dem Refactoring des QuickFix und der Suche wechsle.

---


Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.


Der Quellcode und die Rezepte dafür befinden sich im `sensei-blog-examples` Repository im Secure Code Warrior GitHub-Konto, im Modul `pojoexamples`.

https://github.com/securecodewarrior/sensei-blog-examples

Wir bitten Sie um Ihre Erlaubnis, Ihnen Informationen über unsere Produkte und/oder verwandte Themen der sicheren Codierung zuzusenden. Wir werden Ihre persönlichen Daten immer mit äußerster Sorgfalt behandeln und sie niemals zu Marketingzwecken an andere Unternehmen verkaufen.

Senden
Um das Formular abzuschicken, aktivieren Sie bitte "Analytics"-Cookies. Sie können die Cookies wieder deaktivieren, sobald Sie fertig sind.