SHARED
, que permite tener acceso de lectura y escritura.
results = query.execute(Database.SHARED);
results = query.execute(); //missing query mode
ActionForms
son vulnerables a la manipulación de ClassLoader.String
puede suponer una pérdida de datos.String
, no se especifica lo que ocurrirá con los datos que quedan fuera del conjunto de caracteres correspondiente. Esto puede suponer una pérdida de datos o una disminución en el nivel de seguridad cuando se necesitan datos binarios para garantizar que se cumplen las medidas de seguridad apropiadas.
...
FileInputStream fis = new FileInputStream(myFile);
byte[] byteArr = byte[BUFSIZE];
...
int count = fis.read(byteArr);
...
String fileString = new String(byteArr);
String fileSHA256Hex = DigestUtils.sha256Hex(fileString);
// use fileSHA256Hex to validate file
...
BUFSIZE
, funcionará siempre y cuando la información de myFile
se encuentre codificada igual que el conjunto de caracteres predeterminado. Sin embargo, si utiliza una codificación diferente o es un archivo binario, se perderá información. A su vez, esto provocará que el hash de SHA resultante no sea de confianza y que sea más fácil causar conflictos, especialmente si hay algún dato fuera del conjunto de caracteres predeterminado que se represente con el mismo valor, como un signo de interrogación.notify()
.notify()
. notifyJob()
llama notify()
.
public synchronized notifyJob() {
flag = true;
notify();
}
...
public synchronized waitForSomething() {
while(!flag) {
try {
wait();
}
catch (InterruptedException e)
{
...
}
}
...
}
wait()
, pero es posible que notify()
notifique un subproceso diferente al previsto.sleep()
mientras se mantiene un bloqueo puede provocar una pérdida de rendimiento y podría ocasionar un interbloqueo.sleep()
mientras se mantiene un bloqueo podría causar que todos los demás subprocesos esperen a que el recurso se libere, lo que podría dar lugar a un rendimiento degradado y un interbloqueo. sleep()
mientras mantiene un bloqueo.
ReentrantLock rl = new ReentrantLock();
...
rl.lock();
Thread.sleep(500);
...
rl.unlock();
System.gc()
a menudo parece lograr que el problema desaparezca.System.gc()
es el método incorrecto. De hecho, llamar a System.gc()
puede provocar problemas de rendimiento si se realiza con demasiada frecuencia.run()
del subproceso en lugar de llamar a start()
.run()
del objeto Thread
indica un error. El programador tenía intención de iniciar un nuevo subproceso de control, pero llamó accidentalmente a run()
en lugar de a start()
, por lo que el método run()
se ejecutará en el subproceso de control del autor de la llamada.run()
en lugar de a start()
.
Thread thr = new Thread() {
public void run() {
...
}
};
thr.run();
stop()
del subproceso, lo que puede filtrar recursos.stop()
de un objeto Thread
es un error. El programador pretende detener la ejecución de un subproceso pero no es consciente de que esa no es la mejor forma de detener un subproceso. La función stop()
en Thread
produce una excepción ThreadDeath
en cualquier lugar del objeto Thread
, lo que puede dejar a los objetos en un estado de incoherencia y filtrar recursos. Hace mucho que esta API está en desuso debido a que no es segura por naturaleza.Thread.stop()
.
...
public static void main(String[] args){
...
Thread thr = new Thread() {
public void run() {
...
}
};
...
thr.start();
...
thr.stop();
...
}
clone()
, pero no la interfaz Cloneable
.Cloneable
, ya que implementa un método llamado clone()
. Sin embargo, la clase no implementa la interfaz Cloneable
y el método clone()
no se comportará correctamente. clone()
para esta clase dará lugar a una CloneNotSupportedException.
public class Kibitzer {
public Object clone() throws CloneNotSupportedException {
...
}
}
Equals()
se llama en un objeto que no implementa Equals()
.Equals()
en una clase (o una superclase/interfaz) que no implemente explícitamente Equals()
resulta en una llamada al método Equals()
heredado de System.Object
. En lugar de comparar campos de miembros de objetos u otras propiedades, Object.Equals()
compara dos instancias de objetos para ver si son las mismas. Aunque estos son usos legítimos de Object.Equals()
, a menudo es indicativo de que el código contiene errores.
public class AccountGroup
{
private int gid;
public int Gid
{
get { return gid; }
set { gid = value; }
}
}
...
public class CompareGroup
{
public bool compareGroups(AccountGroup group1, AccountGroup group2)
{
return group1.Equals(group2); //Equals() is not implemented in AccountGroup
}
}
equals()
se llama en un objeto que no implementa equals()
.equals()
en una clase (o una superclase/interfaz) que no implemente explícitamente equals()
resulta en una llamada al método equals()
heredado de java.lang.Object
. En lugar de comparar campos de miembros de objetos u otras propiedades, Object.equals()
compara dos instancias de objetos para ver si son las mismas. Aunque estos son usos legítimos de Object.equals()
, a menudo es indicativo de que el código contiene errores.
public class AccountGroup
{
private int gid;
public int getGid()
{
return gid;
}
public void setGid(int newGid)
{
gid = newGid;
}
}
...
public class CompareGroup
{
public boolean compareGroups(AccountGroup group1, AccountGroup group2)
{
return group1.equals(group2); //equals() is not implemented in AccountGroup
}
}
clone()
de la clase llama a una función que puede anularse.clone()
llama a una función que se puede sobrescribir, puede que el clon se quede en un estado parcialmente inicializado o que se dañe.clone()
llama a un método que se puede sobrescribir.
...
class User implements Cloneable {
private String username;
private boolean valid;
public Object clone() throws CloneNotSupportedException {
final User clone = (User) super.clone();
clone.doSomething();
return clone;
}
public void doSomething(){
...
}
}
doSomething()
y su clase envolvente no son final
, la función se puede sobrescribir, lo que podría dejar al objeto clonado clone
en un estado parcialmente inicializado, lo que podría dar lugar a errores o que funcionase en torno a la lógica de forma inesperada.equals()
, puede producirse un comportamiento inesperado.equals()
del primitivo boxed en vez de a los operadores ==
y !=
. La especificación Java establece lo siguiente sobre las conversiones boxing: Boolean
o Byte
), solo se almacenará en la caché o se memorizará un rango de valores. En el caso de un subconjunto de valores, el uso de ==
o !=
devolverá el valor correcto. Para los demás valores fuera de dicho subconjunto, se devolverá el resultado de comparar las direcciones de los objetos.
...
Integer mask0 = 100;
Integer mask1 = 100;
...
if (file0.readWriteAllPerms){
mask0 = 777;
}
if (file1.readWriteAllPerms){
mask1 = 777;
}
...
if (mask0 == mask1){
//assume file0 and file1 have same permissions
...
}
...
Example 1
utiliza primitivos boxed Integer
para intentar comparar dos valores int
. Si mask0
y mask1
son iguales a 100
, entonces mask0 == mask1
devolverá true
. Sin embargo, cuando mask0
y mask1
son iguales a 777
, mask0 == maske1
devolverá false
, ya que dichos valores no están dentro del rango de valores almacenados en la caché para estos primitivos boxed.NaN
siempre es un error.NaN
, siempre se evalúa como false
, excepto en el caso del operador !=
, que siempre se evalúa como true
, puesto que NaN
no está ordenado.NaN
.
...
if (result == Double.NaN){
//something went wrong
throw new RuntimeException("Something went wrong, NaN found");
}
...
result
no es NaN
. Sin embargo, si se utiliza el operador ==
con NaN
siempre da como resultado un valor de false
, así que esta comprobación nunca produce la excepción.this
antes de que el objeto se inicialice por completo, lo que a su vez puede suponer vulnerabilidad.
...
class User {
private String username;
private boolean valid;
public User(String username, String password){
this.username = username;
this.valid = validateUser(username, password);
}
public boolean validateUser(String username, String password){
//validate user is real and can authenticate
...
}
public final boolean isValid(){
return valid;
}
}
validateUser
y la clase no son final
, significa que se pueden sobrescribir y, en consecuencia, al inicializar una variable en la subclase que sobrescribe dicha función, será posible eludir la funcionalidad validateUser
. Por ejemplo:
...
class Attacker extends User{
public Attacker(String username, String password){
super(username, password);
}
public boolean validateUser(String username, String password){
return true;
}
}
...
class MainClass{
public static void main(String[] args){
User hacker = new Attacker("Evil", "Hacker");
if (hacker.isValid()){
System.out.println("Attack successful!");
}else{
System.out.println("Attack failed");
}
}
}
Example 1
imprime "¡Ataque satisfactorio!" porque la clase Attacker
sobrescribe la función validateUser()
, llamada desde el constructor de la superclase User
, y Java comprobará primero la subclase en busca de funciones llamadas desde el constructor.
if (fitz == null) {
synchronized (this) {
if (fitz == null) {
fitz = new Fitzer();
}
}
}
return fitz;
Fitzer()
, pero no desea pagar el coste de la sincronización cada vez que se llame al código. A este giro se le conoce como bloqueo de doble comprobación.Fitzer()
. Consulte la declaración "El bloqueo de doble comprobación está roto" para obtener más información [1].inputReader
en función de su nombre de clase. Si un usuario malintencionado es capaz de suministrar una implementación de inputReader
que ejecute comandos maliciosos, el código no puede diferenciar entre las versiones benignas y maliciosas del objeto.
if (inputReader.GetType().FullName == "CompanyX.Transaction.Monetary")
{
processTransaction(inputReader);
}
inputReader
en función de su nombre de clase. Si un usuario malintencionado es capaz de suministrar una implementación de inputReader
que ejecute comandos maliciosos, el código no puede diferenciar entre las versiones benignas y maliciosas del objeto.
if (inputReader.getClass().getName().equals("com.example.TrustedClass")) {
input = inputReader.getInput();
...
}
inputReader
en función de su nombre de clase. Si un usuario malintencionado es capaz de suministrar una implementación de inputReader
que ejecute comandos maliciosos, el código no puede diferenciar entre las versiones benignas y maliciosas del objeto.
if (inputReader::class.qualifiedName == "com.example.TrustedClass") {
input = inputReader.getInput()
...
}
finalize()
debería llamar a super.finalize()
.finalize()
llame a super.finalize()
[1].super.finalize()
.
protected void finalize() {
discardNative();
}
equals()
, no con ==
o !=
.==
o !=
para comparar la igualdad de dos cadenas; es decir, compara la igualdad de dos objetos, no de sus valores. Hay muchas probabilidades de que dos referencias nunca sean iguales.
if (args[0] == STRING_CONSTANT) {
logger.info("miracle");
}
==
y !=
solo se comportarán según lo previsto cuando se utilicen para comparar cadenas dentro de objetos iguales. La forma más común para que esto ocurra es que las cadenas sean internas. De este modo, las cadenas se añaden a un grupo de objetos que la clase String
mantiene. Una vez que la cadena se interna, todos los usos de dicha cadena emplearán el mismo objeto y los operadores de igualdad se comportarán según lo previsto. Todos los literales de cadena y las constantes con valor de cadena se internan automáticamente. Otras cadenas pueden internarse manualmente llamando String.intern()
, lo que devolverá una instancia canónica de la cadena actual, creando una si fuera necesario.