代码质量不佳会导致不可预测的行为。对于用户来说,通常表现为可用性差。对于攻击者来说,提供了以意外方式对系统施加压力的机会。
<script>
标签。
...
public String tagProcessor(String tag){
if (tag.toUpperCase().equals("SCRIPT")){
return null;
}
//does not contain SCRIPT tag, keep processing input
...
}
...
Example 1
的问题是,在使用不带区域设置的 java.lang.String.toUpperCase()
时,它将使用默认区域设置的规则。使用土耳其区域设置 "title".toUpperCase()
时将返回“T\u0130TLE”,其中“\u0130”是“LATIN CAPITAL LETTER I WITH DOT ABOVE”字符。这可能会导致意外的结果,例如在Example 1
中,这会阻止此验证捕获“script”一词,从而导致 Cross-Site Scripting 漏洞。
...
import java.sql.PreparedStatement;
import com.sap.sql.NativeSQLAccess;
String mssOnlyStmt = "...";
// variant 1
PreparedStatement ps =
NativeSQLAccess.prepareNativeStatement(
conn, mssOnlyStmt);
. . .
// variant 2
Statement stmt =
NativeSQLAccess.createNativeStatement(conn);
int result = stmt.execute(mssOnlyStmt);
. . .
// variant 3
CallableStatement cs =
NativeSQLAccess.prepareNativeCall(
conn, mssOnlyStmt);
. . .
...
public class Box{
public int area;
public static final int width = 10;
public static final Box box = new Box();
public static final int height = (int) (Math.random() * 100);
public Box(){
area = width * height;
}
...
}
...
Example 1
中,由于 width
等于 10,因此开发人员希望 box.area
是一个随机整数,该整数恰好为 10 的倍数。但在现实情况中,它可能始终具有硬编码值 0。系统首先会对使用编译时常量声明的静态最终字段进行初始化,然后依次执行各个代码。这意味着,由于 height
不是编译时常量,因此会在声明 box
后对其进行声明,这样就会在初始化 height
字段之前调用构造函数。
...
class Foo{
public static final int f = Bar.b - 1;
...
}
...
class Bar{
public static final int b = Foo.f + 1;
...
}
This example is perhaps easier to identify, but would be dependent on which class is loaded first by the JVM. In this exampleFoo.f
could be either -1 or 0, andBar.b
could be either 0 or 1.
null
的指针是否为 null
之前间接引用该指针,则会发生 check-after-dereference 错误。如果程序明确检查过 null
,并确定该指针为 null
,但仍继续间接引用该指针,则会出现 dereference-after-check 错误。此类错误通常是由于错别字或程序员疏忽造成的。如果程序明确将指针设置为 null
,但稍后却间接引用该指针,则将出现 dereference-after-store 错误。此错误通常是因为程序员在声明变量时将该变量初始化为 null
所致。foo
为 null
,然后错误地对其进行间接引用。如果在 if
语句中检查 foo
时其为 null
,则会发生 null
间接引用,从而导致 null 指针异常。示例 2:在下列代码中,程序员假设变量
if (foo is null) {
foo.SetBar(val);
...
}
foo
不是 null
,并通过间接引用该对象来确认此假设。但是,程序员稍后通过检查 foo
是否为 null
发现事实与该假设相反。如果在 if
指令中检查时发现 foo
可能是 null
,则在间接引用它时可能也为 null
,并可能引起 null 指针异常。间接引用不安全,或者无需后续检查。示例 3:在下列代码中,程序员会将变量
foo.SetBar(val);
...
if (foo is not null) {
...
}
foo
明确设置为 null
。之后,程序员会间接引用 foo
,而未检查对象是否为 null
值。
Foo foo = null;
...
foo.SetBar(val);
...
}
null
的指针是否为 null
之前间接引用该指针,则会发生 check-after-dereference 错误。如果程序明确检查过 null
,并确定该指针为 null
,但仍继续间接引用该指针,则会出现 dereference-after-check 错误。此类错误通常是由于错别字或程序员疏忽造成的。如果程序明确将指针设置为 null
,但稍后却间接引用该指针,则将出现 dereference-after-store 错误。此错误通常是因为程序员在声明变量时将该变量初始化为 null
所致。ptr
不是 NULL
。当程序员间接引用该指针时,这个假设就会清晰的体现出来。当程序员检查 ptr
是否为 NULL
时,就会与该假设发生矛盾。当在 if
语句中检查时,如果 ptr
可以为 NULL
,则在其间接引用时也将为 NULL
,并引起 segmentation fault。示例 2:在下列代码中,程序员会确认变量
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
为 NULL
,然后错误地对其进行间接引用。如果在 if
语句中检查 ptr
时其为 NULL
,则会发生 null
dereference,从而导致分段故障。示例 3:在下列代码中,程序员忘记了字符串
if (ptr == null) {
ptr->field = val;
...
}
'\0'
实际上为 0 还是 NULL
,从而间接引用 null 指针并引发分段故障。示例 4:在下列代码中,程序员会将变量
if (ptr == '\0') {
*ptr = val;
...
}
ptr
明确设置为 NULL
。之后,程序员会间接引用 ptr
,而未检查对象是否为 null
值。
*ptr = NULL;
...
ptr->field = val;
...
}
null
,并确定该指针为 null
,但仍继续间接引用该对象,则会出现 dereference-after-check 错误。此类错误通常是由于错别字或程序员疏忽造成的。foo
为 null
,然后错误地对其进行间接引用。如果在 if
语句中检查 foo
时其为 null
,则会发生 null
dereference,从而导致 null 指针异常。
if (foo == null) {
foo.setBar(val);
...
}
require
的调用。
function withdrawWinnings() {
require(uint32(msg.sender) == 0);
_sendWinnings();
}
function _sendWinnings() {
msg.sender.transfer(this.balance);
}
assert
来检查 Lock
合约实例的余额是一个特定值 (msg.value
)。
contract Lock {
constructor (address owner, uint256 unlockTime) public payable {
...
}
}
contract Lockdrop {
...
function lock(...) {
uint256 eth = msg.value;
address owner = msg.sender;
uint256 unlockTime = unlockTimeForTerm(term);
Lock lockAddr = (new Lock).value(eth)(owner, unlockTime);
assert(address(lockAddr).balance == msg.value);
}
}
transfer()
和 send()
。
interface ICallable {
function callMe() external;
}
contract HardcodedNotGood {
function callWithArgs() public {
callable.callMe{gas: 10000}();
}
}