1033
1034 /**
1035 * Verifies that this (possibly subclass) instance can be constructed
1036 * without violating security constraints: the subclass must not override
1037 * security-sensitive non-final methods, or else the
1038 * "enableSubclassImplementation" SerializablePermission is checked.
1039 */
1040 private void verifySubclass() {
1041 Class<?> cl = getClass();
1042 if (cl == ObjectOutputStream.class) {
1043 return;
1044 }
1045 SecurityManager sm = System.getSecurityManager();
1046 if (sm == null) {
1047 return;
1048 }
1049 processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
1050 WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
1051 Boolean result = Caches.subclassAudits.get(key);
1052 if (result == null) {
1053 result = Boolean.valueOf(auditSubclass(cl));
1054 Caches.subclassAudits.putIfAbsent(key, result);
1055 }
1056 if (result.booleanValue()) {
1057 return;
1058 }
1059 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
1060 }
1061
1062 /**
1063 * Performs reflective checks on given subclass to verify that it doesn't
1064 * override security-sensitive non-final methods. Returns true if subclass
1065 * is "safe", false otherwise.
1066 */
1067 private static boolean auditSubclass(final Class<?> subcl) {
1068 Boolean result = AccessController.doPrivileged(
1069 new PrivilegedAction<>() {
1070 public Boolean run() {
1071 for (Class<?> cl = subcl;
1072 cl != ObjectOutputStream.class;
1073 cl = cl.getSuperclass())
1074 {
1075 try {
1076 cl.getDeclaredMethod(
1077 "writeUnshared", new Class<?>[] { Object.class });
1078 return Boolean.FALSE;
1079 } catch (NoSuchMethodException ex) {
1080 }
1081 try {
1082 cl.getDeclaredMethod("putFields", (Class<?>[]) null);
1083 return Boolean.FALSE;
1084 } catch (NoSuchMethodException ex) {
1085 }
1086 }
1087 return Boolean.TRUE;
1088 }
1089 }
1090 );
1091 return result.booleanValue();
1092 }
1093
1094 /**
1095 * Clears internal data structures.
1096 */
1097 private void clear() {
1098 subs.clear();
1099 handles.clear();
1100 }
1101
1102 /**
1103 * Underlying writeObject/writeUnshared implementation.
1104 */
1105 private void writeObject0(Object obj, boolean unshared)
1106 throws IOException
1107 {
1108 boolean oldMode = bout.setBlockDataMode(false);
1109 depth++;
1110 try {
1111 // handle previously written and non-replaceable objects
|
1033
1034 /**
1035 * Verifies that this (possibly subclass) instance can be constructed
1036 * without violating security constraints: the subclass must not override
1037 * security-sensitive non-final methods, or else the
1038 * "enableSubclassImplementation" SerializablePermission is checked.
1039 */
1040 private void verifySubclass() {
1041 Class<?> cl = getClass();
1042 if (cl == ObjectOutputStream.class) {
1043 return;
1044 }
1045 SecurityManager sm = System.getSecurityManager();
1046 if (sm == null) {
1047 return;
1048 }
1049 processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
1050 WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
1051 Boolean result = Caches.subclassAudits.get(key);
1052 if (result == null) {
1053 result = auditSubclass(cl);
1054 Caches.subclassAudits.putIfAbsent(key, result);
1055 }
1056 if (!result) {
1057 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
1058 }
1059 }
1060
1061 /**
1062 * Performs reflective checks on given subclass to verify that it doesn't
1063 * override security-sensitive non-final methods. Returns TRUE if subclass
1064 * is "safe", FALSE otherwise.
1065 */
1066 private static Boolean auditSubclass(Class<?> subcl) {
1067 return AccessController.doPrivileged(
1068 new PrivilegedAction<>() {
1069 public Boolean run() {
1070 for (Class<?> cl = subcl;
1071 cl != ObjectOutputStream.class;
1072 cl = cl.getSuperclass())
1073 {
1074 try {
1075 cl.getDeclaredMethod(
1076 "writeUnshared", new Class<?>[] { Object.class });
1077 return Boolean.FALSE;
1078 } catch (NoSuchMethodException ex) {
1079 }
1080 try {
1081 cl.getDeclaredMethod("putFields", (Class<?>[]) null);
1082 return Boolean.FALSE;
1083 } catch (NoSuchMethodException ex) {
1084 }
1085 }
1086 return Boolean.TRUE;
1087 }
1088 }
1089 );
1090 }
1091
1092 /**
1093 * Clears internal data structures.
1094 */
1095 private void clear() {
1096 subs.clear();
1097 handles.clear();
1098 }
1099
1100 /**
1101 * Underlying writeObject/writeUnshared implementation.
1102 */
1103 private void writeObject0(Object obj, boolean unshared)
1104 throws IOException
1105 {
1106 boolean oldMode = bout.setBlockDataMode(false);
1107 depth++;
1108 try {
1109 // handle previously written and non-replaceable objects
|