Skip to content

SONARJAVA-6706 Implement new rule S2330 - #5867

Open
romainbrenguier wants to merge 7 commits into
masterfrom
new-rule/SONARJAVA-6706-S2330
Open

SONARJAVA-6706 Implement new rule S2330#5867
romainbrenguier wants to merge 7 commits into
masterfrom
new-rule/SONARJAVA-6706-S2330

Conversation

@romainbrenguier

Copy link
Copy Markdown
Contributor

Detect array covariance where an array of a derived type is assigned to a variable declared as an array of its base type, which can lead to ArrayStoreException at runtime.

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

SONARJAVA-6706

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5868

Please review and merge it into your branch.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5868

Please review and merge it into your branch.

romainbrenguier pushed a commit that referenced this pull request Aug 4, 2026
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Ruling Diff Summary

Detected changes in 10 rule files: 0 issues removed, 155 issues added.

S2330 (java) on commons-beanutils - 0 issues removed, 3 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/LazyDynaList.java (line 418)

       413 |      */
       414 |     @Override
       415 |     public Object[] toArray() {
       416 | 
       417 |         if (size() == 0 && elementType == null) {
>>>    418 |             return new LazyDynaBean[0];
       419 |         }
       420 | 
       421 |         final Object[] array = (Object[])Array.newInstance(elementType, size());
       422 |         for (int i = 0; i < size(); i++) {
       423 |             if (Map.class.isAssignableFrom(elementType)) {

Added src/main/java/org/apache/commons/beanutils2/LazyDynaList.java (line 494)

       489 |      * @return A DynaBean[] of the elements in this List.
       490 |      */
       491 |     public DynaBean[] toDynaBeanArray() {
       492 | 
       493 |         if (size() == 0 && elementDynaBeanType == null) {
>>>    494 |             return new LazyDynaBean[0];
       495 |         }
       496 | 
       497 |         final DynaBean[] array = (DynaBean[])Array.newInstance(elementDynaBeanType, size());
       498 |         for (int i = 0; i < size(); i++) {
       499 |             array[i] = (DynaBean)get(i);

Added src/test/java/org/apache/commons/beanutils2/LazyDynaListTestCase.java (line 209)

       204 |         }
       205 | 
       206 | 
       207 | 
       208 |         // ----- Create LazyArrayList from Array -----
>>>    209 |         lazyList = new LazyDynaList(testArray);
       210 |         assertEquals("6. check size", size, lazyList.size());
       211 | 
       212 |         dynaArray = lazyList.toDynaBeanArray();
       213 |         mapArray  = (TreeMap[])lazyList.toArray();
       214 | 
S2198 (java) on eclipse-jetty - 0 issues removed, 9 issues added - new ruling file

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java (line 876)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java (line 890)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java)

Added jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java (line 107)

(source file not found at this revision: jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java)

Added jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java (line 124)

(source file not found at this revision: jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java)

Added jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java (line 142)

(source file not found at this revision: jetty-util/src/main/java/org/eclipse/jetty/util/ByteArrayISO8859Writer.java)

Added jetty-util/src/main/java/org/eclipse/jetty/util/TreeTrie.java (line 98)

(source file not found at this revision: jetty-util/src/main/java/org/eclipse/jetty/util/TreeTrie.java)

Added jetty-util/src/main/java/org/eclipse/jetty/util/TreeTrie.java (line 135)

(source file not found at this revision: jetty-util/src/main/java/org/eclipse/jetty/util/TreeTrie.java)
S2330 (java) on eclipse-jetty - 0 issues removed, 30 issues added - new ruling file

Added jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MetaData.java (line 249)

(source file not found at this revision: jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MetaData.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/ClassLoaderDump.java (line 54)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/ClassLoaderDump.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java (line 67)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java (line 125)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java (line 847)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java (line 869)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java)

Added jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java (line 603)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java)

Added jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java (line 106)

(source file not found at this revision: jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java)

Added jetty-util/src/test/java/org/eclipse/jetty/util/IntrospectionUtilTest.java (line 60)

(source file not found at this revision: jetty-util/src/test/java/org/eclipse/jetty/util/IntrospectionUtilTest.java)

Added jetty-util/src/test/java/org/eclipse/jetty/util/IntrospectionUtilTest.java (line 67)

(source file not found at this revision: jetty-util/src/test/java/org/eclipse/jetty/util/IntrospectionUtilTest.java)

Added jetty-util/src/test/java/org/eclipse/jetty/util/LazyListTest.java (line 425)

(source file not found at this revision: jetty-util/src/test/java/org/eclipse/jetty/util/LazyListTest.java)

Added jetty-util/src/test/java/org/eclipse/jetty/util/LazyListTest.java (line 436)

(source file not found at this revision: jetty-util/src/test/java/org/eclipse/jetty/util/LazyListTest.java)

Added jetty-util/src/test/java/org/eclipse/jetty/util/LazyListTest.java (line 451)

(source file not found at this revision: jetty-util/src/test/java/org/eclipse/jetty/util/LazyListTest.java)

Added jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java (line 456)

(source file not found at this revision: jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java)

Added jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java (line 457)

(source file not found at this revision: jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java)
S9130 (java) on eclipse-jetty - 0 issues removed, 9 issues added - new ruling file

Added jetty-server/src/test/java/org/eclipse/jetty/server/DumpHandler.java (line 84)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/DumpHandler.java)

Added jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java (line 1379)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java)

