CUBA Platform Code Analyse mit PVS-Studio

Bild 2

Für Java-Programmierer gibt es nützliche Tools, mit denen Sie hochwertigen Code schreiben können, z. B. die leistungsstarke IntelliJ IDEA-Entwicklungsumgebung, kostenlose SpotBugs, PMD-Analysatoren und andere. All dies wird bereits in der Entwicklung des CUBA Platform-Projekts verwendet. In dieser Überprüfung der gefundenen Codefehler werde ich Ihnen erläutern, wie Sie die Qualität des Projekts mithilfe des statischen Code-Analysators PVS-Studio verbessern können.

Über das Projekt und den Analysator


Die CUBA-Plattform ist ein Java-Framework auf hoher Ebene zum schnellen Erstellen von Unternehmensanwendungen mit einer vollständigen Weboberfläche. Die Plattform abstrahiert den Entwickler von heterogenen Technologien, sodass Sie sich gleichzeitig auf die Lösung von Geschäftsproblemen konzentrieren können, ohne dass es unmöglich ist, direkt mit ihnen zu arbeiten. Der Quellcode wird aus dem Repository auf GitHub übernommen .

PVS-Studio ist ein Tool zum Erkennen von Fehlern und potenziellen Schwachstellen im Quellcode von Programmen, die in C, C ++, C # und Java geschrieben wurden. Es funktioniert auf 64-Bit-Systemen unter Windows, Linux und MacOS. Für Java-Programmierer haben wir Plugins für Maven, Gradle und IntelliJ IDEA entwickelt. Das CUBA Platform-Projekt konnte mithilfe des Gradle-Plugins problemlos überprüft werden.

Fehler in den Bedingungen


Warnung 1

V6007 Ausdruck 'StringUtils.isNotEmpty ("handleTabKey")' ist immer wahr. SourceCodeEditorLoader.java (60)

@Override public void loadComponent() { .... String handleTabKey = element.attributeValue("handleTabKey"); if (StringUtils.isNotEmpty("handleTabKey")) { resultComponent.setHandleTabKey(Boolean.parseBoolean(handleTabKey)); } .... } 

Nach dem Abrufen des Attributwerts aus einem Element wird die Überprüfung dieses Werts nicht durchgeführt. Stattdessen wird eine konstante Zeichenfolge an die Funktion isNotEmpty übergeben , aber wir mussten die Variable handleTabKey übergeben .

Es gibt einen weiteren ähnlichen Fehler in der Datei AbstractTableLoader.java:

  • V6007 Ausdruck 'StringUtils.isNotEmpty ("editierbar")' ist immer wahr. AbstractTableLoader.java (596)

Warnung 2

V6007 Der Ausdruck 'previousMenuItemFlatIndex> = 0' ist immer wahr. CubaSideMenuWidget.java (328)

 protected MenuItemWidget findNextMenuItem(MenuItemWidget currentItem) { List<MenuTreeNode> menuTree = buildVisibleTree(this); List<MenuItemWidget> menuItemWidgets = menuTreeToList(menuTree); int menuItemFlatIndex = menuItemWidgets.indexOf(currentItem); int previousMenuItemFlatIndex = menuItemFlatIndex + 1; if (previousMenuItemFlatIndex >= 0) { return menuItemWidgets.get(previousMenuItemFlatIndex); } return null; } 

Die Funktion indexOf kann -1 zurückgeben, wenn das Element nicht in der Liste gefunden wird. Dann wird einer zum Index hinzugefügt, wodurch die Situation ausgeblendet wird, in der das gewünschte Element fehlt. Ein weiteres potenzielles Problem kann die Tatsache sein, dass die Variable previousMenuItemFlatIndex immer größer oder gleich Null ist. Wenn beispielsweise die Liste menuItemWidgets leer ist, kann die Grenze des Arrays überschritten werden.

Warnung 3

V6009 Die Funktion 'Löschen' könnte den Wert '-1' empfangen, während ein nicht negativer Wert erwartet wird. Argument überprüfen: 1. AbstractCollectionDatasource.java (556)

 protected DataLoadContextQuery createDataQuery(....) { .... StringBuilder orderBy = new StringBuilder(); .... if (orderBy.length() > 0) { orderBy.delete(orderBy.length() - 2, orderBy.length()); orderBy.insert(0, " order by "); } .... } 

