Códigos de baixa qualidade levam a comportamentos imprevisíveis. Da perspectiva do usuário, isso normalmente se manifesta como usabilidade ruim. Para um invasor, trata-se de uma oportunidade para atacar o sistema de formas imprevistas.
getChunk == NULL
sempre será "false", pois getChunk
é o nome de uma função definida no 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()
em relação à instância user
, e não contra as classes User
ou RegularUser
, isso significa que essa condição sempre retornará true
e a operação restrita será realizada mesmo que instanceof
tenha sido usado para entrar nessa parte do bloco if/else
.serialPersistentFields
corretamente, ele deve ser declarado como private
, static
e final
.serialPersistentFields
. Esse recurso somente funcionará se serialPersistentFields
for declarado como private
, static
e final
.serialPersistentFields
não será usada para definir campos Serializable
porque não é private
, static
e final
.
class List implements Serializable {
public ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("myField", List.class) };
...
}
Object.equals()
em um array no lugar de java.util.Arrays.equals().
Object.equals()
contra um array é um erro na maioria dos casos, pois isso verificará a igualdade dos endereços dos arrays, em vez da igualdade dos elementos dos arrays, e, em geral, deve ser substituído 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()
a fim de enviar a função routine
para a pilha de limpeza do thread de chamada e, em seguida, é retornado. Como pthread_cleanup_push()
e sua função parceira pthread_cleanup_pop()
são implementadas como macros em plataformas diferentes do IBM AIX, a estrutura de dados criada por pthread_cleanup_push()
não será acessível a chamadas subsequentes para pthread_cleanup_pop()
. O código não conseguirá compilar ou apresentará um comportamento incorreto em tempo de execução em todas as plataformas nas quais essas funções são implementadas 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()
usa um argumento do tipo object
, o método nunca é chamado.Object.equals()
:
public boolean equals(Object obj1, Object obj2) {
...
}
Object.equals()
usa apenas um argumento, o método no Example 1
nunca é chamado.ISerializable
, mas não declararem o atributo [Serializable]
, não serão serializadas.[Serializable]
. Se a classe puder ser serializada usando os métodos de serialização padrão definidos pelo .NET Framework, será necessário e suficiente que o objeto seja serializado corretamente. Se a classe exigir métodos de serialização personalizados, ela também deverá implementar a interface ISerializable
. No entanto, a classe ainda deve declarar o atributo [Serializable]
.CustomStorage
implementa a interface ISerializable
. No entanto, por não declarar o atributo [Serializable]
, ela não será serializada.
public class CustomStorage: ISerializable {
...
}
java.io.Serializable
podem causar problemas e deixar vazar informações da classe externa.
...
class User implements Serializable {
private int accessLevel;
class Registrator implements Serializable {
...
}
}
Example 1
, quando a classe interna Registrator
for serializada, ela também serializará o campo accessLevel
da classe externa User
.synchronized
, garantindo o comportamento correto quando vários threads acessam a mesma instância. Todos os métodos de substituição também devem ser declarados como synchronized
, caso contrário, um comportamento inesperado poderá ocorrer.Foo
substitui a classe Bar
, mas não declara o método synchronizedMethod
como 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
pode ser convertida no tipo Bar
. Se a mesma instância for fornecida a dois threads separados e synchronizedMethod
for executado repetidamente, o comportamento será imprevisível.obj.Equals(null)
sempre deve ser "false".Equals()
para comparar um objeto com null
. O contrato do método Equals()
exige que essa comparação sempre retorne "false".obj.equals(null)
sempre será "false".equals()
para comparar um objeto com null
. Essa comparação sempre retornará "false", uma vez que o objeto não é null
. (Se o objeto for null
, o programa lançará NullPointerException
).pthread_create()
a partir da função main()
do processo pai serão encerrados prematuramente se o processo pai encerrar sua execução antes dos threads que ele gerou, sem chamar pthread_exit()
. Chamar pthread_exit()
garante que o processo pai permanecerá ativo até que a execução de todos os seus threads tenha sido encerrada. Como alternativa, o processo pai pode chamar pthread_join
em todos os threads filho e garantir que eles serão concluídos antes da conclusão do processo.pthread_create()
para criar um thread e depois é encerrado normalmente. Se a conclusão do thread filho não tiver sido encerrada até o retorno da função main()
, o thread será encerrado prematuramente.
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()
na classe chama uma função que pode ser substituída.readObject()
age como um construtor e, portanto, a inicialização do objeto só estará concluída quando essa função terminar. Portanto, quando uma função readObject()
de uma classe Serializable
chama uma função substituível, isso pode fornecer ao método de substituição o acesso necessário ao estado do objeto antes que ele seja totalmente inicializado.readObject()
a seguir chama um método que pode ser substituído.
...
private void readObject(final ObjectInputStream ois) throws IOException, ClassNotFoundException {
checkStream(ois);
ois.defaultReadObject();
}
public void checkStream(ObjectInputStream stream){
...
}
checkStream()
e sua classe delimitadora não são final
e públicas, isso implica que a função pode ser substituída, o que pode significar que um invasor pode substituir a função checkStream()
a fim de obter acesso ao objeto durante a desserialização.private readonly
de uma propriedade somente "getter" permite que o código de chamada modifique o conteúdo da lista, fornecendo a ela eficazmente acesso de gravação e contrariando as intenções do programador que a tornou private readonly
._item
, que é 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 inclui um método de processamento recursivo, ele aciona uma exceção de estouro de pilha (exaustão de pilha). Essa exceção ocorre devido ao link circular entre filho e pai.String
não é confiável e não deve ser feito.String
, ele primeiro deve ser transformado em um objeto String
, o que normalmente é feito usando uma função como Double.toString()
. Dependendo do tipo e do valor da variável de ponto flutuante, quando convertida em um objeto String
, ela pode ser "NaN", "Infinity", "-Infinity", ter uma certa quantidade de casas decimais à esquerda contendo zeros ou incluir uma campo de expoente. Se convertida em uma String hexadecimal, a representação também poderá ser consideravelmente diferente.String
.
...
int initialNum = 1;
...
String resultString = Double.valueOf(initialNum/10000.0).toString();
if (s.equals("0.0001")){
//do something
...
}
...
if
é impossível de atender. Ela requer que a variável s
seja não nula, embora no único caminho em que s
pode receber um valor não nulo exista uma instrução return
.
String s = null;
if (b) {
s = "Yes";
return;
}
if (s != null) {
Dead();
}