diff options
author | Fabian Meumertzheim <fabian@meumertzhe.im> | 2022-03-08 12:54:20 +0100 |
---|---|---|
committer | Fabian Meumertzheim <fabian@meumertzhe.im> | 2022-03-09 11:57:17 +0100 |
commit | 59d16517cd5ae8d743d570ee24fed2403fdd4682 (patch) | |
tree | 478eec3e250397b0df05e149f6e42dc800b94f83 /agent/src | |
parent | 95520d2b1090934af983b2342770238084557d31 (diff) | |
download | jazzer-api-59d16517cd5ae8d743d570ee24fed2403fdd4682.tar.gz |
Fix ClassCastException in mapGet hook
If the argument to Map#get cannot be compared to the keys in the map due
to an incompatible type, the hook threw a ClassCastException.
To address this, we:
* Catch and ignore ClassCastException where it could be thrown.
* Reverse the compareTo calls so that the likely more lenient compareTo
function of the valid map key is used.
The original OSS-Fuzz finding that uncovered this bug:
== Java Exception: java.lang.ClassCastException: class com.alibaba.fastjson.JSONObject cannot be cast to class java.lang.Integer (com.alibaba.fastjson.JSONObject is in unnamed module of loader 'app'; java.lang.Integer is in module java.base of loader 'bootstrap')
at java.base/java.lang.Integer.compareTo(Integer.java:64)
at com.code_intelligence.jazzer.runtime.TraceCmpHooks.mapGet(TraceCmpHooks.java:308)
at com.alibaba.fastjson.JSONObject.get(JSONObject.java:110)
at com.alibaba.fastjson.JSONPath.getArrayItem(JSONPath.java:3577)
at com.alibaba.fastjson.JSONPath$ArrayAccessSegment.eval(JSONPath.java:2736)
at com.alibaba.fastjson.JSONPath.eval(JSONPath.java:121)
at com.alibaba.fastjson.parser.DefaultJSONParser.handleResovleTask(DefaultJSONParser.java:1599)
at com.alibaba.fastjson.JSON.parse(JSON.java:183)
at com.alibaba.fastjson.JSON.parse(JSON.java:191)
at com.alibaba.fastjson.JSON.parse(JSON.java:147)
at JsonFuzzer.fuzzerTestOneInput(JsonFuzzer.java:24)
Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=42365
Diffstat (limited to 'agent/src')
-rw-r--r-- | agent/src/main/java/com/code_intelligence/jazzer/runtime/TraceCmpHooks.java | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/agent/src/main/java/com/code_intelligence/jazzer/runtime/TraceCmpHooks.java b/agent/src/main/java/com/code_intelligence/jazzer/runtime/TraceCmpHooks.java index c7d4947e..e6d74187 100644 --- a/agent/src/main/java/com/code_intelligence/jazzer/runtime/TraceCmpHooks.java +++ b/agent/src/main/java/com/code_intelligence/jazzer/runtime/TraceCmpHooks.java @@ -293,25 +293,36 @@ final public class TraceCmpHooks { Object upperBoundKey = null; if (map instanceof TreeMap) { final TreeMap treeMap = (TreeMap) map; - lowerBoundKey = treeMap.floorKey(currentKey); - upperBoundKey = treeMap.ceilingKey(currentKey); + try { + lowerBoundKey = treeMap.floorKey(currentKey); + upperBoundKey = treeMap.ceilingKey(currentKey); + } catch (ClassCastException ignored) { + // Can be thrown by floorKey and ceilingKey if currentKey is of a type that can't be + // compared to the maps keys. + } } else if (currentKey instanceof Comparable) { - final Comparable comparableKey = (Comparable) currentKey; + final Comparable comparableCurrentKey = (Comparable) currentKey; // Find two keys that bracket currentKey. // Note: This is not deterministic if map.size() > MAX_NUM_KEYS_TO_ENUMERATE. int enumeratedKeys = 0; for (Object validKey : map.keySet()) { - if (validKey == null) + if (!(validKey instanceof Comparable)) continue; + final Comparable comparableValidKey = (Comparable) validKey; // If the key sorts lower than the non-existing key, but higher than the current lower // bound, update the lower bound and vice versa for the upper bound. - if (comparableKey.compareTo(validKey) > 0 - && (lowerBoundKey == null || ((Comparable) validKey).compareTo(lowerBoundKey) > 0)) { - lowerBoundKey = validKey; - } - if (comparableKey.compareTo(validKey) < 0 - && (upperBoundKey == null || ((Comparable) validKey).compareTo(upperBoundKey) < 0)) { - upperBoundKey = validKey; + try { + if (comparableValidKey.compareTo(comparableCurrentKey) < 0 + && (lowerBoundKey == null || comparableValidKey.compareTo(lowerBoundKey) > 0)) { + lowerBoundKey = validKey; + } + if (comparableValidKey.compareTo(comparableCurrentKey) > 0 + && (upperBoundKey == null || comparableValidKey.compareTo(upperBoundKey) < 0)) { + upperBoundKey = validKey; + } + } catch (ClassCastException ignored) { + // Can be thrown by floorKey and ceilingKey if currentKey is of a type that can't be + // compared to the maps keys. } if (enumeratedKeys++ > MAX_NUM_KEYS_TO_ENUMERATE) break; |