In der Zeichenpufferreihenfolge By werden die letzten 2 Zeichen gelöscht, wenn ihre Gesamtzahl größer als Null ist, d.h. Eine Zeichenfolge enthält ein oder mehrere Zeichen. Die Startposition zum Löschen von Zeichen wurde jedoch mit einem Versatz von 2 Zeichen festgelegt. Wenn orderBy plötzlich aus 1 Zeichen besteht, löst ein Löschversuch eine StringIndexOutOfBoundsException aus .

Warnung 4

V6013 Die Objekte 'masterCollection' und 'entity' werden als Referenz verglichen. Möglicherweise war ein Gleichstellungsvergleich beabsichtigt. CollectionPropertyContainerImpl.java (81)

 @Override public void setItems(@Nullable Collection<E> entities) { super.setItems(entities); Entity masterItem = master.getItemOrNull(); if (masterItem != null) { MetaProperty masterProperty = getMasterProperty(); Collection masterCollection = masterItem.getValue(masterProperty.getName()); if (masterCollection != entities) { updateMasterCollection(masterProperty, masterCollection, entities); } } } 

In der Funktion updateMasterCollection werden Werte von Entitäten in masterCollection kopiert. Zuvor wurden die Sammlungen anhand von Referenzen verglichen, aber möglicherweise war geplant, sie nach Wert zu vergleichen.

Warnung 5

V6013 Die Objekte 'value' und 'oldValue' werden als Referenz verglichen. Möglicherweise war ein Gleichstellungsvergleich beabsichtigt. WebOptionsList.java (278)

 protected boolean isCollectionValuesChanged(Collection<I> value, Collection<I> oldValue) { return value != oldValue; } 

Dieses Beispiel ähnelt dem vorherigen. Hier ist isCollectionValuesChanged zum Vergleichen von Sammlungen. Vielleicht ist ein Vergleich durch Bezugnahme auch nicht der erwartete Weg.

Überbedingungen


Warnung 1

