一行代码,损失 6000 万美元
1990 年 1 月 15 日,AT&T 的新泽西运营中心检测到大范围的系统故障,网络显示屏上出现了大量红色警告。尽管试图排除故障,但网络故障仍持续了 9 个小时,导致呼叫连接故障率达到 50%。AT&T 因此损失了 6000 多万美元,6 万多名美国人的电话完全无法接通。此外,500 个航班延误,8.5 万人受到影响。按理说,AT&T 的长途网络是高效率的典范,它利用先进的电子交换机和信号系统处理了全国大部分的电话。该系统通常能在几秒钟内完成电话路由选择。然而,就在这一天,从纽约的一个交换机开始,整个网络出现了故障。这是由于最近一次更新中的一个软件错误造成的,该错误影响了网络中的 114 个交换机。当纽约的交换机复位并发出信号时,这个错误引发了多米诺骨牌效应,导致大范围的网络中断。有趣的是,这个软件并没有经过测试。由于代码改动较小,因此按照管理层的要求绕过了测试。
问题所在
追根溯源,原因在于网络交换机实施的软件更新中出现了编码错误。该错误发生在一个 C 语言程序中,涉及嵌套条件语句中一个错位的中断语句,导致数据覆盖和系统重置。伪代码如下:
while (ring receive buffer not empty
and side buffer not empty):
Initialize pointer to first message in side buffer
or ring receive buffer
get copy of buffer
switch (message):
case (incoming_message):
if (sending switch is out of service):
if (ring write buffer is empty):
send "in service" to status map
else:
break // The error was here!
END IF
process incoming message, set up pointers to
optional parameters
break
END SWITCH
do optional parameter work
问题分析
如果环写入缓冲区不是空的,那么第 7 行的 `if` 语句就会被跳过,取而代之的是第 10 行的中断语句。
然而,为了使程序正常运行,本应执行第 11 行。
当中断语句被执行,而不是处理传入的信息并为可选参数设置指针时,数据(本应保留的指针)就会被覆盖
纠错软件识别出数据被覆盖,并启动关闭开关进行重置。由于网络中的所有交换机都使用了这种有缺陷的软件,导致了连锁重置反应,最终瘫痪了整个网络系统,使问题变得更加复杂。
追根溯源,原因在于网络交换机实施的软件更新中出现了编码错误。该错误发生在一个 C 语言程序中,涉及嵌套条件语句中一个错位的中断语句,导致数据覆盖和系统重置。伪代码如下:
while (ring receive buffer not empty
and side buffer not empty):
Initialize pointer to first message in side buffer
or ring receive buffer
get copy of buffer
switch (message):
case (incoming_message):
if (sending switch is out of service):
if (ring write buffer is empty):
send "in service" to status map
else:
break // The error was here!
END IF
process incoming message, set up pointers to
optional parameters
break
END SWITCH
do optional parameter work
问题分析
如果环写入缓冲区不是空的,那么第 7 行的 `if` 语句就会被跳过,取而代之的是第 10 行的中断语句。
然而,为了使程序正常运行,本应执行第 11 行。
当中断语句被执行,而不是处理传入的信息并为可选参数设置指针时,数据(本应保留的指针)就会被覆盖
纠错软件识别出数据被覆盖,并启动关闭开关进行重置。由于网络中的所有交换机都使用了这种有缺陷的软件,导致了连锁重置反应,最终瘫痪了整个网络系统,使问题变得更加复杂。
while (ring receive buffer not empty
and side buffer not empty):
Initialize pointer to first message in side buffer
or ring receive buffer
get copy of buffer
switch (message):
case (incoming_message):
if (sending switch is out of service):
if (ring write buffer is empty):
send "in service" to status map
else:
break // The error was here!
END IF
process incoming message, set up pointers to
optional parameters
break
END SWITCH
do optional parameter work
问题分析
如果环写入缓冲区不是空的,那么第 7 行的 `if` 语句就会被跳过,取而代之的是第 10 行的中断语句。
然而,为了使程序正常运行,本应执行第 11 行。
当中断语句被执行,而不是处理传入的信息并为可选参数设置指针时,数据(本应保留的指针)就会被覆盖
纠错软件识别出数据被覆盖,并启动关闭开关进行重置。由于网络中的所有交换机都使用了这种有缺陷的软件,导致了连锁重置反应,最终瘫痪了整个网络系统,使问题变得更加复杂。
如果环写入缓冲区不是空的,那么第 7 行的 `if` 语句就会被跳过,取而代之的是第 10 行的中断语句。
然而,为了使程序正常运行,本应执行第 11 行。
当中断语句被执行,而不是处理传入的信息并为可选参数设置指针时,数据(本应保留的指针)就会被覆盖
纠错软件识别出数据被覆盖,并启动关闭开关进行重置。由于网络中的所有交换机都使用了这种有缺陷的软件,导致了连锁重置反应,最终瘫痪了整个网络系统,使问题变得更加复杂。