代码质量不佳会导致不可预测的行为。对于用户来说,通常表现为可用性差。对于攻击者来说,提供了以意外方式对系统施加压力的机会。
assert
Solidity 函数检查 false 语句。assert
Solidity 函数旨在仅检查求值为 true
的语句。将 false
语句传递到此函数会指出无法正常运行的代码或被误用的函数,以便进行验证输入等操作。assert
函数检查 false 语句。
contract A {
B b = new B(7);
function checkWithAssert(){
assert(b.retValue() == 21);
...
}
}
contract B {
uint _par;
constructor(uint par){
_par = par;
}
function retValue() returns(uint){
return _par;
}
}
getChunk == NULL
将永远是 false,因为 getChunk
是程序中定义的一个函数名称。
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();
}
}
}
}
user
实例,而非 User
或 RegularUser
类来调用 getAccessLevel()
方法,这意味着此条件下将始终返回 true
且会执行该限制操作,即使使用了 instanceof
以便进入 if/else
块的此部分也是如此。serialPersistentFields
,必须将其声明为 private
、static
和 final
。serialPersistentFields
数组中指定类的可序列化的字段来手动定义这些字段。仅当 serialPersistentFields
被声明为 private
、static
和 final
时,此功能才能运行。serialPersistentFields
的下列声明来定义 Serializable
字段,因为它不是 private
、static
和 final
。
class List implements Serializable {
public ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("myField", List.class) };
...
}
Object.equals()
,而非 java.util.Arrays.equals().
Object.equals()
会检查数组地址是否相同而非检查数组元素是否相同,因此在大多数情况下这是一个错误调用,通常应将该代码替换为 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()
函数将 routine
函数推至调用线程清除堆栈之上,然后返回。由于 pthread_cleanup_push()
及其搭档函数 pthread_cleanup_pop()
在 IBM AIX 之外的平台上作为宏来执行,因此随后调用 pthread_cleanup_pop()
将无法访问 pthread_cleanup_push()
创建的数据结构。在将这些函数作为宏执行的平台上,该代码将无法编译,或者不能正确运行。
void helper() {
...
pthread_cleanup_push (routine, arg);
}