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.
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......*/
}
msg.sender.call.value
(Interaction, Interação).
function withdraw(uint amount) public{
if (credit[msg.sender] >= amount) {
require(msg.sender.call.value(amount)());
credit[msg.sender]-=amount;
}
}
Example 1
quebra o padrão Checks-Effects-Interaction executando Checks-Interaction-Effects. Isso poderá levar à reentrada se um contrato inteligente de ataque receber o Ether em uma função de fallback e imediatamente chamar de volta withdraw
, criando uma situação recursiva em que o Ether é drenado porque a linha de código que diminui o equilíbrio (também conhecido como Efeito) nunca é executada.
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();
}
msg.sender
, mas usa ==
em vez de =
para fazer isso, o que não tem efeito.
function deposit(uint amount) public payable {
require(msg.value == amount, 'incorrect amount');
balance[msg.sender] == amount;
}