Added tests for UnsafeDeserialization.ql and Jackson

This commit is contained in:
Artem Smotrakov
2021-05-15 11:37:59 +02:00
parent ea0991c980
commit aefd21075b
76 changed files with 538 additions and 4 deletions

View File

@@ -0,0 +1,28 @@
---
sourceLocationPrefix: "/media/i504100/Artem_Flash_1T/codeql-bounties/codeql-repo/java/ql/src"
unicodeNewlines: false
columnKind: "utf16"
primaryLanguage: "java"
inProgress:
primaryLanguage: "java"
installedExtractors:
cpp:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/cpp/"
csharp:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/csharp/"
csv:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/csv/"
go:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/go/"
html:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/html/"
java:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/java/"
javascript:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/javascript/"
properties:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/properties/"
python:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/python/"
xml:
- "file:///media/i504100/Artem_Flash_1T/codeql-bounties/codeql-cli/xml/"

View File

@@ -0,0 +1 @@
[2021-06-14 08:53:54] [javac-extractor-9926] [ERROR] 10 errors were reported by javac.

View File

@@ -0,0 +1,9 @@
[2021-06-14 08:53:53] [javac-extractor-9926] Starting extraction for:
sun.java.command=com.semmle.extractor.java.JavaExtractor --javacOptions -source 8 --strict-javac-errors --encoding UTF-8 --files SafeMacComparison.java UnsafeMacComparison.java
user.dir=/media/i504100/Artem_Flash_1T/codeql-bounties/codeql-repo/java/ql/src/experimental/Security/CWE/CWE-208
[2021-06-14 08:53:54] [javac-extractor-9926] Javac init time: 0.6s
[2021-06-14 08:53:54] [javac-extractor-9926] Javac attr time: 0.0s
[2021-06-14 08:53:54] [javac-extractor-9926] Extractor time: 0.0s
[2021-06-14 08:53:54] [javac-extractor-9926] Other time: 0.2s
[2021-06-14 08:53:54] [javac-extractor-9926] Total time: 0.7s
[2021-06-14 08:53:54] [javac-extractor-9926] [ERROR] 10 errors were reported by javac.

View File

@@ -0,0 +1,31 @@
[2021-06-14 08:53:53] [javac-output-9926] warning: [options] bootstrap class path not set in conjunction with -source 8
[2021-06-14 08:53:53] [javac-output-9926] SafeMacComparison.java:1: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] public boolean check(byte[] expected, byte[] data, SecretKey key) throws Exception {
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] SafeMacComparison.java:3: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] mac.init(new SecretKeySpec(key.getEncoded(), "HmacSHA256"));
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] SafeMacComparison.java:4: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] byte[] actual = mac.doFinal(data);
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] SafeMacComparison.java:5: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] return MessageDigest.isEqual(expected, actual);
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] SafeMacComparison.java:6: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] }
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] UnsafeMacComparison.java:1: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] public boolean check(byte[] expected, byte[] data, SecretKey key) throws Exception {
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] UnsafeMacComparison.java:3: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] mac.init(new SecretKeySpec(key.getEncoded(), "HmacSHA256"));
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] UnsafeMacComparison.java:4: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] byte[] actual = mac.doFinal(data);
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] UnsafeMacComparison.java:5: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] return Arrays.equals(expected, actual);
[2021-06-14 08:53:53] [javac-output-9926] ^
[2021-06-14 08:53:53] [javac-output-9926] UnsafeMacComparison.java:6: error: class, interface, or enum expected
[2021-06-14 08:53:53] [javac-output-9926] }
[2021-06-14 08:53:53] [javac-output-9926] ^

View File

