[ 
https://issues.apache.org/jira/browse/LANG-1799?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Gary D. Gregory updated LANG-1799:
----------------------------------
    Summary: Make private static variables final in RandomStringUtils  (was: 
Non-final Static Singleton Variables Break Thread Safety and Singleton Design 
in RandomStringUtils)

> Make private static variables final in RandomStringUtils
> --------------------------------------------------------
>
>                 Key: LANG-1799
>                 URL: https://issues.apache.org/jira/browse/LANG-1799
>             Project: Commons Lang
>          Issue Type: Bug
>          Components: lang.*
>    Affects Versions: 3.20.0
>            Reporter: Zhongxin Yan
>            Priority: Major
>
> The RandomStringUtils class exposes three primary singleton instances 
> (INSECURE, SECURE, SECURE_STRONG) through static fields that are currently 
> missing the final keyword.
>  
> {code:java}
> private static RandomStringUtils INSECURE = new 
> RandomStringUtils(RandomUtils::insecure);
> private static RandomStringUtils SECURE = new 
> RandomStringUtils(SECURE_SUPPLIER);
> private static RandomStringUtils SECURE_STRONG = new 
> RandomStringUtils(RandomUtils::secureStrong);
>  {code}
> h3. Key Issues Caused by Non-final Modifier:
>  * {*}Unintended Reassignment{*}: The variables can be modified at runtime 
> (e.g., via reflection, accidental code changes, or subclassing), breaking the 
> singleton contract and leading to inconsistent random string generation 
> behavior across the application.
>  * {*}Violation of Documentation{*}: The class Javadoc explicitly labels it 
> {{{}#ThreadSafe#{}}}, but non-final static state undermines this promise.
>  
> {code:java}
> // Test
> /**
>  * Test case to demonstrate the security and robustness risk introduced
>  * by the non-final static singleton fields in RandomStringUtils.
>  * * NOTE: This test should fail when the code is fixed (i.e., when fields 
> are made final).
>  */
> public class RandomStringUtilsNonFinalSingletonTest {
>     private static final String FIELD_NAME = "SECURE";
>     /**
>      * Attempts to corrupt the static singleton reference via reflection.
>      */
>     @Test
>     void testNonFinalStaticSingletonCorruption() throws Exception {
>         // 1. Get the non-final static field
>         Field secureField = 
> RandomStringUtils.class.getDeclaredField(FIELD_NAME);
>         // Ensure the field is NOT final (pre-condition for the bug)
>         
> assertFalse(java.lang.reflect.Modifier.isFinal(secureField.getModifiers()),
>                 "Pre-condition failed: Field should not be final to 
> demonstrate the corruption risk.");
>         // 2. Override accessibility for private field access
>         secureField.setAccessible(true);
>         // 3. Store the original instance for cleanup
>         RandomStringUtils originalInstance = (RandomStringUtils) 
> secureField.get(null);
>         assertNotNull(originalInstance, "Original singleton must be 
> initialized.");
>         try {
>             // 4. CORRUPT THE SINGLETON REFERENCE ***
>             // Setting a static field: pass null as the first argument
>             secureField.set(null, null);
>             // 5. Verify corruption succeeded
>             assertNull(secureField.get(null), "Non-final static field was 
> successfully set to null.");
>             // 6. Assert that subsequent application logic fails with NPE
>             // This proves the integrity of the singleton has been 
> compromised.
>             assertThrows(NullPointerException.class, () -> {
>                 // The call to RandomStringUtils.secure() returns null, and 
> .next(1) fails.
>                 RandomStringUtils.secure().next(1);
>             }, "Subsequent calls to the corrupted singleton must throw NPE.");
>         } finally {
>             // Cleanup: Restore the original instance to avoid breaking other 
> tests
>             if (secureField.get(null) == null) {
>                 secureField.set(null, originalInstance);
>             }
>         }
>     }
> }{code}
> [github pr|https://github.com/apache/commons-lang/pull/1513]
>  
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to