Added jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java (line 1386)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java)

Added jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java (line 1407)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java)

Added jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java (line 303)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java)

Added jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java (line 466)

(source file not found at this revision: jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java)

Added jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java (line 467)

(source file not found at this revision: jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java)
S2198 (java) on eclipse-jetty-similar-to-main - 0 issues removed, 2 issues added - new ruling file

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java (line 876)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java)

Added jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java (line 890)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java)
S2330 (java) on eclipse-jetty-similar-to-main - 0 issues removed, 10 issues added - new ruling file

Added jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java (line 277)

(source file not found at this revision: jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java)

Added jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MetaData.java (line 249)

(source file not found at this revision: jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MetaData.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/ClassLoaderDump.java (line 54)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/ClassLoaderDump.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/Server.java (line 274)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/Server.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java (line 67)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java (line 125)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java (line 847)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java)

Added jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java (line 869)

(source file not found at this revision: jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java)
S9130 (java) on eclipse-jetty-similar-to-main - 0 issues removed, 5 issues added - new ruling file

Added jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java (line 1379)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java)

Added jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java (line 1386)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java)

Added jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java (line 1407)

(source file not found at this revision: jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java)
S2198 (java) on guava - 0 issues removed, 1 issues added - new ruling file

Added src/com/google/common/net/InetAddresses.java (line 907)

       902 |     // Squash into 224/4 Multicast and 240/4 Reserved space (i.e. 224/3).
       903 |     coercedHash |= 0xe0000000;
       904 | 
       905 |     // Fixup to avoid some "illegal" values.  Currently the only potential
       906 |     // illegal value is 255.255.255.255.
>>>    907 |     if (coercedHash == 0xffffffff) {
       908 |       coercedHash = 0xfffffffe;
       909 |     }
       910 | 
       911 |     return getInet4Address(Ints.toByteArray(coercedHash));
       912 |   }
S2330 (java) on guava - 0 issues removed, 28 issues added - new ruling file

Added src/com/google/common/collect/ImmutableBiMap.java (line 228)

       223 |             }
       224 |             Arrays.sort(entries, 0, size,
       225 |                 Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
       226 |           }
       227 |           entriesUsed = size == entries.length;
