Una mala calidad del código lleva a un comportamiento no predecible. Desde la perspectiva de un usuario, muchas veces también supone una usabilidad limitada. Pero para un atacante es una oportunidad para atacar al sistema de formas insospechadas.
getChunk == NULL
siempre será falso porque getChunk
es el nombre de una función definida en el programa.
if (getChunk == NULL)
return ERR;
char* getName() {
char name[STR_MAX];
fillInName(name);
return name;
}
class AccessLevel{
public static final int ROOT = 0;
//...
public static final int NONE = 9;
}
//...
class User {
private static int access;
public User(){
access = AccessLevel.ROOT;
}
public static int getAccessLevel(){
return access;
}
//...
}
class RegularUser extends User {
private static int access;
public RegularUser(){
access = AccessLevel.NONE;
}
public static int getAccessLevel(){
return access;
}
public static void escalatePrivilege(){
access = AccessLevel.ROOT;
}
//...
}
//...
class SecureArea {
//...
public static void doRestrictedOperation(User user){
if (user instanceof RegularUser){
if (user.getAccessLevel() == AccessLevel.ROOT){
System.out.println("doing a privileged operation");
}else{
throw new RuntimeException();
}
}
}
}
getAccessLevel()
en la instancia user
y no en las clases User
o RegularUser
, la condición siempre devolverá true
y se llevará a cabo la operación restringida aunque se utilice instanceof
para entrar en esta parte del bloque if/else
.serialPersistentFields
correctamente, debe declararse como private
, static
y final
.serialPersistentFields
. Esta característica solo funcionará si serialPersistentFields
se declara como private
, static
y final
.serialPersistentFields
no se utilizará para definir campos Serializable
porque no es private
, static
y final
.
class List implements Serializable {
public ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("myField", List.class) };
...
}
Object.equals()
en una matriz en vez de java.util.Arrays.equals().
.Object.equals()
en una matriz es casi siempre un error, ya que comprobará la igualdad de las direcciones de las matrices, en vez de la igualdad de los elementos de las matrices, y debería reemplazarse por java.util.Arrays.equals()
. Object.equals()
.
...
int[] arr1 = new int[10];
int[] arr2 = new int[10];
...
if (arr1.equals(arr2)){
//treat arrays as if identical elements
}
...
pthread_cleanup_push()
para insertar la función routine
en las devoluciones y la pila de limpieza del subproceso de llamada. Como pthread_cleanup_push()
y su función asociada pthread_cleanup_pop()
se implementan como macros en las plataformas que no son IBM AIX, la estructura de datos creada por pthread_cleanup_push()
no será accesible para las subsiguientes llamadas a pthread_cleanup_pop()
. El código no se compilará o se comportará incorrectamente en tiempo de ejecución en todas las plataformas donde estas funciones se implementen como macros.
void helper() {
...
pthread_cleanup_push (routine, arg);
}
void clean_up()
{
char tmp[256];
...
free(tmp);
return;
}
System.Object.Equals()
:
public boolean Equals(string obj) {
...
}
System.Object.Equals()
utiliza un argumento de tipo object
, nunca se llama al método.Object.equals()
:
public boolean equals(Object obj1, Object obj2) {
...
}
Object.equals()
toma solo un argumento, el método en el Example 1
no se llama nunca.ISerializable
, pero que no declaran el atributo [Serializable]
no se serializarán.[Serializable]
. Si la clase se puede serializar mediante los métodos de serialización predeterminados definidos por .NET Framework, esto es necesario y suficiente para que el objeto se serialice correctamente. Si la clase requiere métodos de serialización personalizados, debe implementar también la interfaz ISerializable
. Sin embargo, la clase debe declarar aún el atributo [Serializable]
.CustomStorage
implementa la interfaz ISerializable
. Sin embargo, debido a que no puede declarar el atributo [Serializable]
, no se serializará.
public class CustomStorage: ISerializable {
...
}
java.io.Serializable
pueden ocasionar problemas y filtrar información de la clase externa.
...
class User implements Serializable {
private int accessLevel;
class Registrator implements Serializable {
...
}
}
Example 1
, cuando se serializa la clase interna Registrator
, también se serializa el campo accessLevel
de la clase externa User
.synchronized
, garantizando un comportamiento correcto cuando varios subprocesos acceden a la misma instancia. Todos los métodos de reemplazo también deben ser declarados como synchronized
porque, de no ser así, podría producirse un comportamiento inesperado.Foo
reemplaza a la clase Bar
, pero no declara el método synchronizedMethod
para que sea synchronized
:
public class Bar {
public synchronized void synchronizedMethod() {
for (int i=0; i<10; i++) System.out.print(i);
System.out.println();
}
}
public class Foo extends Bar {
public void synchronizedMethod() {
for (int i=0; i<10; i++) System.out.print(i);
System.out.println();
}
}
Foo
en el tipo Bar
. Si se da la misma instancia a dos subprocesos distintos y synchronizedMethod
se ejecuta repetidamente, el comportamiento se impredecible.obj.Equals(null)
debe ser siempre false.Equals()
para comparar un objeto con null
. El contrato del método Equals()
requiere que esta comparación devuelva siempre un valor "false".obj.equals(null)
siempre será "false".equals()
para comparar un objeto con null
. Esta comparación siempre devolverá false, porque el objeto no es null
. (Si el objeto es null
, el programa lanzará una NullPointerException
).pthread_create()
desde la función main()
del proceso primario finalizarán antes de tiempo si el proceso primario termina la ejecución antes que cualquier subproceso que haya generado sin llamar pthread_exit()
. Llamar pthread_exit()
garantiza que el proceso primario se mantendrá activo hasta que todos sus subprocesos hayan finalizado la ejecución. Otra opción es que el proceso primario puede llamar pthread_join
en todos los subprocesos secundarios y garantizar su compleción antes de que el proceso concluya.pthread_create()
para crear un subproceso y, a continuación, sale normalmente. Si el subproceso secundario no ha completado su ejecución hasta que la función main()
vuelve, entonces finalizará antes de tiempo.
void *Simple(void *threadid)
{
...
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
int rc;
pthread_t pt;
rc = pthread_create(&pt, NULL, Simple, (void *)t);
if (rc){
exit(-1);
}
}
readObject()
de la clase llama a una función que puede anularse.readObject()
actúa como un constructor, por lo que la inicialización del objeto no se completa hasta que finaliza esta función. Así, cuando una función readObject()
de una clase Serializable
llama a una función que se puede sobrescribir, puede permitir que el método de sobrescritura acceda al estado del objeto antes de que se inicialice por completo.readObject()
llama a un método que se puede sobrescribir.
...
private void readObject(final ObjectInputStream ois) throws IOException, ClassNotFoundException {
checkStream(ois);
ois.defaultReadObject();
}
public void checkStream(ObjectInputStream stream){
...
}
checkStream()
y su clase envolvente no son final
y públicas, la función se puede sobrescribir y un atacante puede sobrescribir la función checkStream()
para tener acceso al objeto durante la deserialización.private readonly
desde una propiedad de solo getter permite que el código de llamada modifique el contenido de la lista, lo cual proporciona a la lista acceso de escritura y contradice las intenciones del programador que la hizo private readonly
._item
declarada como private readonly
.
class Order
{
private readonly List<string> _item = new List<string>();
public IEnumerable<string> Item { get { return _item; } }
public Order()
{
/*class initialize */
}
/*some important function......*/
}
Marker child = MarkerManager.getMarker("child");
Marker parent = MarkerManager.getMarker("parent");
child.addParents(parent);
parent.addParents(child);
String toInfinity = child.toString();
toString()
, que incluye un método de procesamiento recursivo, desencadena una excepción de desbordamiento de pila (agotamiento de pila). Esta excepción se produce debido al enlace circular entre elemento secundario y elemento principal.String
no es fiable y no debe hacerse.String
, es necesario cambiarlo primero por un objeto String
, por lo general, mediante una función como Double.toString()
. En función de la forma y el valor de la variable de punto flotante, al convertirla en un objeto String
, puede ser "NaN", "Infinity" o "-Infinity", incluir alguna cantidad de decimales finales con ceros o contener un campo de exponente. Si se convierte en una cadena hexadecimal, la representación también podría diferir en gran medida.String
.
...
int initialNum = 1;
...
String resultString = Double.valueOf(initialNum/10000.0).toString();
if (s.equals("0.0001")){
//do something
...
}
...
if
. Exige que la variable s
sea no nula, mientras que en la única ruta de acceso en la que a s
se le puede asignar un valor no nulo hay una instrucción return
.
String s = null;
if (b) {
s = "Yes";
return;
}
if (s != null) {
Dead();
}