#207 concurrent modification of simplehash

closed-fixed
None
5
2014-02-21
2008-04-10
Alex Burgel
No

i want to iterate through a hash checking for keys and variations of keys. for example:

<#list myhash?keys as key>
<#if myhash[key] == 'foo'>
do something
<#elseif myhash[key + 'variation'] == 'bar'>
do something else
</#if>
</#list>

if key + 'variation' doesn't exist in myhash, then SimpleHash will do a put (SimpleHash line 204), which will cause a ConcurrentModificationException on the next iteration because the hash has been modified.

the reason for the put seems to be to cache the value wrapped in a TemplateModel. i'm sure this is a good thing for performance reasons, but it obviously has its side effects.

the solution is to not add a new entry to the hash. if you are just replacing the value for a particular key with a new value, then you won't trigger a ConcurrentModificationException. but if the key isn't in the hash, then you shouldn't add it.

so after line 202, add this:

if (result == null) return tm;

Discussion

  • Attila Szegedi
    Attila Szegedi
    2008-04-28

    Logged In: YES
    user_id=52489
    Originator: NO

    Fixed on 2.3 branch. 2.4 doesn't seem to have the problem since it was reworked for JAVA_NULL handling.

     
  • Attila Szegedi
    Attila Szegedi
    2008-04-28

    • assigned_to: nobody --> szegedia
    • status: open --> open-fixed
     
    • status: open-fixed --> closed-fixed
     
  • Logged In: YES
    user_id=546667
    Originator: NO

    Fix released with 2.3.13.

     
  • There is still an edge case where this bug is triggered: using a length-1 string key with a null value.

    Example data:

    Map<String, String> map = new TreeMap<>();
    map.put("1", null);
    map.put("2", "foo");
    

    Example template:

    <#list map?keys as key>
      ${map[key]!'null'}
    </#list>
    

    The problem is that SimpleHash sees that map.get("1") returns null and map.get('1') also returns null, but map.containsKey("1") || map.containsKey('1') returns true, so it concludes that the key is '1'. Yet it is "1".

     
    • Just for the record, this issue with length-1 string key with null value is addressed in #409 now.