Un API es un contrato entre un autor de llamada y un receptor de llamada. Las formas de abuso de API más comunes los produce el autor de llamada cuando no consigue atender su fin de este contrato. Por ejemplo, si un programa no consigue llamar chdir() después de llamar chroot(), se viola el contrato que especifica cómo cambiar el directorio de origen activo de una forma segura. Otro buen ejemplo de un abuso de manual es esperar que el receptor devuelva una información de DNS de confianza al autor de llamada. En este caso, el autor de llamada abusa el API del receptor haciendo determinadas suposiciones sobre su comportamiento (que el valor de retorno se puede usar con fines de autenticación). También se puede violar el contrato entre el autor de llamada y el receptor desde el otro lado. Por ejemplo, si un codificador envía SecureRandom y devuelve un valor no aleatorio, se viola el contrato.
null
.Object.equals()
, Comparable.compareTo()
y Comparator.compare()
devuelvan un valor especificado si sus parámetros son null
. De no cumplir el contrato se daría lugar a un comportamiento inesperado.equals()
no compara su parámetro con null
.
public boolean equals(Object object)
{
return (toString().equals(object.toString()));
}
clone()
debe llamar super.clone()
para obtener el nuevo objeto.clone()
deben obtener el nuevo objeto llamando super.clone()
. Si una clase no puede seguir esta convención, un método clone()
de subclase devolverá un objeto del tipo incorrecto.super.clone()
. Dada la forma en que Kibitzer
implementa clone()
, el método de clonación de FancyKibitzer
devolverá un objeto de tipo Kibitzer
en lugar de FancyKibitzer
.
public class Kibitzer implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = new Kibitzer();
...
}
}
public class FancyKibitzer extends Kibitzer
implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = super.clone();
...
}
}
Equals()
y GetHashCode()
.a.Equals(b) == true
, entonces a.GetHashCode() == b.GetHashCode()
. Equals()
pero no GetHashCode()
.
public class Halfway() {
public override boolean Equals(object obj) {
...
}
}
equals()
y hashCode()
.a.equals(b) == true
, entonces a.hashCode() == b.hashCode()
. equals()
pero no hashCode()
.
public class halfway() {
public boolean equals(Object obj) {
...
}
}
saveState()
y restoreState()
.saveState(javax.faces.context.FacesContext)
como restoreState(javax.faces.context.FacesContext, java.lang.Object)
, o no implementar ninguna de ellos. Como estos dos métodos tienen una relación estrecha, no se pueden tener los métodos saveState(javax.faces.context.FacesContext)
y restoreState(javax.faces.context.FacesContext, java.lang.Object)
residiendo en diferentes niveles de la jerarquía de herencia.saveState()
y no restoreState()
, de forma que siempre está equivocada, independientemente de lo que pueda hacer cualquier clase
public class KibitzState implements StateHolder {
public Object saveState(FacesContext fc) {
...
}
}
checkCallingOrSelfPermission()
o checkCallingOrSelfUriPermission()
determina si el programa que realiza la llamada cuenta con el permiso necesario para acceder a determinado servicio o URI. Sin embargo, estas funciones deben utilizarse con cuidado, ya que pueden conceder acceso a aplicaciones malintencionadas, que carecen de los permisos correspondientes, adoptando los permisos de las aplicaciones.Assert()
con un permiso concreto, es una forma de decir que el flujo de control actual tiene el permiso especificado. Esto provoca que .NET Framework detenga cualquier comprobación de permisos adicional, siempre y cuando se hayan satisfecho los permisos necesarios, por lo que el código que llama al código que realiza la llamada a Assert()
podría no tener el permiso requerido. Usar Assert()
es útil en ciertos casos, pero puede dar lugar a vulnerabilidades cuando permite que un usuario malintencionado tome el control de un recurso que no tendría derecho a controlar de otro modo.