数据类型错误导致的问题

计算机在无时无刻的接收数据,并对数据进行传输和类型转化以及计算,然后再进行传输,传输到其他的IO设备,比如显示器或者到磁盘文件。

在这里数据转化是非常关键的一部分,类比下就好像是协议,当协商不一致的时候,两个人之间对数据的理解是完全不对等的,会导致严重的错误。

这里摘录了几个由于在代码中数据类型转化导致问题而引发的事件。

一般来说都是大数转为整型,或者小数接近于0,导致溢出。

还有要说明的是,为什么你写的软件赚不到钱,因为你根本没有意识到数据的准确性在真实世界是多么的珍贵。所以在给银行,证券,军事,航空航天,远洋运输,卫星,医疗,精密工业制造等用的软件才是真正的体现了人类智慧和思考精华的软件,才是可以赚钱的软件,并且应该赚钱的软件和服务。

下面是几个例子:

阿丽亚娜5火箭升空爆炸

Converting large floating-point numbers to integers is a common source of programming errors. Such an error had disastrous consequences for the maiden voyage of the Ariane 5 rocket, on June 4, 1996. Just 37 seconds after liftoff, the rocket veered off its flight path, broke up, and exploded. Communication satellites valued at $500 million were on board the rocket.

A later investigation [73, 33] showed that the computer controlling the inertial navigation system had sent invalid data to the computer controlling the engine nozzles. Instead of sending flight control information, it had sent a diagnostic bit pattern indicating that an overflow had occurred during the conversion of a 64-bit floating-point number to a 16-bit signed integer.

The value that overflowed measured the horizontal velocity of the rocket, which could be more than five times higher than that achieved by the earlier Ariane 4 rocket. In the design of the Ariane 4 software, they had carefully analyzed the numeric values and determined that the horizontal velocity would never overflow a 16-bit number. Unfortunately, they simply reused this part of the software in the Ariane 5 without checking the assumptions on which it had been based.

爱国者拦截飞毛腿导弹失败的问题

The imprecision of floating-point arithmetic can have disastrous effects. On February 25, 1991, during the first Gulf War, an American Patriot Missile battery in Dharan, Saudi Arabia, failed to intercept an incoming Iraqi Scud missile. The Scud struck an American Army barracks and killed 28 soldiers. The US General Accounting Office (GAO) conducted a detailed analysis of the failure [76] and determined that the underlying cause was an imprecision in a numeric calculation.

The Patriot system contains an internal clock, implemented as a counter that is incremented every 0.1 seconds. To determine the time in seconds, the program would multiply the value of this counter by a 24-bit quantity that was a fractional binary approximation to 1/10 . In particular, the binary representation 1 … of 10 is the nonterminating sequence 0.000110011[0011] , where the portion in brackets is repeated indefinitely. The program approximated 0.1, as a value x, by considering just the first 23 bits of the sequence to the right of the binary point: x = 0.00011001100110011001100.

The problem was that the Patriot software had been upgraded to use a more accurate function for reading time, but not all of the function calls had been replaced by the new code. As a result, the tracking software used the accurate time for one reading and the inaccurate time for the other

整型数字可能溢出导致的问题

In 2002, it was discovered that code supplied by Sun Microsystems to implement the XDR library, a widely used facility for sharing data structures between programs, had a security vulnerability arising from the fact that multiplication can overflow without any notice being given to the program.

Code similar to that containing the vulnerability is shown below:


/* Illustration of code vulnerability similar to that found in * Sun’s XDR library.

*/ 

void* copy_elements(void *ele_src[], int ele_cnt, size_t ele_size) { 
/* * Allocate buffer for ele_cnt objects, each of ele_size bytes * and copy from locations designated by ele_src */ 
	void *result = malloc(ele_cnt * ele_size); 
	if (result == NULL) /* malloc failed */ 
		return NULL; 
	void *next = result; 
	int i;

	for(i=0;i<ele_cnt;i++){
	
		/* Copy object i to destination */ 
		memcpy(next, ele_src[i], ele_size); /* Move pointer to next memory region */ 
		next += ele_size;
		} 
		return result;
	}

The function copy_elements is designed to copy ele_cnt data structures, each consisting of ele_ size bytes into a buffer allocated by the function on line 9. The number of bytes required is computed as ele_cnt * ele_size.

Imagine, however, that a malicious programmer calls this function with ele_cnt being 1,048,577 (2 20 + 1) and ele_size being 4,096 (2 12 ) with the program compiled for 32 bits. Then the multiplication on line 9 will overflow, causing only 4,096 bytes to be allocated, rather than the 4,294,971,392 bytes required to hold that much data. The loop starting at line 15 will attempt to copy all of those bytes, overrunning the end of the allocated buffer, and therefore corrupting other data structures. This could cause the program to crash or otherwise misbehave.

The Sun code was used by almost every operating system and in such widely used programs as Internet Explorer and the Kerberos authentication system. The Computer Emergency Response Team (CERT), an organization run by the Carnegie Mellon Software Engineering Institute to track security vulnerabilities and breaches, issued advisory “CA-2002-25,” and many companies rushed to patch their code. Fortunately, there were no reported security breaches caused by this vulnerability.

GetPeerName 问题

In 2002, programmers involved in the FreeBSD open-source operating systems project realized that their implementation of the getpeername library function had a security vulnerability. A simplified version of their code went something like this:

/*

* Illustration of code vulnerability similar to that found in * FreeBSD’s implementation of getpeername() */

/* Declaration of library function memcpy */

void *memcpy(void *dest, void *src, size_t n);
/* Kernel memory region holding user-accessible data */ 
#define KSIZE 1024 
char kbuf[KSIZE];
/* Copy at most maxlen bytes from kernel region to user buffer */
int copy_from_kernel(void *user_dest, int maxlen) {
/* Byte count len is minimum of buffer size and maxlen */
	int len = KSIZE < maxlen ? KSIZE : maxlen; 
	memcpy(user_dest, kbuf, len); return len; 
 }

In this code, we show the prototype for library function memcpy on line 7, which is designed to copy a specified number of bytes n from one region of memory to another.

The function copy_from_kernel, starting at line 14, is designed to copy some of the data maintained by the operating system kernel to a designated region of memory accessible to the user. Most of the data structures maintained by the kernel should not be readable by a user, since they may contain sensitive information about other users and about other jobs running on the system, but the region shown as kbuf was intended to be one that the user could read. The parameter maxlen is intended to be the length of the buffer allocated by the user and indicated by argument user_dest. The computation at line 16 then makes sure that no more bytes are copied than are available in either the source or the destination buffer.

Suppose, however, that some malicious programmer writes code that calls copy_from_kernel with a negative value of maxlen. Then the minimum computation on line 16 will compute this value for len, which will then be passed as the parameter n to memcpy. Note, however, that parameter n is declared as having data type size_t. This data type is declared (via typedef) in the library file stdio.h. Typically, it is defined to be unsigned for 32-bit programs and unsigned long for 64-bit programs. Since argument n is unsigned, memcpy will treat it as a very large positive number and attempt to copy that many bytes from the kernel region to the user’s buffer. Copying that many bytes (at least 231 ) will not actually work, because the program will encounter invalid addresses in the process, but the program could read regions of the kernel memory for which it is not authorized.

| 访问量:
Table of Contents