mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8302111: Serialization considerations
Reviewed-by: skoivu, rhalade, weijun, wetmore
This commit is contained in:
parent
df7d6e081f
commit
369c573383
21 changed files with 747 additions and 468 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -100,11 +100,9 @@ public class SecretKeySpec implements KeySpec, SecretKey {
|
|||
* is null or <code>key</code> is null or empty.
|
||||
*/
|
||||
public SecretKeySpec(byte[] key, String algorithm) {
|
||||
if (key == null || algorithm == null) {
|
||||
throw new IllegalArgumentException("Missing argument");
|
||||
}
|
||||
if (key.length == 0) {
|
||||
throw new IllegalArgumentException("Empty key");
|
||||
String errMsg = doSanityCheck(key, algorithm);
|
||||
if (errMsg != null) {
|
||||
throw new IllegalArgumentException(errMsg);
|
||||
}
|
||||
this.key = key.clone();
|
||||
this.algorithm = algorithm;
|
||||
|
@ -266,14 +264,22 @@ public class SecretKeySpec implements KeySpec, SecretKey {
|
|||
private void readObject(ObjectInputStream stream)
|
||||
throws IOException, ClassNotFoundException {
|
||||
stream.defaultReadObject();
|
||||
String errMsg = doSanityCheck(key, algorithm);
|
||||
if (errMsg != null) {
|
||||
throw new InvalidObjectException(errMsg);
|
||||
}
|
||||
byte[] temp = key;
|
||||
this.key = temp.clone();
|
||||
Arrays.fill(temp, (byte) 0);
|
||||
}
|
||||
|
||||
private static String doSanityCheck(byte[] key, String algorithm) {
|
||||
String errMsg = null;
|
||||
if (key == null || algorithm == null) {
|
||||
throw new InvalidObjectException("Missing argument");
|
||||
}
|
||||
|
||||
this.key = key.clone();
|
||||
if (key.length == 0) {
|
||||
throw new InvalidObjectException("Invalid key length");
|
||||
errMsg = "Missing argument";
|
||||
} else if (key.length == 0) {
|
||||
errMsg = "Empty key";
|
||||
}
|
||||
return errMsg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -102,20 +102,18 @@ public class ChoiceCallback implements Callback, java.io.Serializable {
|
|||
public ChoiceCallback(String prompt, String[] choices,
|
||||
int defaultChoice, boolean multipleSelectionsAllowed) {
|
||||
|
||||
if (prompt == null || prompt.isEmpty() ||
|
||||
choices == null || choices.length == 0 ||
|
||||
defaultChoice < 0 || defaultChoice >= choices.length)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
choices = (choices == null || choices.length == 0 ? choices :
|
||||
choices.clone());
|
||||
String errMsg = doSanityCheck(prompt, choices, defaultChoice,
|
||||
multipleSelectionsAllowed);
|
||||
if (errMsg != null) {
|
||||
throw new IllegalArgumentException(errMsg);
|
||||
}
|
||||
this.prompt = prompt;
|
||||
this.defaultChoice = defaultChoice;
|
||||
this.multipleSelectionsAllowed = multipleSelectionsAllowed;
|
||||
|
||||
this.choices = choices.clone();
|
||||
for (int i = 0; i < choices.length; i++) {
|
||||
if (choices[i] == null || choices[i].isEmpty())
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.choices = choices;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,9 +181,11 @@ public class ChoiceCallback implements Callback, java.io.Serializable {
|
|||
* @see #getSelectedIndexes
|
||||
*/
|
||||
public void setSelectedIndexes(int[] selections) {
|
||||
if (!multipleSelectionsAllowed)
|
||||
if (!multipleSelectionsAllowed) {
|
||||
throw new UnsupportedOperationException();
|
||||
this.selections = selections == null ? null : selections.clone();
|
||||
}
|
||||
this.selections = ((selections == null || selections.length == 0) ?
|
||||
selections : selections.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,26 +211,35 @@ public class ChoiceCallback implements Callback, java.io.Serializable {
|
|||
private void readObject(ObjectInputStream stream)
|
||||
throws IOException, ClassNotFoundException {
|
||||
stream.defaultReadObject();
|
||||
choices = (choices == null || choices.length == 0 ?
|
||||
choices : choices.clone());
|
||||
String errMsg = doSanityCheck(prompt, choices, defaultChoice,
|
||||
multipleSelectionsAllowed);
|
||||
if (errMsg != null) {
|
||||
throw new InvalidObjectException(errMsg);
|
||||
}
|
||||
|
||||
selections = (selections == null || selections.length == 0 ?
|
||||
selections : selections.clone());
|
||||
if (selections != null && selections.length > 1 &&
|
||||
!multipleSelectionsAllowed) {
|
||||
throw new InvalidObjectException("Multiple selections not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
private static String doSanityCheck(String prompt, String[] choices,
|
||||
int defaultChoice, boolean allowMultiple) {
|
||||
if ((prompt == null) || prompt.isEmpty() ||
|
||||
(choices == null) || (choices.length == 0) ||
|
||||
(defaultChoice < 0) || (defaultChoice >= choices.length)) {
|
||||
throw new InvalidObjectException(
|
||||
"Missing/invalid prompt/choices");
|
||||
return "Missing/invalid prompt/choices";
|
||||
}
|
||||
|
||||
choices = choices.clone();
|
||||
for (int i = 0; i < choices.length; i++) {
|
||||
if ((choices[i] == null) || choices[i].isEmpty())
|
||||
throw new InvalidObjectException("Null/empty choices");
|
||||
}
|
||||
|
||||
if (selections != null) {
|
||||
selections = selections.clone();
|
||||
if (!multipleSelectionsAllowed && (selections.length != 1)) {
|
||||
throw new InvalidObjectException(
|
||||
"Multiple selections not allowed");
|
||||
if ((choices[i] == null) || choices[i].isEmpty()) {
|
||||
return "Null/empty choices value";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -26,6 +26,7 @@
|
|||
package javax.security.auth.callback;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
/**
|
||||
|
@ -189,25 +190,10 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
|
|||
*/
|
||||
public ConfirmationCallback(int messageType,
|
||||
int optionType, int defaultOption) {
|
||||
|
||||
if (messageType < INFORMATION || messageType > ERROR ||
|
||||
optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
switch (optionType) {
|
||||
case YES_NO_OPTION:
|
||||
if (defaultOption != YES && defaultOption != NO)
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case YES_NO_CANCEL_OPTION:
|
||||
if (defaultOption != YES && defaultOption != NO &&
|
||||
defaultOption != CANCEL)
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case OK_CANCEL_OPTION:
|
||||
if (defaultOption != OK && defaultOption != CANCEL)
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
String errMsg = doSanityCheck(messageType, optionType, false, null,
|
||||
defaultOption, null, false);
|
||||
if (errMsg != null) {
|
||||
throw new IllegalArgumentException(errMsg);
|
||||
}
|
||||
|
||||
this.prompt = null;
|
||||
|
@ -250,21 +236,20 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
|
|||
public ConfirmationCallback(int messageType,
|
||||
String[] options, int defaultOption) {
|
||||
|
||||
if (messageType < INFORMATION || messageType > ERROR ||
|
||||
options == null || options.length == 0 ||
|
||||
defaultOption < 0 || defaultOption >= options.length)
|
||||
throw new IllegalArgumentException();
|
||||
if (options != null) {
|
||||
options = options.clone();
|
||||
}
|
||||
String errMsg = doSanityCheck(messageType, UNSPECIFIED_OPTION, true,
|
||||
options, defaultOption, null, false);
|
||||
if (errMsg != null) {
|
||||
throw new IllegalArgumentException(errMsg);
|
||||
}
|
||||
|
||||
this.prompt = null;
|
||||
this.messageType = messageType;
|
||||
this.optionType = UNSPECIFIED_OPTION;
|
||||
this.defaultOption = defaultOption;
|
||||
|
||||
this.options = options.clone();
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
if (options[i] == null || options[i].isEmpty())
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -304,27 +289,11 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
|
|||
public ConfirmationCallback(String prompt, int messageType,
|
||||
int optionType, int defaultOption) {
|
||||
|
||||
if (prompt == null || prompt.isEmpty() ||
|
||||
messageType < INFORMATION || messageType > ERROR ||
|
||||
optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
switch (optionType) {
|
||||
case YES_NO_OPTION:
|
||||
if (defaultOption != YES && defaultOption != NO)
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case YES_NO_CANCEL_OPTION:
|
||||
if (defaultOption != YES && defaultOption != NO &&
|
||||
defaultOption != CANCEL)
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case OK_CANCEL_OPTION:
|
||||
if (defaultOption != OK && defaultOption != CANCEL)
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
String errMsg = doSanityCheck(messageType, optionType, false, null,
|
||||
defaultOption, prompt, true);
|
||||
if (errMsg != null) {
|
||||
throw new IllegalArgumentException(errMsg);
|
||||
}
|
||||
|
||||
this.prompt = prompt;
|
||||
this.messageType = messageType;
|
||||
this.optionType = optionType;
|
||||
|
@ -369,22 +338,20 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
|
|||
public ConfirmationCallback(String prompt, int messageType,
|
||||
String[] options, int defaultOption) {
|
||||
|
||||
if (prompt == null || prompt.isEmpty() ||
|
||||
messageType < INFORMATION || messageType > ERROR ||
|
||||
options == null || options.length == 0 ||
|
||||
defaultOption < 0 || defaultOption >= options.length)
|
||||
throw new IllegalArgumentException();
|
||||
if (options != null) {
|
||||
options = options.clone();
|
||||
}
|
||||
String errMsg = doSanityCheck(messageType, UNSPECIFIED_OPTION, true,
|
||||
options, defaultOption, prompt, true);
|
||||
if (errMsg != null) {
|
||||
throw new IllegalArgumentException(errMsg);
|
||||
}
|
||||
|
||||
this.prompt = prompt;
|
||||
this.messageType = messageType;
|
||||
this.optionType = UNSPECIFIED_OPTION;
|
||||
this.defaultOption = defaultOption;
|
||||
|
||||
this.options = options.clone();
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
if (options[i] == null || options[i].isEmpty())
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -491,6 +458,49 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
|
|||
return selection;
|
||||
}
|
||||
|
||||
private static String doSanityCheck(int msgType, int optionType,
|
||||
boolean isUnspecifiedOption, String[] options, int defOption,
|
||||
String prompt, boolean checkPrompt) {
|
||||
// validate msgType
|
||||
if (msgType < INFORMATION || msgType > ERROR) {
|
||||
return "Invalid msgType";
|
||||
}
|
||||
// validate prompt if checkPrompt == true
|
||||
if (checkPrompt && (prompt == null || prompt.isEmpty())) {
|
||||
return "Invalid prompt";
|
||||
}
|
||||
// validate optionType
|
||||
if (isUnspecifiedOption) {
|
||||
if (optionType != UNSPECIFIED_OPTION) {
|
||||
return "Invalid optionType";
|
||||
}
|
||||
// check options
|
||||
if (options == null || options.length == 0 ||
|
||||
defOption < 0 || defOption >= options.length) {
|
||||
return "Invalid options and/or default option";
|
||||
}
|
||||
for (String ov : options) {
|
||||
if (ov == null || ov.isEmpty()) {
|
||||
return "Invalid option value";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION) {
|
||||
return "Invalid optionType";
|
||||
}
|
||||
// validate defOption based on optionType
|
||||
if ((optionType == YES_NO_OPTION && (defOption != YES &&
|
||||
defOption != NO)) ||
|
||||
(optionType == YES_NO_CANCEL_OPTION && (defOption != YES &&
|
||||
defOption != NO && defOption != CANCEL)) ||
|
||||
(optionType == OK_CANCEL_OPTION && (defOption != OK &&
|
||||
defOption != CANCEL))) {
|
||||
return "Invalid default option";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the state of this object from the stream.
|
||||
*
|
||||
|
@ -502,8 +512,15 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
|
|||
private void readObject(ObjectInputStream stream)
|
||||
throws IOException, ClassNotFoundException {
|
||||
stream.defaultReadObject();
|
||||
|
||||
if (options != null) {
|
||||
options = options.clone();
|
||||
}
|
||||
String errMsg = doSanityCheck(messageType, optionType,
|
||||
(optionType == UNSPECIFIED_OPTION), options, defaultOption,
|
||||
prompt, false);
|
||||
if (errMsg != null) {
|
||||
throw new InvalidObjectException(errMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -178,7 +178,9 @@ public class PasswordCallback implements Callback, java.io.Serializable {
|
|||
}
|
||||
|
||||
if (inputPassword != null) {
|
||||
inputPassword = inputPassword.clone();
|
||||
char[] temp = inputPassword;
|
||||
inputPassword = temp.clone();
|
||||
Arrays.fill(temp, '0');
|
||||
cleanable = CleanerFactory.cleaner().register(
|
||||
this, cleanerFor(inputPassword));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue