From dff7f8d95cbded4d18ee3de220d7c21dd15f1424 Mon Sep 17 00:00:00 2001 From: thc202 Date: Tue, 14 Jul 2026 09:52:48 +0100 Subject: [PATCH 1/2] Address NPEs related to script types Guard against the usage of null keys when handling script types, the collection now in use does not support null keys. Signed-off-by: thc202 --- .../zap/extension/script/ExtensionScript.java | 13 +++++ .../script/ExtensionScriptUnitTest.java | 53 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/zap/src/main/java/org/zaproxy/zap/extension/script/ExtensionScript.java b/zap/src/main/java/org/zaproxy/zap/extension/script/ExtensionScript.java index 5b006917429..7a35886c481 100644 --- a/zap/src/main/java/org/zaproxy/zap/extension/script/ExtensionScript.java +++ b/zap/src/main/java/org/zaproxy/zap/extension/script/ExtensionScript.java @@ -546,11 +546,17 @@ public ScriptTreeModel getTreeModel() { * *

The script is added to the tree of scripts and its scripts/templates loaded, if any. * + *

The call to this method has no effect if the given type or its name is null. + * * @param type the new type of script * @throws InvalidParameterException if a script type with same name is already registered * @see #removeScriptType(ScriptType) */ public void registerScriptType(ScriptType type) { + if (type == null || type.getName() == null) { + return; + } + if (typeMap.containsKey(type.getName())) { throw new InvalidParameterException("ScriptType already registered: " + type.getName()); } @@ -623,6 +629,10 @@ public void removeScripType(ScriptType type) { * @see #registerScriptType(ScriptType) */ public void removeScriptType(ScriptType type) { + if (type == null || type.getName() == null) { + return; + } + ScriptType scriptType = typeMap.remove(type.getName()); if (scriptType != null) { getTreeModel().removeType(scriptType); @@ -630,6 +640,9 @@ public void removeScriptType(ScriptType type) { } public ScriptType getScriptType(String name) { + if (name == null) { + return null; + } return this.typeMap.get(name); } diff --git a/zap/src/test/java/org/zaproxy/zap/extension/script/ExtensionScriptUnitTest.java b/zap/src/test/java/org/zaproxy/zap/extension/script/ExtensionScriptUnitTest.java index f8e8f25fb53..0c91fcc1f90 100644 --- a/zap/src/test/java/org/zaproxy/zap/extension/script/ExtensionScriptUnitTest.java +++ b/zap/src/test/java/org/zaproxy/zap/extension/script/ExtensionScriptUnitTest.java @@ -64,6 +64,59 @@ void shouldReturnThreadSafeScriptTypesCollection() { assertDoesNotThrow(it::next); } + @Test + void shouldHandleRegistrationOfNullScriptType() { + // Given + ExtensionScript extensionScript = new ExtensionScript(); + ScriptType scriptType = null; + + // When / Then + assertDoesNotThrow(() -> extensionScript.registerScriptType(scriptType)); + } + + @Test + void shouldHandleRegistrationOfScriptTypeWithNullName() { + // Given + ExtensionScript extensionScript = new ExtensionScript(); + ScriptType scriptType = new ScriptType(null, "i18n.type", null, false); + + // When / Then + assertDoesNotThrow(() -> extensionScript.registerScriptType(scriptType)); + } + + @Test + void shouldHandleRemovalOfNullScriptType() { + // Given + ExtensionScript extensionScript = new ExtensionScript(); + ScriptType scriptType = null; + + // When / Then + assertDoesNotThrow(() -> extensionScript.removeScriptType(scriptType)); + } + + @Test + void shouldHandleRemovalOfScriptTypeWithNullName() { + // Given + ExtensionScript extensionScript = new ExtensionScript(); + ScriptType scriptType = new ScriptType(null, "i18n.type", null, false); + + // When / Then + assertDoesNotThrow(() -> extensionScript.removeScriptType(scriptType)); + } + + @Test + void shouldGetNullScriptTypeFromNullName() { + // Given + ExtensionScript extensionScript = new ExtensionScript(); + String scriptTypeName = null; + + // When + ScriptType type = extensionScript.getScriptType(scriptTypeName); + + // Then + assertThat(type, is(nullValue())); + } + @Test void shouldCreateScriptsCache() { // Given From 43010404fe188e337d10fb8d18264841b6cec6ad Mon Sep 17 00:00:00 2001 From: thc202 Date: Tue, 14 Jul 2026 10:50:20 +0100 Subject: [PATCH 2/2] Address exceptions related to statistics Guard against the usage of null keys when handling statistics, the collection in use does not support null keys. Signed-off-by: thc202 --- .../org/zaproxy/zap/utils/Statistics.java | 28 ++++++ .../zaproxy/zap/utils/StatisticsUnitTest.java | 92 +++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/zap/src/main/java/org/zaproxy/zap/utils/Statistics.java b/zap/src/main/java/org/zaproxy/zap/utils/Statistics.java index e838c3ed5fb..abd5eddf088 100644 --- a/zap/src/main/java/org/zaproxy/zap/utils/Statistics.java +++ b/zap/src/main/java/org/zaproxy/zap/utils/Statistics.java @@ -34,6 +34,10 @@ public void incCounter(String key) { } public void incCounter(String key, long inc) { + if (key == null) { + return; + } + stats.compute(key, (k, v) -> (v != null ? v : 0) + inc); } @@ -42,10 +46,18 @@ public void decCounter(String key) { } public void decCounter(String key, long dec) { + if (key == null) { + return; + } + stats.compute(key, (k, v) -> (v != null ? v : 0) - dec); } public void setHighwaterMark(String key, long value) { + if (key == null) { + return; + } + Long curValue = stats.get(key); if (curValue == null || value > curValue) { stats.put(key, value + 1); @@ -53,6 +65,10 @@ public void setHighwaterMark(String key, long value) { } public void setLowwaterMark(String key, long value) { + if (key == null) { + return; + } + Long curValue = stats.get(key); if (curValue == null || value < curValue) { stats.put(key, value + 1); @@ -60,11 +76,19 @@ public void setLowwaterMark(String key, long value) { } public Long getStat(String key) { + if (key == null) { + return null; + } + return stats.get(key); } public Map getStats(String keyPrefix) { Map map = new HashMap<>(); + if (keyPrefix == null) { + return map; + } + for (Entry stat : stats.entrySet()) { if (stat.getKey().startsWith(keyPrefix)) { map.put(stat.getKey(), stat.getValue()); @@ -78,6 +102,10 @@ public void clearAll() { } public void clear(String keyPrefix) { + if (keyPrefix == null) { + return; + } + Iterator> iter = stats.entrySet().iterator(); while (iter.hasNext()) { Entry entry = iter.next(); diff --git a/zap/src/test/java/org/zaproxy/zap/utils/StatisticsUnitTest.java b/zap/src/test/java/org/zaproxy/zap/utils/StatisticsUnitTest.java index 54c02983f43..e226981ab00 100644 --- a/zap/src/test/java/org/zaproxy/zap/utils/StatisticsUnitTest.java +++ b/zap/src/test/java/org/zaproxy/zap/utils/StatisticsUnitTest.java @@ -55,6 +55,16 @@ void shouldIncreaseCounter() throws Exception { assertThat(statistics.getStat(STAT_KEY), is(equalTo(1L))); } + @Test + void shouldIgnoreIncreaseCounterForNullKey() { + // Given + Statistics statistics = new Statistics(); + // When + statistics.incCounter(null); + // Then + assertThat(statistics.getStat(null), is(nullValue())); + } + @Test void shouldIncreaseExistingCounter() throws Exception { // Given @@ -76,6 +86,16 @@ void shouldIncreaseCounterWithGivenValue() throws Exception { assertThat(statistics.getStat(STAT_KEY), is(equalTo(5L))); } + @Test + void shouldIgnoreIncreaseCounterWithGivenValueForNullKey() { + // Given + Statistics statistics = new Statistics(); + // When + statistics.incCounter(null, 5); + // Then + assertThat(statistics.getStat(null), is(nullValue())); + } + @Test void shouldIncreaseExistingCounterWithGivenValue() throws Exception { // Given @@ -107,6 +127,16 @@ void shouldDecreaseCounter() throws Exception { assertThat(statistics.getStat(STAT_KEY), is(equalTo(-1L))); } + @Test + void shouldIgnoreDecreaseCounterForNullKey() { + // Given + Statistics statistics = new Statistics(); + // When + statistics.decCounter(null); + // Then + assertThat(statistics.getStat(null), is(nullValue())); + } + @Test void shouldDecreaseExistingCounter() throws Exception { // Given @@ -128,6 +158,16 @@ void shouldDecreaseCounterWithGivenValue() throws Exception { assertThat(statistics.getStat(STAT_KEY), is(equalTo(-5L))); } + @Test + void shouldIgnoreDecreaseCounterWithGivenValueForNullKey() { + // Given + Statistics statistics = new Statistics(); + // When + statistics.decCounter(null, 5); + // Then + assertThat(statistics.getStat(null), is(nullValue())); + } + @Test void shouldDecreaseExistingCounterWithGivenValue() throws Exception { // Given @@ -182,6 +222,19 @@ void shouldReturnNoStatsIfNoneWithGivenPrefix() throws Exception { assertThat(stats.size(), is(equalTo(0))); } + @Test + void shouldReturnNoStatsWithNullPrefix() { + // Given + Statistics statistics = new Statistics(); + statistics.incCounter("other.stats.a"); + statistics.incCounter("other.stats.b"); + statistics.incCounter("other.stats.c"); + // When + Map stats = statistics.getStats(null); + // Then + assertThat(stats.size(), is(equalTo(0))); + } + @Test void shouldClearAllStats() throws Exception { // Given @@ -213,4 +266,43 @@ void shouldClearStatsWithSamePrefix() throws Exception { assertThat(statistics.getStat("other.stats.a"), is(not(nullValue()))); assertThat(statistics.getStat("other.stats.b"), is(not(nullValue()))); } + + @Test + void shouldIgnoreClearStatsWithNullPrefix() { + // Given + Statistics statistics = new Statistics(); + statistics.incCounter("stats"); + statistics.incCounter("stats.a"); + statistics.incCounter("stats.b"); + statistics.incCounter("other.stats.a"); + statistics.incCounter("other.stats.b"); + // When + statistics.clear(null); + // Then + assertThat(statistics.getStat("stats"), is(equalTo(1L))); + assertThat(statistics.getStat("stats.a"), is(equalTo(1L))); + assertThat(statistics.getStat("stats.b"), is(equalTo(1L))); + assertThat(statistics.getStat("other.stats.a"), is(equalTo(1L))); + assertThat(statistics.getStat("other.stats.b"), is(equalTo(1L))); + } + + @Test + void shouldIgnoreSetHighwaterMarkForNullKey() { + // Given + Statistics statistics = new Statistics(); + // When + statistics.setHighwaterMark(null, 10); + // Then + assertThat(statistics.getStat(null), is(nullValue())); + } + + @Test + void shouldIgnoreSetLowwaterMarkForNullKey() { + // Given + Statistics statistics = new Statistics(); + // When + statistics.setLowwaterMark(null, 10); + // Then + assertThat(statistics.getStat(null), is(nullValue())); + } }