From f129a67fd2da3c590db057575d2e4e50a76b64fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Csahvx655-wq=E2=80=9D?= <“sahvx655@gmail.com”> Date: Wed, 3 Jun 2026 12:30:45 +0530 Subject: [PATCH] Fix state leakage of otherCountryCodes in IBANValidator custom configurations --- .../validator/routines/IBANValidator.java | 19 ++++++++- .../validator/routines/IBANValidatorTest.java | 40 +++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/validator/routines/IBANValidator.java b/src/main/java/org/apache/commons/validator/routines/IBANValidator.java index 3e6e72dd5..5de5d5fb4 100644 --- a/src/main/java/org/apache/commons/validator/routines/IBANValidator.java +++ b/src/main/java/org/apache/commons/validator/routines/IBANValidator.java @@ -376,7 +376,13 @@ public Validator setValidator(final String countryCode, final int length, final throw new IllegalStateException("The singleton validator cannot be modified"); } if (length < 0) { - return validatorMap.remove(countryCode); + final Validator prev = validatorMap.remove(countryCode); + if (prev != null) { + for (final String otherCC : prev.otherCountryCodes) { + validatorMap.remove(otherCC); + } + } + return prev; } return setValidator(new Validator(countryCode, length, format)); } @@ -393,7 +399,16 @@ public Validator setValidator(final Validator validator) { if (this == DEFAULT_IBAN_VALIDATOR) { throw new IllegalStateException("The singleton validator cannot be modified"); } - return validatorMap.put(validator.countryCode, validator); + final Validator prev = validatorMap.put(validator.countryCode, validator); + if (prev != null) { + for (final String otherCC : prev.otherCountryCodes) { + validatorMap.remove(otherCC); + } + } + for (final String otherCC : validator.otherCountryCodes) { + validatorMap.put(otherCC, validator); + } + return prev; } /** diff --git a/src/test/java/org/apache/commons/validator/routines/IBANValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/IBANValidatorTest.java index 2a0f62297..8a7009cba 100644 --- a/src/test/java/org/apache/commons/validator/routines/IBANValidatorTest.java +++ b/src/test/java/org/apache/commons/validator/routines/IBANValidatorTest.java @@ -465,6 +465,46 @@ void testSetValidatorLen1() { assertNull(validator.setValidator("GB", -1, ""), "no longer present"); } + @Test + void testSetValidatorCleanupOtherCountryCodes() { + final IBANValidator validator = new IBANValidator(); + + // Confirm GB (United Kingdom) handles IM (Isle of Man), JE (Jersey), GG (Guernsey) by default + assertTrue(validator.hasValidator("GB")); + assertTrue(validator.hasValidator("IM")); + assertTrue(validator.hasValidator("JE")); + assertTrue(validator.hasValidator("GG")); + + // Remove GB validator + assertNotNull(validator.setValidator("GB", -1, null)); + + // Verify that GB and all associated territories are removed + assertFalse(validator.hasValidator("GB")); + assertFalse(validator.hasValidator("IM")); + assertFalse(validator.hasValidator("JE")); + assertFalse(validator.hasValidator("GG")); + } + + @Test + void testSetValidatorReplaceOtherCountryCodes() { + final IBANValidator validator = new IBANValidator(); + + // Confirm GB handles IM by default + assertTrue(validator.hasValidator("GB")); + assertTrue(validator.hasValidator("IM")); + final Validator oldGbValidator = validator.getValidator("GB"); + final Validator oldImValidator = validator.getValidator("IM"); + assertEquals(oldGbValidator, oldImValidator); + + // Replace GB validator with a custom one (which will have no other country codes) + final Validator newGbValidator = new Validator("GB", 22, "GB\\d{20}"); + validator.setValidator(newGbValidator); + + // Verify GB has the new validator, but IM no longer has the old validator + assertEquals(newGbValidator, validator.getValidator("GB")); + assertFalse(validator.hasValidator("IM")); + } + @Test void testSetValidatorLen35() { final IBANValidator validator = new IBANValidator();