Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.rpc.model.ApplicationModel;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
Expand Down Expand Up @@ -61,6 +62,7 @@
import java.util.function.Supplier;

import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_REFLECTIVE_OPERATION_FAILED;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_UNTRUSTED_SERIALIZE_CLASS;
import static org.apache.dubbo.common.utils.ClassUtils.isAssignableFrom;

/**
Expand Down Expand Up @@ -464,6 +466,22 @@ private static Object realize1(
}
}

// When the Map does not carry a "class" key, the type comes from the
// method signature. We still need to enforce the Serializable contract
// so that non-Serializable DTOs are rejected consistently (they are
// already rejected when a "class" key is present, via
// DefaultSerializeClassChecker.loadClass).
if (!(className instanceof String) && !type.isPrimitive() && !Serializable.class.isAssignableFrom(type)) {
DefaultSerializeClassChecker checker = DefaultSerializeClassChecker.getInstance();
String msg = "[Serialization Security] Serialized class " + type.getName()
+ " has not implement Serializable interface. "
+ "Current mode is strict check, will disallow to deserialize it by default. ";
logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg);
if (checker.isCheckSerializable()) {
throw new IllegalArgumentException(msg);
}
}

// special logic for enum
if (type.isEnum()) {
Object name = ((Map<Object, Object>) pojo).get("name");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1286,4 +1286,46 @@ interface Message {

boolean isUrgent();
}

/**
* Non-Serializable POJO used to verify that PojoUtils.realize enforces
* the Serializable contract even when the generic Map has no "class" key.
* See <a href="https://github.com/apache/dubbo/issues/16270">issue #16270</a>.
*/
public static class NonSerializableDto {
private String label;
private Integer sequence;

public NonSerializableDto() {}

public String getLabel() {
return label;
}

public void setLabel(String label) {
this.label = label;
}

public Integer getSequence() {
return sequence;
}

public void setSequence(Integer sequence) {
this.sequence = sequence;
}
}

@Test
void test_realize_rejectsNonSerializableMapWithoutClassKey() {
// A generic Map that does NOT carry a "class" entry.
Map<String, Object> data = new LinkedHashMap<>();
data.put("label", "no-class-key");
data.put("sequence", 100);

// PojoUtils.realize should reject the non-Serializable target type
// even when the Map has no "class" key (issue #16270).
Assertions.assertThrows(IllegalArgumentException.class, () -> {
PojoUtils.realize(data, NonSerializableDto.class, NonSerializableDto.class);
});
}
}
Loading