LinkedCaseInsensitiveMap.keySet().remove returns false after removing a null-valued entry
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
- #37478 @zsewasdsdsd による — マージされずにクローズ
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 78/100
調査の方向性
バグは spring-core の LinkedCaseInsensitiveMap.java にある内部クラス KeySet にあります。そこでは remove(o) が戻り値の boolean を、Map.remove が null を返したかどうかで決めているため、値が null のエントリでは false が返ります。issue の Repro.java スニペットを spring-core に対して実行し、1行目と3行目が false を出力することを確認してください。keySet().remove と keySet().removeAll が、存在する値 null のキーに対して true を返し、既存の LinkedCaseInsensitiveMap のテストがすべて通れば完了です。
索引モデルが issue の本文から書いたものです。
説明
Affected versions
Verified with the published spring-core 7.0.9 and 6.2.19 artifacts on JDK 21. The same result was reproduced with the affected classes compiled from main at 85a532dce455655aec8fd5a301b37c6c5ceda5bb, with the remaining dependencies supplied by spring-core 7.0.9. This was a focused reproduction, not a full Gradle build.
Problem
LinkedCaseInsensitiveMap supports null values. When a key is mapped to null, keySet().remove(key) removes the entry but returns false. This contradicts the Set removal contract, and also makes keySet().removeAll(...) report no change when it chooses its remove-based path.
Callers relying on the boolean result to detect a change receive the wrong result even though the map was modified.
Minimal reproduction
Save as Repro.java:
import java.util.Locale;
import java.util.Set;
import org.springframework.util.LinkedCaseInsensitiveMap;
public class Repro {
public static void main(String[] args) {
var map = new LinkedCaseInsensitiveMap<String>(Locale.ROOT);
map.put("key", null);
System.out.println(map.keySet().remove("key"));
System.out.println(map.isEmpty());
map.put("key", null);
map.put("other", "value");
System.out.println(map.keySet().removeAll(Set.of("key")));
System.out.println(map.containsKey("key"));
System.out.println(map.size());
}
}
Run on Java 17 or later:
curl -fLO https://repo.maven.apache.org/maven2/org/springframework/spring-core/7.0.9/spring-core-7.0.9.jar
java -cp spring-core-7.0.9.jar Repro.java
Actual output:
false
true
false
false
1
Expected: the first and third lines should be true, because both operations removed an existing key. The remaining lines are correct.
Cause
LinkedCaseInsensitiveMap.KeySet.remove returns LinkedCaseInsensitiveMap.this.remove(o) != null. A null return from Map.remove cannot distinguish an absent key from a present null-valued mapping.
The Java Set.remove contract requires true when the set contained the element and it was removed.
Related reports checked
#22821 / #23644 addressed stale internal key registrations after collection-view removals. This report concerns the boolean return value after a successful removal; the internal key registration is correctly cleared in this reproduction. #37351 concerns computeIfAbsent registrations and is also a separate case. Searches for LinkedCaseInsensitiveMap keySet and LinkedCaseInsensitiveMap null remove did not reveal a direct duplicate.
- 主要言語
- Java
- スター
- 60.3k
- フォーク
- 38.7k
- 平均マージ
- 1日 9時間
- マージ済み PR(30日)
- 34
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
spring-projects/spring-framework のほかの issue
-
`YamlProcessor.getFlattenedMap` with `includeEmpty` returns a `null` key for an empty root mapping再び着手できるかも @erfannvb が 7 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンstatus: waiting-for-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
spring-projects/spring-framework#37522 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
`WebClient` with default codecs drops `ProblemDetail` extension members再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンstatus: waiting-for-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
spring-projects/spring-framework#37503 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
StandardApiVersionDeprecationHandler generates nonconforming Sunset HTTP dates再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンstatus: waiting-for-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
spring-projects/spring-framework#37486 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
FastByteArrayOutputStream input stream rejects valid skip(long) arguments再び着手できるかも @hickey-ai が 10 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンstatus: waiting-for-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
spring-projects/spring-framework#37471 · コメント 6 件 ·
メンテナーはふだん 1 日以内に返信
-
ServerSentEventHttpMessageReader does not recognize data fields without a colon再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンin: web status: waiting-for-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
spring-projects/spring-framework#37461 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
spring-projects/spring-framework の issue をすべて見る
似ている issue
-
:Search Relevance/Vectors >test-failure needs:risk Team:Search Relevance
難易度 2/5 1〜3時間 初心者へのやさしさ 61/100
elastic/elasticsearch#163668 · コメント 3 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
agent:working bug follow-up lane:auto
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
Sanne/incus-spawn#1765 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
Mend: dependency security vulnerability untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 63/100
opensearch-project/data-prepper#7219 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 83/100
メンテナーはふだん 1 日以内に返信