@@ -274,11 +274,19 @@ predicate createJacksonTreeNodeStep(DataFlow::Node fromNode, DataFlow::Node toNo
)
}
/**
* Holds if `type` or one of its supertypes has a field with `JsonTypeInfo` annotation
* that enables polymorphic type handling.
*/
predicate hasJsonTypeInfoAnnotation(RefType type) {
hasFieldWithJsonTypeAnnotation(type.getASupertype*()) or
hasFieldWithJsonTypeAnnotation(type.getAField().getType())
}
/**
* Holds if `type` has a field with `JsonTypeInfo` annotation
* that enables polymorphic type handling.
*/
predicate hasFieldWithJsonTypeAnnotation(RefType type) {
exists(Annotation a |
type.getAField().getAnAnnotation() = a and

View File

@@ -0,0 +1,193 @@
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import java.io.IOException;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
public class JacksonTest {
public static void withSocket(Action<String> action) throws Exception {
try (ServerSocket serverSocket = new ServerSocket(0)) {
try (Socket socket = serverSocket.accept()) {
byte[] bytes = new byte[1024];
int n = socket.getInputStream().read(bytes);
String jexlExpr = new String(bytes, 0, n);
action.run(jexlExpr);
}
}
}
}
interface Action<T> {
void run(T object) throws Exception;
}
abstract class PhoneNumber implements Serializable {
public int areaCode;
public int local;
}
class DomesticNumber extends PhoneNumber {
}
class InternationalNumber extends PhoneNumber {
public int countryCode;
}
class Employee extends Person {
}
class Person {
public String name;
public int age;
// this annotation enables polymorphic type handling
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public Object phone;
}
class Task {
public Person assignee;
}
class Tag implements Serializable {
public String title;
}
class Cat {
public String name;
public Serializable tag;
}
class UnsafePersonDeserialization {
// BAD: Person has a field with an annotation that enables polymorphic type
// handling
private static void testUnsafeDeserialization() throws Exception {
JacksonTest.withSocket(string -> {
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(string, Person.class);
});
}
// BAD: Employee extends Person that has a field with an annotation that enables
// polymorphic type handling
private static void testUnsafeDeserializationWithExtendedClass() throws Exception {
JacksonTest.withSocket(string -> {
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(string, Employee.class);
});
}
// BAD: Task has a Person field that has a field with an annotation that enables
// polymorphic type handling
private static void testUnsafeDeserializationWithWrapper() throws Exception {
JacksonTest.withSocket(string -> {
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(string, Task.class);
});
}
}
class SaferPersonDeserialization {
// GOOD: Despite enabled polymorphic type handling, this is safe because ObjectMapper
// has a validator
private static void testSafeDeserializationWithValidator() throws Exception {
JacksonTest.withSocket(string -> {
PolymorphicTypeValidator ptv =
BasicPolymorphicTypeValidator.builder()
.allowIfSubType("only.allowed.package")
.build();
ObjectMapper mapper = new ObjectMapper();
mapper.setPolymorphicTypeValidator(ptv);
mapper.readValue(string, Person.class);
});
}
// GOOD: Despite enabled polymorphic type handling, this is safe because ObjectMapper
// has a validator
private static void testSafeDeserializationWithValidatorAndBuilder() throws Exception {
JacksonTest.withSocket(string -> {
PolymorphicTypeValidator ptv =
BasicPolymorphicTypeValidator.builder()
.allowIfSubType("only.allowed.package")
.build();
ObjectMapper mapper = JsonMapper.builder()
.polymorphicTypeValidator(ptv)
.build();
mapper.readValue(string, Person.class);
});
}
}
class UnsafeCatDeserialization {
// BAD: deserializing untrusted input while polymorphic type handling is on
private static void testUnsafeDeserialization() throws Exception {
JacksonTest.withSocket(string -> {
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(); // this enables polymorphic type handling
mapper.readValue(string, Cat.class);
});
}
// BAD: deserializing untrusted input while polymorphic type handling is on
private static void testUnsafeDeserializationWithObjectMapperReadValues() throws Exception {
JacksonTest.withSocket(string -> {
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
mapper.readValues(new JsonFactory().createParser(string), Cat.class).readAll();
});
}
// BAD: deserializing untrusted input while polymorphic type handling is on
private static void testUnsafeDeserializationWithObjectMapperTreeToValue() throws Exception {
JacksonTest.withSocket(string -> {
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
mapper.treeToValue(mapper.readTree(string), Cat.class);
});
}
// BAD: an attacker can control both data and type of deserialized object
private static void testUnsafeDeserializationWithUnsafeClass() throws Exception {
JacksonTest.withSocket(input -> {
String[] parts = input.split(";");
String data = parts[0];
String type = parts[1];
Class clazz = Class.forName(type);
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(data, clazz);
});
}
}
class SaferCatDeserialization {
// GOOD: Despite enabled polymorphic type handling, this is safe because ObjectMapper
// has a validator
private static void testUnsafeDeserialization() throws Exception {
JacksonTest.withSocket(string -> {
PolymorphicTypeValidator ptv =
BasicPolymorphicTypeValidator.builder()
.allowIfSubType("only.allowed.pachage")
.build();
ObjectMapper mapper = JsonMapper.builder().polymorphicTypeValidator(ptv).build();
mapper.enableDefaultTyping(); // this enables polymorphic type handling
mapper.readValue(string, Cat.class);
});
}
}

View File

@@ -80,6 +80,22 @@ edges
| C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:87:3:87:13 | burlapInput |
| C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:91:3:91:14 | burlapInput1 |
| C.java:85:54:85:67 | serializedData : byte[] | C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream |
| JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | JacksonTest.java:19:54:19:58 | bytes [post update] : byte[] |
| JacksonTest.java:19:54:19:58 | bytes [post update] : byte[] | JacksonTest.java:21:28:21:35 | jexlExpr : String |
| JacksonTest.java:21:28:21:35 | jexlExpr : String | JacksonTest.java:73:32:73:37 | string : String |
| JacksonTest.java:21:28:21:35 | jexlExpr : String | JacksonTest.java:82:32:82:37 | string : String |
| JacksonTest.java:21:28:21:35 | jexlExpr : String | JacksonTest.java:91:32:91:37 | string : String |
| JacksonTest.java:21:28:21:35 | jexlExpr : String | JacksonTest.java:138:32:138:37 | string : String |
| JacksonTest.java:21:28:21:35 | jexlExpr : String | JacksonTest.java:147:32:147:37 | string : String |
| JacksonTest.java:21:28:21:35 | jexlExpr : String | JacksonTest.java:156:32:156:37 | string : String |
| JacksonTest.java:21:28:21:35 | jexlExpr : String | JacksonTest.java:165:32:165:36 | input : String |
| JacksonTest.java:73:32:73:37 | string : String | JacksonTest.java:75:30:75:35 | string |
| JacksonTest.java:82:32:82:37 | string : String | JacksonTest.java:84:30:84:35 | string |
| JacksonTest.java:91:32:91:37 | string : String | JacksonTest.java:93:30:93:35 | string |
| JacksonTest.java:138:32:138:37 | string : String | JacksonTest.java:141:30:141:35 | string |
| JacksonTest.java:147:32:147:37 | string : String | JacksonTest.java:150:31:150:68 | createParser(...) |
| JacksonTest.java:156:32:156:37 | string : String | JacksonTest.java:159:32:159:54 | readTree(...) |
| JacksonTest.java:165:32:165:36 | input : String | JacksonTest.java:171:30:171:33 | data |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream |
| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
@@ -176,6 +192,23 @@ nodes
| C.java:85:54:85:67 | serializedData : byte[] | semmle.label | serializedData : byte[] |
| C.java:87:3:87:13 | burlapInput | semmle.label | burlapInput |
| C.java:91:3:91:14 | burlapInput1 | semmle.label | burlapInput1 |
| JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| JacksonTest.java:19:54:19:58 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
| JacksonTest.java:21:28:21:35 | jexlExpr : String | semmle.label | jexlExpr : String |
| JacksonTest.java:73:32:73:37 | string : String | semmle.label | string : String |
| JacksonTest.java:75:30:75:35 | string | semmle.label | string |
| JacksonTest.java:82:32:82:37 | string : String | semmle.label | string : String |
| JacksonTest.java:84:30:84:35 | string | semmle.label | string |
| JacksonTest.java:91:32:91:37 | string : String | semmle.label | string : String |
| JacksonTest.java:93:30:93:35 | string | semmle.label | string |
| JacksonTest.java:138:32:138:37 | string : String | semmle.label | string : String |
| JacksonTest.java:141:30:141:35 | string | semmle.label | string |
| JacksonTest.java:147:32:147:37 | string : String | semmle.label | string : String |
| JacksonTest.java:150:31:150:68 | createParser(...) | semmle.label | createParser(...) |
| JacksonTest.java:156:32:156:37 | string : String | semmle.label | string : String |
| JacksonTest.java:159:32:159:54 | readTree(...) | semmle.label | readTree(...) |
| JacksonTest.java:165:32:165:36 | input : String | semmle.label | input : String |
| JacksonTest.java:171:30:171:33 | data | semmle.label | data |
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | semmle.label | entityStream : InputStream |
| TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | semmle.label | new ObjectInputStream(...) |
| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | semmle.label | entityStream : InputStream |
@@ -226,4 +259,11 @@ nodes
| C.java:79:3:79:72 | unmarshal(...) | C.java:79:43:79:70 | getParameter(...) : String | C.java:79:26:79:71 | new StringReader(...) | Unsafe deserialization of $@. | C.java:79:43:79:70 | getParameter(...) | user input |
| C.java:87:3:87:26 | readObject(...) | C.java:84:27:84:54 | getParameter(...) : String | C.java:87:3:87:13 | burlapInput | Unsafe deserialization of $@. | C.java:84:27:84:54 | getParameter(...) | user input |
| C.java:91:3:91:27 | readObject(...) | C.java:84:27:84:54 | getParameter(...) : String | C.java:91:3:91:14 | burlapInput1 | Unsafe deserialization of $@. | C.java:84:27:84:54 | getParameter(...) | user input |
| JacksonTest.java:75:13:75:50 | readValue(...) | JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | JacksonTest.java:75:30:75:35 | string | Unsafe deserialization of $@. | JacksonTest.java:19:25:19:47 | getInputStream(...) | user input |
| JacksonTest.java:84:13:84:52 | readValue(...) | JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | JacksonTest.java:84:30:84:35 | string | Unsafe deserialization of $@. | JacksonTest.java:19:25:19:47 | getInputStream(...) | user input |
| JacksonTest.java:93:13:93:48 | readValue(...) | JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | JacksonTest.java:93:30:93:35 | string | Unsafe deserialization of $@. | JacksonTest.java:19:25:19:47 | getInputStream(...) | user input |
| JacksonTest.java:141:13:141:47 | readValue(...) | JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | JacksonTest.java:141:30:141:35 | string | Unsafe deserialization of $@. | JacksonTest.java:19:25:19:47 | getInputStream(...) | user input |
| JacksonTest.java:150:13:150:80 | readValues(...) | JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | JacksonTest.java:150:31:150:68 | createParser(...) | Unsafe deserialization of $@. | JacksonTest.java:19:25:19:47 | getInputStream(...) | user input |
| JacksonTest.java:159:13:159:66 | treeToValue(...) | JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | JacksonTest.java:159:32:159:54 | readTree(...) | Unsafe deserialization of $@. | JacksonTest.java:19:25:19:47 | getInputStream(...) | user input |
| JacksonTest.java:171:13:171:41 | readValue(...) | JacksonTest.java:19:25:19:47 | getInputStream(...) : InputStream | JacksonTest.java:171:30:171:33 | data | Unsafe deserialization of $@. | JacksonTest.java:19:25:19:47 | getInputStream(...) | user input |
| TestMessageBodyReader.java:22:18:22:65 | readObject(...) | TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | Unsafe deserialization of $@. | TestMessageBodyReader.java:20:55:20:78 | entityStream | user input |

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.10

View File

@@ -0,0 +1,27 @@
package com.fasterxml.jackson.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonTypeInfo {
JsonTypeInfo.Id use();
public static enum Id {
CLASS("@class"),
MINIMAL_CLASS("@c");
private final String _defaultPropertyName;
private Id(String defProp) {
this._defaultPropertyName = defProp;
}
public String getDefaultPropertyName() {
return this._defaultPropertyName;
}
}
}

View File

@@ -9,4 +9,8 @@ public class JsonFactory {
public JsonGenerator createGenerator(Writer writer) {
return new JsonGenerator();
}
public JsonParser createParser(String content) {
return null;
}
}

View File

@@ -0,0 +1,3 @@
package com.fasterxml.jackson.core;
public abstract class JsonParser {}

View File

@@ -0,0 +1,3 @@
package com.fasterxml.jackson.core;
public interface TreeNode {}

View File

@@ -1,8 +1,8 @@
package com.fasterxml.jackson.databind;
import java.util.*;
import com.fasterxml.jackson.core.TreeNode;
public abstract class JsonNode implements Iterable<JsonNode> {
public JsonNode() {
}
public abstract class JsonNode implements TreeNode, Iterable<JsonNode> {
public JsonNode() {}
}

View File

@@ -25,4 +25,8 @@ public class MappingIterator<T> implements Iterator<T>, Closeable {
public void close() throws IOException {
}
public List<T> readAll() {
return null;
}
}

View File

@@ -1,5 +1,8 @@
package com.fasterxml.jackson.databind;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import java.io.*;
import java.util.*;
@@ -38,4 +41,28 @@ public class ObjectMapper {
public <T> T convertValue(Object fromValue, Class<T> toValueType) throws IllegalArgumentException {
return null;
}
public ObjectMapper setPolymorphicTypeValidator(PolymorphicTypeValidator ptv) {
return null;
}
public ObjectMapper enableDefaultTyping() {
return null;
}
public <T> T readValue(String content, Class<T> valueType) {
return null;
}
public <T> MappingIterator<T> readValues(JsonParser p, Class<T> valueType) {
return null;
}
public <T> T treeToValue(TreeNode n, Class<T> valueType) {
return null;
}
public JsonNode readTree(String content) {
return null;
}
}

View File

@@ -0,0 +1,9 @@
package com.fasterxml.jackson.databind.cfg;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
public abstract class MapperBuilder<M extends ObjectMapper, B extends MapperBuilder<M, B>> {
public M build() { return null; }
public B polymorphicTypeValidator(PolymorphicTypeValidator ptv) { return null; }
}

View File

@@ -0,0 +1,9 @@
package com.fasterxml.jackson.databind.json;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.MapperBuilder;
public class JsonMapper extends ObjectMapper {
public static JsonMapper.Builder builder() { return null; }
public static class Builder extends MapperBuilder<JsonMapper, JsonMapper.Builder> {}
}

View File

@@ -0,0 +1,10 @@
package com.fasterxml.jackson.databind.jsontype;
public class BasicPolymorphicTypeValidator extends PolymorphicTypeValidator {
public static BasicPolymorphicTypeValidator.Builder builder() { return null; }
public static class Builder {
public BasicPolymorphicTypeValidator.Builder allowIfSubType(final String prefixForSubType) { return null; }
public BasicPolymorphicTypeValidator build() { return null; }
}
}

View File

@@ -0,0 +1,3 @@
package com.fasterxml.jackson.databind.jsontype;
public abstract class PolymorphicTypeValidator {}