V6007 Ausdruck 'mask.charAt (i + offset)! = PlaceHolder' ist immer wahr. DatePickerDocument.java (238)

 private String calculateFormattedString(int offset, String text) .... { .... if ((mask.charAt(i + offset) == placeHolder)) { // <= .... } else if ((mask.charAt(i + offset) != placeHolder) && // <= (Character.isDigit(text.charAt(i)))) { .... } .... } 

Im zweiten Vergleich wird ein Ausdruck geprüft, der dem ersten entgegengesetzt ist. Die zweite Prüfung kann entfernt werden, um den Code zu vereinfachen.

V6007 Der Ausdruck 'connector == null' ist immer falsch. HTML5Support.java (169)

 private boolean validate(NativeEvent event) { .... while (connector == null) { widget = widget.getParent(); connector = Util.findConnectorFor(widget); } if (this.connector == connector) { return true; } else if (connector == null) { // <= return false; } else if (connector.getWidget() instanceof VDDHasDropHandler) { return false; } return true; } 

Nach Abschluss der while-Schleife ist der Wert der Konnektorvariablen nicht null , daher kann die redundante Prüfung entfernt werden.

Ein weiterer verdächtiger Ort, auf den Entwickler achten sollten:

  • V6007 Ausdruck 'StringUtils.isBlank (strValue)' ist immer wahr. Param.java (818)

Nicht erreichbarer Code in Tests


V6019 Nicht erreichbarer Code erkannt. Möglicherweise liegt ein Fehler vor. TransactionTest.java (283)

 private void throwException() { throw new RuntimeException(TEST_EXCEPTION_MSG); } @Test public void testSuspendRollback() { Transaction tx = cont.persistence().createTransaction(); try { .... Transaction tx1 = cont.persistence().createTransaction(); try { EntityManager em1 = cont.persistence().getEntityManager(); assertTrue(em != em1); Server server1 = em1.find(Server.class, server.getId()); assertNull(server1); throwException(); // <= tx1.commit(); // <= } catch (Exception e) { // } finally { tx1.end(); } tx.commit(); } finally { tx.end(); } } 

Die Funktion throwException löst eine Ausnahme aus, die den Aufruf der Funktion tx1.commit verhindert. Vielleicht sollten diese Zeilen vertauscht werden.

Einige weitere ähnliche Stellen in anderen Tests:

  • V6019 Nicht erreichbarer Code erkannt. Möglicherweise liegt ein Fehler vor. TransactionTest.java (218)
  • V6019 Nicht erreichbarer Code erkannt. Möglicherweise liegt ein Fehler vor. TransactionTest.java (163)
  • V6019 Nicht erreichbarer Code erkannt. Möglicherweise liegt ein Fehler vor. TransactionTest.java (203)
  • V6019 Nicht erreichbarer Code erkannt. Möglicherweise liegt ein Fehler vor. TransactionTest.java (137)
  • V6019 Nicht erreichbarer Code erkannt. Möglicherweise liegt ein Fehler vor. UpdateDetachedTest.java (153)
  • V6019 Nicht erreichbarer Code erkannt. Möglicherweise liegt ein Fehler vor. EclipseLinkDetachedTest.java (132)
  • V6019 Nicht erreichbarer Code erkannt. Möglicherweise liegt ein Fehler vor. PersistenceTest.java (223)

Verdächtige Funktionsargumente


Warnung 1

V6023 Der Parameter 'salt' wird vor der Verwendung immer im Methodenkörper neu geschrieben. BCryptEncryptionModule.java (47)

 @Override public String getHash(String content, String salt) { salt = BCrypt.gensalt(); return BCrypt.hashpw(content, salt); } 

In der Kryptographie ist Salt eine Datenfolge, die zusammen mit einem Kennwort an eine Hash-Funktion übergeben wird. Es wird hauptsächlich zum Schutz vor Wörterbuchsuchen und Angriffen mithilfe von Regenbogentabellen sowie zum Ausblenden derselben Kennwörter verwendet. Weiterlesen: Salz (Kryptographie) .

In dieser Funktion wird die Linie sofort nach dem Aufrufen der Funktion gerieben. Möglicherweise ist das Ignorieren des übergebenen Werts eine potenzielle Sicherheitsanfälligkeit.

Warnung 2

Für die betrachtete Funktion gibt der Analysator zwei Warnungen gleichzeitig aus:

  • V6023 Der Parameter 'offsetWidth' wird vor seiner Verwendung immer im Methodenkörper neu geschrieben. CubaSuggestionFieldWidget.java (433)
  • V6023 Der Parameter 'offsetHeight' wird vor seiner Verwendung immer im Methodenkörper neu geschrieben. CubaSuggestionFieldWidget.java (433)


 @Override public void setPosition(int offsetWidth, int offsetHeight) { offsetHeight = getOffsetHeight(); .... if (offsetHeight + getPopupTop() > ....)) { .... } .... offsetWidth = containerFirstChild.getOffsetWidth(); if (offsetWidth + getPopupLeft() > ....)) { .... } else { left = getPopupLeft(); } setPopupPosition(left, top); } 

Amüsanter Code. Die Funktion akzeptiert nur zwei Variablen: offsetWidth und offsetHeight . Beide werden vor der Verwendung überschrieben.

Warnung 3

V6022 Der Parameter 'Verknüpfung' wird im Konstruktorkörper nicht verwendet. DeclarativeTrackingAction.java (47)

 public DeclarativeTrackingAction(String id, String caption, String description, String icon, String enable, String visible, String methodName, @Nullable String shortcut, ActionsHolder holder) { super(id); this.caption = caption; this.description = description; this.icon = icon; setEnabled(enable == null || Boolean.parseBoolean(enable)); setVisible(visible == null || Boolean.parseBoolean(visible)); this.methodName = methodName; checkActionsHolder(holder); } 

Der Wert des Shortcut- Parameters wird in der Funktion nicht verwendet. Die Funktionsoberfläche ist möglicherweise veraltet oder diese Warnung ist kein Fehler.

Noch ein paar ähnliche Orte:

  • V6022 Der Parameter 'type' wird im Konstruktorkörper nicht verwendet. QueryNode.java (36)
  • V6022 Der Parameter 'text2' wird im Konstruktorkörper nicht verwendet. MarkerAddition.java (22)
  • V6022 Der Parameter 'Auswahl' wird im Konstruktorkörper nicht verwendet. AceEditor.java (114)
  • V6022 Der Parameter 'options' wird im Konstruktorkörper nicht verwendet. EntitySerialization.java (379)

Verschiedene Funktionen mit dem gleichen Code


Warnung 1

V6032 Es ist seltsam, dass der Hauptteil der Methode 'firstItemId' dem Hauptteil einer anderen Methode 'lastItemId' vollständig entspricht. ContainerTableItems.java (213), ContainerTableItems.java (219)

 @Override public Object firstItemId() { List<E> items = container.getItems(); return items.isEmpty() ? null : items.get(0).getId(); } @Override public Object lastItemId() { List<E> items = container.getItems(); return items.isEmpty() ? null : items.get(0).getId(); } 

Die Funktionen firstItemId und lastItemId haben dieselbe Implementierung. In letzterem Fall war es höchstwahrscheinlich erforderlich, ein Element nicht mit dem Index 0 zu erhalten , sondern den Index des letzten Elements zu berechnen.

Warnung 2

V6032 Es ist seltsam, dass der Hauptteil der Methode dem Körper einer anderen Methode vollständig entspricht. SearchComboBoxPainter.java (495), SearchComboBoxPainter.java (501)

 private void paintBackgroundDisabledAndEditable(Graphics2D g) { rect = decodeRect1(); g.setPaint(color53); g.fill(rect); } private void paintBackgroundEnabledAndEditable(Graphics2D g) { rect = decodeRect1(); g.setPaint(color53); g.fill(rect); } 

Zwei weitere Funktionen mit verdächtig identischer Implementierung. Ich würde es wagen vorzuschlagen, dass in einem von ihnen eine andere Farbe als color53 verwendet werden musste .

Nullreferenz


Warnung 1

V6060 Die Referenz 'descriptionPopup' wurde verwendet, bevor sie gegen null verifiziert wurde. SuggestPopup.java (252), SuggestPopup.java (251)

 protected void updateDescriptionPopupPosition() { int x = getAbsoluteLeft() + WIDTH; int y = getAbsoluteTop(); descriptionPopup.setPopupPosition(x, y); if (descriptionPopup!=null) { descriptionPopup.setPopupPosition(x, y); } } 

In nur zwei Zeilen gelang es dem Autor, einen sehr verdächtigen Code zu schreiben. Zuerst wird die setPopupPosition- Methode für das descriptionPopup- Objekt aufgerufen, und dann wird das Objekt mit null verglichen. Höchstwahrscheinlich ist der erste Aufruf der Funktion setPopupPosition redundant und gefährlich. Es sieht nach den Folgen eines fehlgeschlagenen Refactorings aus.

Warnungen 2

V6060 Die 'tableModel'-Referenz wurde verwendet, bevor sie gegen null verifiziert wurde. DesktopAbstractTable.java (1580), DesktopAbstractTable.java (1564)

 protected Column addRuntimeGeneratedColumn(String columnId) { // store old cell editors / renderers TableCellEditor[] cellEditors = new TableCellEditor[tableModel.getColumnCount() + 1]; // <= TableCellRenderer[] cellRenderers = new TableCellRenderer[tableModel.getColumnCount() + 1]; // <= for (int i = 0; i < tableModel.getColumnCount(); i++) { // <= Column tableModelColumn = tableModel.getColumn(i); if (tableModel.isGeneratedColumn(tableModelColumn)) { // <= TableColumn tableColumn = getColumn(tableModelColumn); cellEditors[i] = tableColumn.getCellEditor(); cellRenderers[i] = tableColumn.getCellRenderer(); } } Column col = new Column(columnId, columnId); col.setEditable(false); columns.put(col.getId(), col); if (tableModel != null) { // <= tableModel.addColumn(col); } .... } 

Eine ähnliche Situation besteht bei dieser Funktion. Nach zahlreichen Aufrufen des tableModel- Objekts wird geprüft , ob es null ist oder nicht.

Ein weiteres Beispiel:

  • V6060 Die 'tableModel'-Referenz wurde verwendet, bevor sie gegen null verifiziert wurde. DesktopAbstractTable.java (596), DesktopAbstractTable.java (579)

Vielleicht ein logischer Fehler


V6026 Dieser Wert ist bereits der Variablen 'sortAscending' zugeordnet. CubaScrollTableWidget.java (488)

 @Override protected void sortColumn() { .... if (sortAscending) { if (sortClickCounter < 2) { // special case for initial revert sorting instead of reset sort order if (sortClickCounter == 0) { client.updateVariable(paintableId, "sortascending", false, false); } else { reloadDataFromServer = false; sortClickCounter = 0; sortColumn = null; sortAscending = true; // <= client.updateVariable(paintableId, "resetsortorder", "", true); } } else { client.updateVariable(paintableId, "sortascending", false, false); } } else { if (sortClickCounter < 2) { // special case for initial revert sorting instead of reset sort order if (sortClickCounter == 0) { client.updateVariable(paintableId, "sortascending", true, false); } else { reloadDataFromServer = false; sortClickCounter = 0; sortColumn = null; sortAscending = true; client.updateVariable(paintableId, "resetsortorder", "", true); } } else { reloadDataFromServer = false; sortClickCounter = 0; sortColumn = null; sortAscending = true; client.updateVariable(paintableId, "resetsortorder", "", true); } } .... } 

In der ersten Bedingung ist die Variable sortAscending bereits wahr , ihr wird jedoch immer noch der gleiche Wert zugewiesen. Vielleicht ist das ein Fehler und wollte falsch zuweisen.

Ein ähnliches Beispiel aus einer anderen Datei:

  • V6026 Dieser Wert ist bereits der Variablen 'sortAscending' zugeordnet. CubaTreeTableWidget.java (444)

Rückgabewerte für seltsame Funktionen


Warnung 1

V6037 Eine bedingungslose 'Rückkehr' innerhalb einer Schleife. QueryCacheManager.java (128)

 public <T> T getSingleResultFromCache(QueryKey queryKey, List<View> views) { .... for (Object id : queryResult.getResult()) { return (T) em.find(metaClass.getJavaClass(), id, views.toArray(....)); } .... } 

Der Analysator hat bei der ersten Iteration der for- Schleife einen bedingungslosen Aufruf der return-Anweisung festgestellt. Möglicherweise ist dies ein Fehler, oder Sie müssen den Code neu schreiben, um die if-Anweisung zu verwenden .

Warnung 2

V6014 Es ist seltsam, dass diese Methode immer ein und denselben Wert zurückgibt. DefaultExceptionHandler.java (40)

 @Override public boolean handle(ErrorEvent event, App app) { Throwable t = event.getThrowable(); if (t instanceof SocketException || ExceptionUtils.getRootCause(t) instanceof SocketException) { return true; } if (ExceptionUtils.getThrowableList(t).stream() .anyMatch(o -> o.getClass().getName().equals("...."))) { return true; } if (StringUtils.contains(ExceptionUtils.getMessage(t), "....")) { return true; } AppUI ui = AppUI.getCurrent(); if (ui == null) { return true; } if (t != null) { if (app.getConnection().getSession() != null) { showDialog(app, t); } else { showNotification(app, t); } } return true; } 

Diese Funktion gibt in allen Fällen true zurück . Aber hier in der allerletzten Zeile bittet um die Rückkehr von falsch . Vielleicht liegt ein Fehler vor.

Die gesamte Liste verdächtiger Funktionen mit ähnlichem Code:

  • V6014 Es ist seltsam, dass diese Methode immer ein und denselben Wert zurückgibt. ErrorNodesFinder.java (31)
  • V6014 Es ist seltsam, dass diese Methode immer ein und denselben Wert zurückgibt. FileDownloadController.java (69)
  • V6014 Es ist seltsam, dass diese Methode immer ein und denselben Wert zurückgibt. IdVarSelector.java (73)
  • V6014 Es ist seltsam, dass diese Methode immer ein und denselben Wert zurückgibt. IdVarSelector.java (48)
  • V6014 Es ist seltsam, dass diese Methode immer ein und denselben Wert zurückgibt. IdVarSelector.java (67)
  • V6014 Es ist seltsam, dass diese Methode immer ein und denselben Wert zurückgibt. IdVarSelector.java (46)
  • V6014 Es ist seltsam, dass diese Methode immer ein und denselben Wert zurückgibt. JoinVariableNode.java (57)

Warnung 3

V6007 Der Ausdruck 'needReload' ist immer falsch. WebAbstractTable.java (2702)

 protected boolean handleSpecificVariables(Map<String, Object> variables) { boolean needReload = false; if (isUsePresentations() && presentations != null) { Presentations p = getPresentations(); if (p.getCurrent() != null && p.isAutoSave(p.getCurrent()) && needUpdatePresentation(variables)) { Element e = p.getSettings(p.getCurrent()); saveSettings(e); p.setSettings(p.getCurrent(), e); } } return needReload; } 

Die Funktion gibt die Variable needReload zurück , deren Wert immer false ist . Höchstwahrscheinlich haben sie unter einer der Bedingungen vergessen, den Code zum Ändern des Werts der Variablen hinzuzufügen.

Warnung 4

V6062 Mögliche unendliche Rekursion innerhalb der 'isFocused'-Methode. GwtAceEditor.java (189), GwtAceEditor.java (190)

 public final native void focus() /*-{ this.focus(); }-*/; public final boolean isFocused() { return this.isFocused(); } 

Der Analysator hat eine Funktion erkannt, die rekursiv aufgerufen wird, ohne dass die Rekursion gestoppt werden muss. Diese Datei verfügt über viele Funktionen, die mit dem nativen Schlüsselwort gekennzeichnet sind und kommentierten Code enthalten. Höchstwahrscheinlich wird die Datei derzeit überschrieben, und bald werden die Entwickler auf die Funktion isFocused achten .

Verschiedene Warnungen


Warnung 1

V6002 Die switch-Anweisung deckt nicht alle Werte der Enum 'Operation' ab: ADD. DesktopAbstractTable.java (665)

 /** * Operation which caused the datasource change. */ enum Operation { REFRESH, CLEAR, ADD, REMOVE, UPDATE } @Override public void setDatasource(final CollectionDatasource datasource) { .... collectionChangeListener = e -> { switch (e.getOperation()) { case CLEAR: case REFRESH: fieldDatasources.clear(); break; case UPDATE: case REMOVE: for (Object entity : e.getItems()) { fieldDatasources.remove(entity); } break; } }; .... } 

Die switch-Anweisung adressiert nicht den Wert von ADD . Es ist das einzige, das nicht überprüft wurde. Es lohnt sich daher zu prüfen, ob es sich um einen Fehler handelt oder nicht.

Warnung 2

V6021 Variable 'Quelle' wird nicht verwendet. DefaultHorizontalLayoutDropHandler.java (177)

 @Override protected void handleHTML5Drop(DragAndDropEvent event) { LayoutBoundTransferable transferable = (LayoutBoundTransferable) event .getTransferable(); HorizontalLayoutTargetDetails details = (HorizontalLayoutTargetDetails) event .getTargetDetails(); AbstractOrderedLayout layout = (AbstractOrderedLayout) details .getTarget(); Component source = event.getTransferable().getSourceComponent(); // <= int idx = (details).getOverIndex(); HorizontalDropLocation loc = (details).getDropLocation(); if (loc == HorizontalDropLocation.CENTER || loc == HorizontalDropLocation.RIGHT) { idx++; } Component comp = resolveComponentFromHTML5Drop(event); if (idx >= 0) { layout.addComponent(comp, idx); } else { layout.addComponent(comp); } if (dropAlignment != null) { layout.setComponentAlignment(comp, dropAlignment); } } 

Die Quellvariable wird deklariert und nicht im Code verwendet. Vielleicht haben sie wie eine andere Comp- Variable des gleichen Typs vergessen, dem Layout eine Quelle hinzuzufügen.

Weitere Funktionen mit nicht verwendeten Variablen:

  • V6021 Variable 'Quelle' wird nicht verwendet. DefaultHorizontalLayoutDropHandler.java (175)
  • V6021 Der Wert wird der Variablen 'r' zugewiesen, aber nicht verwendet. ExcelExporter.java (262)
  • V6021 Variable 'over' wird nicht verwendet. DefaultCssLayoutDropHandler.java (49)
  • V6021 Variable 'übertragbar' wird nicht verwendet. DefaultHorizontalLayoutDropHandler.java (171)
  • V6021 Variable 'übertragbar' wird nicht verwendet. DefaultHorizontalLayoutDropHandler.java (169)
  • V6021 Die Variable 'beanLocator' wird nicht verwendet. ScreenEventMixin.java (28)

Warnung 3

V6054 Klassen sollten nicht mit ihrem Namen verglichen werden. MessageTools.java (283)

 public boolean hasPropertyCaption(MetaProperty property) { Class<?> declaringClass = property.getDeclaringClass(); if (declaringClass == null) return false; String caption = getPropertyCaption(property); int i = caption.indexOf('.'); if (i > 0 && declaringClass.getSimpleName().equals(caption.substring(0, i))) return false; else return true; } 

Der Analysator hat eine Situation festgestellt, als der Klassenvergleich namentlich durchgeführt wurde. Ein solcher Vergleich ist falsch, da JVM-Klassen gemäß der Spezifikation nur innerhalb des Pakets einen eindeutigen Namen haben. Dies kann zu einem falschen Vergleich und zur Ausführung des geplanten falschen Codes führen.

Feedback von CUBA Platform-Entwicklern


Natürlich gibt es in jedem größeren Projekt Fehler. Aus diesem Grund haben wir dem Vorschlag des PVS-Studio-Teams zur Überprüfung unseres Projekts gerne zugestimmt. Das CUBA-Repository enthält Gabeln einiger OSS-Bibliotheken von Drittanbietern unter der Apache 2-Lizenz, und es scheint, dass wir diesem Code mehr Aufmerksamkeit schenken müssen. Der Analysator hat in diesen Quellen einige Probleme festgestellt. Jetzt verwenden wir SpotBugs als Hauptanalysator und es werden keine wesentlichen Probleme von PVS-Studio festgestellt. Es ist Zeit, selbst zusätzliche Schecks zu schreiben. Vielen Dank an das PVS-Studio Team für die geleistete Arbeit.

Die Entwickler stellten außerdem fest, dass die Warnungen V6013 und V6054 falsch sind. Der Code wurde so absichtlich geschrieben. Ein statischer Analysator erkennt verdächtige Codefragmente und die Wahrscheinlichkeit, Fehler zu finden, ist bei allen Inspektionen unterschiedlich. Trotzdem ist es einfach, mit solchen Warnungen zu arbeiten, indem der praktische Mechanismus zur Massenunterdrückung von Analysatorwarnungen verwendet wird, ohne die Quellcodedateien zu ändern.

Ein anderes PVS-Studio-Team kann den Satz „Es ist Zeit, selbst zusätzliche Schecks zu schreiben“ nicht ignorieren und dieses Bild nicht verlassen :)

Bild 1

Fazit


PVS-Studio ist eine großartige Ergänzung zu Ihrem bestehenden Projekt, um Tools für die Codequalität zu verbessern. Besonders wenn es Dutzende, Hunderte und Tausende von Mitarbeitern gibt. PVS-Studio wurde entwickelt, um Fehler nicht nur zu finden, sondern auch zu beheben. Darüber hinaus geht es nicht um die automatische Codebearbeitung, sondern um eine zuverlässige Codequalitätskontrolle. In einem großen Unternehmen ist es unmöglich, sich eine Situation vorzustellen, in der absolut alle Entwickler ihren Code unabhängig mit verschiedenen Tools überprüfen. Tools wie PVS-Studio eignen sich daher besser für solche Unternehmen, in denen die Qualitätskontrolle des Codes in allen Entwicklungsphasen bereitgestellt wird, nicht nur für einen normalen Programmierer.



Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Svyatoslav Razmyslov. Analysieren des Codes der CUBA-Plattform mit PVS-Studio

Source: https://habr.com/ru/post/de449022/


All Articles