代码质量不佳会导致不可预测的行为。对于用户来说,通常表现为可用性差。对于攻击者来说,提供了以意外方式对系统施加压力的机会。
SafeEvpPKeyHandle
的新实例,但是在没有相应调用 DangerousRelease
的情况下调用了 DangerousAddRef
方法。示例 2:以下代码创建了
var pkey = NativeMethods.ENGINE_LOAD_SSL_PRIVATE_KEY(...);
var safeEvpHandle = new SafeEvpPKeyHandle(handle: handle, ownsHandle: true);
bool success = false;
try {
safeEvpHandle.DangerousAddRef(ref success);
var handle = safeEvpHandle.DangerousGetHandle();
} catch (ObjectDisposedException ex) {
//...
} finally {
safeEvpHandle.close();
}
SafeEvpPKeyHandle
的新实例,但是在没有相应调用 DangerousAddRef
的情况下调用了 DangerousRelease
方法。
var pkey = NativeMethods.ENGINE_LOAD_SSL_PRIVATE_KEY(...);
var safeEvpHandle = new SafeEvpPKeyHandle(handle: handle, ownsHandle: true);
bool success = false;
try {
var handle = safeEvpHandle.DangerousGetHandle();
} catch (ObjectDisposedException ex) {
//...
} finally {
safeEvpHandle.DangerousRelease();
safeEvpHandle.close();
}
SafeEvpPKeyHandle
的新实例,但由于将 ownsHandle
参数设置为 false
,无法可靠地让对象在完成阶段释放句柄。
var pkey = NativeMethods.ENGINE_LOAD_SSL_PRIVATE_KEY(...);
var safeEvpHandle = new SafeEvpPKeyHandle(handle: handle, ownsHandle: false);
if (safeEvpHandle.IsInvalid) {
...
}
safeEvpHandle.close();
SafeEvpPKeyHandle
的新实例,但在通过 SetHandleAsInvalid
使句柄失效后调用了 DangerousGetHandle
,这可能会返回过时的句柄值。
var pkey = NativeMethods.ENGINE_LOAD_SSL_PRIVATE_KEY(...);
var safeEvpHandle = new SafeEvpPKeyHandle(handle: handle, ownsHandle: true);
...
safeEvpHandle.SetHandleAsInvalid();
...
var handle = safeEvpHandle.DangerousGetHandle();
...
safeEvpHandle.close();
DirectoryEntry
对象。但是如果在执行 LDAP 查询或者处理查询结果时发生异常,那么 DirectoryEntry
对象将不会被关闭。这会在应用程序中引入内存泄漏,因为 DirectoryEntry
在内部使用 COM API 来查询 Active Directory 服务器。
...
DirectoryEntry entry = new DirectoryEntry("LDAP://CN=users,DC=fabrikam,DC=com");
DirectorySearcher mySearcher = new DirectorySearcher(entry);
SearchResultCollection result = mySearcher.FindAll();
CheckUsers(result);
mySearcher.Dispose();
entry.Close();
...
...
lo_client = cl_apc_tcp_client_manager=>create( i_host = host
i_port = port
i_frame = lv_frame
i_protocol = protocol
i_ssl_id = ssl_id
i_event_handler = lo_event_handler ).
" initiate the connection setup, successful connect leads to execution of ON_OPEN
lo_client->connect( ).
...
例 2:正常情况下,以下修复代码会正常关闭套接字以及任何相关联的数据流。但如果在读取输入或将数据输出到屏幕时出现异常,则不会关闭套接字对象。如果这种情况经常出现,系统将会耗尽所有套接字,无法处理更多连接。
private void echoSocket(String host, int port) throws UnknownHostException, SocketException, IOException
{
Socket sock = new Socket(host, port);
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
while ((String socketData = reader.readLine()) != null) {
System.out.println(socketData);
}
}
private void echoSocket(String host, int port) throws UnknownHostException, SocketException, IOException
{
Socket sock = new Socket(host, port);
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
while ((String socketData = reader.readLine()) != null) {
System.out.println(socketData);
}
sock.close();
}
StreamReader
的 Finalize()
方法最终会调用 Close()
,但是不能确保何时会调用 Finalize()
方法。事实上,无法确保 Finalize()
会被调用。因此,在繁忙的环境中,这可能会导致 VM 用尽它的所有可用文件句柄。
private void processFile(string fName) {
StreamWriter sw = new StreamWriter(fName);
string line;
while ((line = sr.ReadLine()) != null)
processLine(line);
}
FileInputStream
中的 finalize()
方法最终会调用 close()
,但是不能确保何时会调用 finalize()
方法。在繁忙的环境中,这会导致 JVM 用尽它所有的文件句柄。
private void processFile(String fName) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream(fName);
int sz;
byte[] byteArray = new byte[BLOCK_SIZE];
while ((sz = fis.read(byteArray)) != -1) {
processBytes(byteArray, sz);
}
}
...
CFIndex numBytes;
do {
UInt8 buf[bufferSize];
numBytes = CFReadStreamRead(readStream, buf, sizeof(buf));
if( numBytes > 0 ) {
handleBytes(buf, numBytes);
} else if( numBytes < 0 ) {
CFStreamError error = CFReadStreamGetError(readStream);
reportError(error);
}
} while( numBytes > 0 );
...
def readFile(filename: String): Unit = {
val data = Source.fromFile(fileName).getLines.mkString
// Use the data
}
...
func leak(reading input: InputStream) {
input.open()
let bufferSize = 1024
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
while input.hasBytesAvailable {
let read = input.read(buffer, maxLength: bufferSize)
}
buffer.deallocate(capacity: bufferSize)
}
...
performOperationInCriticalSection()
之前建立锁定,但是如果该方法抛出异常则该代码未能释放锁定。
Object synchronizationObject = new Object ();
System.Threading.Monitor.Enter(synchronizationObject);
performOperationInCriticalSection();
System.Threading.Monitor.Exit(synchronizationObject);
int helper(char* fName)
{
int status;
...
pthread_cond_init (&count_threshold_cv, NULL);
pthread_mutex_init(&count_mutex, NULL);
status = perform_operation();
if (status) {
printf("%s", "cannot perform operation");
return OPERATION_FAIL;
}
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
return OPERATION_SUCCESS;
}
CALL "CBL_GET_RECORD_LOCK"
USING file-handle
record-offset
record-length
reserved
END-CALL
IF return-code NOT = 0
DISPLAY "Error!"
GOBACK
ELSE
PERFORM write-data
IF ws-status-code NOT = 0
DISPLAY "Error!"
GOBACK
ELSE
DISPLAY "Success!"
END-IF
END-IF
CALL "CBL_FREE_RECORD_LOCK"
USING file-handle
record-offset
record-length
reserved
END-CALL
GOBACK
.
performOperationInCriticalSection()
之前建立锁定,但是如果该方法抛出异常则该代码未能释放锁定。
ReentrantLock myLock = new ReentrantLock ();
myLock.lock();
performOperationInCriticalSection();
myLock.unlock();
performOperationInCriticalSection()
的前面创建一个锁,但从未释放过。
os_unfair_lock lock1 = OS_UNFAIR_LOCK_INIT;
os_unfair_lock_lock(&lock1);
performOperationInCriticalSection();
performOperationInCriticalSection()
的前面创建一个锁,但从未释放过。
let lock1 = OSAllocatedUnfairLock()
lock1.lock()
performOperationInCriticalSection();
incomingStream
创建受管的 Bitmap Object。Bitmap 被操纵并连接至外部流 outgoingStream
。incomingBitmap
和 outgoingBitmap
的 Dispose()
方法从未被明确调用过。Bitmap.Dispose()
。然而,Bitmap
对象使用稀缺的非受管系统资源。垃圾收集器在耗尽非受管资源池之前会调用 Dispose()
失败。
private void processBitmap(Stream incomingStream, Stream outgoingStream, int thumbnailSize)
{
Bitmap incomingBitmap = (Bitmap)System.Drawing.Image.FromStream(incomingStream);
bool validBitmap = validateBitmap(incomingBitmap);
if (!validBitmap)
throw new ValidationException(incomingBitmap);
Bitmap outgoingBitmap = new Bitmap(incomingBitmap, new Size(thumbnailSize, thumbnailSize));
outgoingBitmap.Save(outgoingStream, ImageFormat.Bmp);
}
char* ptr = (char*)malloc (SIZE);
...
if (err) {
abrt = 1;
free(ptr);
}
...
if (abrt) {
logError("operation aborted before commit", ptr);
}