>>>    228 |           return RegularImmutableBiMap.fromEntryArray(size, entries);
       229 |       }
       230 |     }
       231 |   }
       232 | 
       233 |   /**

Added src/com/google/common/collect/ImmutableCollection.java (line 185)

       180 |     if (other.length < size) {
       181 |       other = ObjectArrays.newArray(other, size);
       182 |     } else if (other.length > size) {
       183 |       other[size] = null;
       184 |     }
>>>    185 |     copyIntoArray(other, 0);
       186 |     return other;
       187 |   }
       188 | 
       189 |   @Override
       190 |   public abstract boolean contains(@Nullable Object object);

Added src/com/google/common/collect/ImmutableCollection.java (line 457)

       452 |       return this;
       453 |     }
       454 | 
       455 |     @Override
       456 |     public Builder<E> add(E... elements) {
>>>    457 |       checkElementsNotNull(elements);
       458 |       ensureCapacity(size + elements.length);
       459 |       System.arraycopy(elements, 0, contents, size, elements.length);
       460 |       size += elements.length;
       461 |       return this;
       462 |     }

Added src/com/google/common/collect/ImmutableList.java (line 278)

       273 |       case 0:
       274 |         return ImmutableList.of();
       275 |       case 1:
       276 |         return new SingletonImmutableList<E>(elements[0]);
       277 |       default:
>>>    278 |         return new RegularImmutableList<E>(checkElementsNotNull(elements.clone()));
       279 |     }
       280 |   }
       281 | 
       282 |   /**
       283 |    * Views the array as an immutable list.  Checks for nulls; does not copy.

Added src/com/google/common/collect/ImmutableMap.java (line 289)

       284 |             }
       285 |             Arrays.sort(entries, 0, size,
       286 |                 Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
       287 |           }
       288 |           entriesUsed = size == entries.length;
>>>    289 |           return RegularImmutableMap.fromEntryArray(size, entries);
       290 |       }
       291 |     }
       292 |   }
       293 | 
       294 |   /**

Added src/com/google/common/collect/ImmutableMapEntrySet.java (line 57)

        52 |       return asList().iterator();
        53 |     }
        54 | 
        55 |     @Override
        56 |     ImmutableList<Entry<K, V>> createAsList() {
>>>     57 |       return new RegularImmutableAsList<Entry<K, V>>(this, entries);
        58 |     }
        59 |   }
        60 | 
        61 |   ImmutableMapEntrySet() {}
        62 | 

Added src/com/google/common/collect/ImmutableSet.java (line 304)

       299 |       case 0:
       300 |         return of();
       301 |       case 1:
       302 |         return of(elements[0]);
       303 |       default:
>>>    304 |         return construct(elements.length, elements.clone());
       305 |     }
       306 |   }
       307 | 
       308 |   @SuppressWarnings("rawtypes") // necessary to compile against Java 8
       309 |   private static ImmutableSet copyOfEnumSet(EnumSet enumSet) {

Added src/com/google/common/collect/ImmutableSortedMap.java (line 107)

       102 |         ImmutableList.of(v1));
       103 |   }
       104 | 
       105 |   private static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> ofEntries(
       106 |       ImmutableMapEntry<K, V>... entries) {
>>>    107 |     return fromEntries(Ordering.natural(), false, entries, entries.length);
       108 |   }
       109 | 
       110 |   /**
       111 |    * Returns an immutable sorted map containing the given entries, sorted by the
       112 |    * natural ordering of their keys.

Added src/com/google/common/collect/ImmutableSortedMap.java (line 500)

       495 |         case 0:
       496 |           return emptyMap(comparator);
       497 |         case 1:
       498 |           return of(comparator, entries[0].getKey(), entries[0].getValue());
       499 |         default:
>>>    500 |           return fromEntries(comparator, false, entries, size);
       501 |       }
       502 |     }
       503 |   }
       504 | 
       505 |   private final transient RegularImmutableSortedSet<K> keySet;

Added src/com/google/common/collect/ImmutableSortedSet.java (line 375)

       370 |   static <E> ImmutableSortedSet<E> construct(
       371 |       Comparator<? super E> comparator, int n, E... contents) {
       372 |     if (n == 0) {
       373 |       return emptySet(comparator);
       374 |     }
>>>    375 |     checkElementsNotNull(contents, n);
       376 |     Arrays.sort(contents, 0, n, comparator);
       377 |     int uniques = 1;
       378 |     for (int i = 1; i < n; i++) {
       379 |       E cur = contents[i];
       380 |       E prev = contents[uniques - 1];

Added src/com/google/common/collect/ImmutableSortedSet.java (line 387)

       382 |         contents[uniques++] = cur;
       383 |       }
       384 |     }
       385 |     Arrays.fill(contents, uniques, n, null);
       386 |     return new RegularImmutableSortedSet<E>(
>>>    387 |         ImmutableList.<E>asImmutableList(contents, uniques), comparator);
       388 |   }
       389 | 
       390 |   /**
       391 |    * Returns a builder that creates immutable sorted sets with an explicit
       392 |    * comparator. If the comparator has a more general type than the set being

Added src/com/google/common/collect/ObjectArrays.java (line 147)

       142 |   static <T> T[] toArrayImpl(Collection<?> c, T[] array) {
       143 |     int size = c.size();
       144 |     if (array.length < size) {
       145 |       array = newArray(array, size);
       146 |     }
>>>    147 |     fillArray(c, array);
       148 |     if (array.length > size) {
       149 |       array[size] = null;
       150 |     }
       151 |     return array;
       152 |   }

Added src/com/google/common/collect/Ordering.java (line 791)

       786 |     values[right] = pivotValue;
       787 | 
       788 |     int storeIndex = left;
       789 |     for (int i = left; i < right; i++) {
       790 |       if (compare(values[i], pivotValue) < 0) {
>>>    791 |         ObjectArrays.swap(values, storeIndex, i);
       792 |         storeIndex++;
       793 |       }
       794 |     }
       795 |     ObjectArrays.swap(values, right, storeIndex);
       796 |     return storeIndex;

Added src/com/google/common/collect/Ordering.java (line 795)

       790 |       if (compare(values[i], pivotValue) < 0) {
       791 |         ObjectArrays.swap(values, storeIndex, i);
       792 |         storeIndex++;
       793 |       }
       794 |     }
>>>    795 |     ObjectArrays.swap(values, right, storeIndex);
       796 |     return storeIndex;
       797 |   }
       798 | 
       799 |   /**
       800 |    * Returns the {@code k} greatest elements of the given iterable according to

Added src/com/google/common/collect/RegularImmutableBiMap.java (line 66)

        61 |     ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize);
        62 |     Entry<K, V>[] entries;
        63 |     if (n == entryArray.length) {
        64 |       entries = entryArray;
        65 |     } else {
>>>     66 |       entries = createEntryArray(n);
        67 |     }
        68 |     int hashCode = 0;
        69 | 
        70 |     for (int i = 0; i < n; i++) {
        71 |       @SuppressWarnings("unchecked")
S2330 (java) on sonar-server - 0 issues removed, 58 issues added - new ruling file

Added src/main/java/org/sonar/server/ce/ws/ActivityAction.java (line 126)

(source file not found at this revision: src/main/java/org/sonar/server/ce/ws/ActivityAction.java)

Added src/main/java/org/sonar/server/ce/ws/ActivityAction.java (line 127)

(source file not found at this revision: src/main/java/org/sonar/server/ce/ws/ActivityAction.java)

Added src/main/java/org/sonar/server/ce/ws/ActivityAction.java (line 131)

(source file not found at this revision: src/main/java/org/sonar/server/ce/ws/ActivityAction.java)

Added src/main/java/org/sonar/server/component/index/ComponentIndex.java (line 84)

(source file not found at this revision: src/main/java/org/sonar/server/component/index/ComponentIndex.java)

Added src/main/java/org/sonar/server/component/ws/SuggestionsAction.java (line 129)

(source file not found at this revision: src/main/java/org/sonar/server/component/ws/SuggestionsAction.java)

Added src/main/java/org/sonar/server/es/StickyFacetBuilder.java (line 105)

(source file not found at this revision: src/main/java/org/sonar/server/es/StickyFacetBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyClearCacheRequestBuilder.java (line 72)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyClearCacheRequestBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyClearCacheRequestBuilder.java (line 76)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyClearCacheRequestBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyClusterHealthRequestBuilder.java (line 72)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyClusterHealthRequestBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyClusterStateRequestBuilder.java (line 72)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyClusterStateRequestBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyClusterStatsRequestBuilder.java (line 72)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyClusterStatsRequestBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyFlushRequestBuilder.java (line 72)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyFlushRequestBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyIndicesExistsRequestBuilder.java (line 72)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyIndicesExistsRequestBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyIndicesStatsRequestBuilder.java (line 72)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyIndicesStatsRequestBuilder.java)

Added src/main/java/org/sonar/server/es/request/ProxyNodesStatsRequestBuilder.java (line 72)

(source file not found at this revision: src/main/java/org/sonar/server/es/request/ProxyNodesStatsRequestBuilder.java)

romainbrenguier and others added 2 commits August 4, 2026 11:05
Detect array covariance where an array of a derived type is assigned to
a variable declared as an array of its base type, which can lead to
ArrayStoreException at runtime.
Cover varargs method invocations with covariant array arguments,
including multiple vararg arguments, mixed varargs with regular
parameters, and edge cases like no vararg arguments passed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@romainbrenguier
romainbrenguier force-pushed the new-rule/SONARJAVA-6706-S2330 branch from 594a768 to 2648f82 Compare August 4, 2026 09:06
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5875

Please review and merge it into your branch.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5875

Please review and merge it into your branch.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5880

Please review and merge it into your branch.

…n S2330

Handle LAMBDA_EXPRESSION nodes directly to detect covariant array returns
in expression-bodied lambdas (e.g. `() -> new Apple[1]`), which were
previously missed since they have no RETURN_STATEMENT node.

For varargs, check the first argument against the whole array type first,
falling back to element-type check only if no issue was reported. This
prevents double-reporting when an array-of-arrays argument matches both
the vararg type and its element type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5880

Please review and merge it into your branch.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

@NoemieBenard NoemieBenard left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks good and the examples are very thorough, but I think the rule will be quite controversial. I already see some false positives worth addressing in the ruling diffs. Disabling the rule by default like in C# is also an option.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that the rule is in sonar way seems contradictory with the RSPEC and the choice of disabling it by default in C# , is it intentional?

"tags": [
"pitfall"
],
"defaultSeverity": "Critical",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default severity should be "Major" to match "RELIABILITY": "MEDIUM".

"type": "CODE_SMELL",
"code": {
"impacts": {
"RELIABILITY": "MEDIUM"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional to modify the metadata from the C# RSPEC? To me it makes sense to keep the "MAINTAINABILITY" impact together with the RELIABILITY impact (maybe with lower maintainability than reliability)

494
],
"commons-beanutils:commons-beanutils:src/main/java/org/apache/commons/beanutils2/MethodUtils.java": [
1352,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the rule raises false positives on both parameters of Array.equals because the method takes parameters of type Object[] and these are arrays with a different sub-type. We should probably exclude standard library methods from the check (though there will probably be a high FP rate for the rule anyway). Based on the ruling diffs there is the same issue for Array.fill

…m S2330

These standard library methods are safe with covariant arrays because they
either only read from the array or write type-safe values. Flagging them
produces false positives (e.g. Arrays.fill, Arrays.equals, Arrays.sort).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqube-next

sonarqube-next Bot commented Aug 5, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #5887

Please review and merge it into your branch.

@gitar-bot

gitar-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown
CI failed: Ruling QA integration tests failed due to expected issue differences (63 differences) introduced by implementing the new rule S2330.

Overview

Both Linux and Windows CI pipelines encountered test failures in the ruling QA test suite (JavaRulingTest) due to issue count mismatches against existing baseline expectations after introducing the new rule S2330.

Failures

Ruling QA Integration Test Differences (confidence: high)

  • Type: test
  • Affected jobs: 92288795700, 91689140646
  • Related to change: yes
  • Root cause: The new rule S2330 (ArrayCovarianceCheck) generates new analysis issues that differ from the current baseline expected results stored in test resources.
  • Suggested fix: Review the generated diff report artifacts and update the expected ruling test baselines/resources to include the expected findings for the new rule S2330.

Summary

  • Change-related failures: 2 test failures in the ruling integration test suite caused by new rule S2330 output differences.
  • Infrastructure/flaky failures: None
  • Recommended action: Review the HTML diff report artifacts from the CI run to confirm the correctness of rule S2330's findings, and update the expected test resources/baselines accordingly.
Code Review ✅ Approved 2 resolved / 2 findings

Implements rule S2330 to detect array covariance issues, addressing the expression-bodied lambdas and double-checked varargs findings. No issues found.

✅ 2 resolved
Edge Case: Expression-bodied lambdas escape covariance detection

📄 java-checks/src/main/java/org/sonar/java/checks/ArrayCovarianceCheck.java:79-91
The return-path handling only fires on Tree.Kind.RETURN_STATEMENT, but an expression-bodied lambda such as Supplier<Fruit[]> s = () -> new Apple[1]; has no return statement node (its body is an ExpressionTree, not a block with a return). Such covariant lambda bodies are therefore never checked, a false negative compared to the block-lambda case that is tested at ArrayCovarianceCheckSample.java:85-89. Consider also handling LAMBDA_EXPRESSION nodes directly: when the body is an ExpressionTree, compare lambda.symbol().returnType().type() against the body expression's type.

Edge Case: First vararg argument is checked twice in visitInvocation

📄 java-checks/src/main/java/org/sonar/java/checks/ArrayCovarianceCheck.java:111-116
For the first vararg argument, visitInvocation both checks it against the whole vararg array type (line 112, treating the call as passing a pre-built array) and against the vararg element type (line 114 loop starts at nonVarargCount). When a covariant array-of-arrays is passed to an array-typed varargs parameter (e.g. Object[]... ), both checks can fire and report two issues on the same expression. Consider only running the whole-array check when a single vararg argument is supplied, and starting the element loop after it, to avoid redundant/double reporting.

Tip

Comment Gitar fix CI or enable auto-apply: gitar auto-apply:on

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants