• 编写安全代码:死循环


    死循环,是不安全代码的一种,易造成CPU load过高,从而会导致低优先级进程得不到调度而饿死。

    基于这种危害,因此我们在写代码的时候要注意避免死循环。

    今天工作中就遇到了一个死循环导致CPU load过高,没有及时喂狗,导致NMI中断,板子重启的问题。

    针对网络协议的测试,有一种叫鲁棒性测试(robustness)。这种测试手段通过向系统发送各种各样错误的报文(比如某些字段值故意设成非法值),试图引发系统异常,从而测试协议软件是否足够健壮。

    来看代码片段:这是早期freeBSD中的代码:我省略一些无关的代码段。

     1 static void
     2 sctp_handle_stream_reset(struct sctp_tcb *stcb, struct sctp_stream_reset_req *sr_req)
     3 {
     4      int chk_length, param_len;
     5      struct sctp_paramhdr *ph;
     6  
     7      struct sctp_stream_reset_request *req;
     8      struct sctp_stream_reset_response *resp;
     9      chk_length = ntohs(sr_req->ch.chunk_length);
    10  
    11      ph = (struct sctp_paramhdr *)&sr_req->sr_req;
    12      while ( (size_t)chk_length >=  sizeof (struct sctp_stream_reset_request)) {
    13          param_len = ntohs(ph->param_length);
    14          if (ntohs(ph->param_type) == SCTP_STR_RESET_REQUEST) {
    15 
    16              req = (struct sctp_stream_reset_request *)ph;
    17              sctp_send_str_reset_ack(stcb, req);
    18          } else if (ntohs(ph->param_type) == SCTP_STR_RESET_RESPONSE) {
    19              
    20              resp = (struct sctp_stream_reset_response *)ph;
    21              sctp_handle_stream_reset_response(stcb, resp);
    22          }
    23          ph = (struct sctp_paramhdr *)((caddr_t)ph + SCTP_SIZE32(param_len));
    24          chk_length -= SCTP_SIZE32(param_len);
    25       }
    26 }

    这里有一个while循环,很容易发现如果param_len取值为零,死循环就此发生。

    偏偏不巧,鲁棒性测试的case就有这样的错误报文:

    000014

     Additional chunks

    000014

      Type

    000014

       Chunk-Type-STREAM-RESET

    .   82  

    000015

      Flags

    .   00  

    000016

      Length

    ..   00   18  

    000018

      Value

    000018

       First

    000018

        Type

    ..   00   0d  

    00001a

        Length

    ..   00   00 

    00001c

        Parameter Value

    00001c

         Request-Sequence

    ....   00   00   00   01  

    000020

         Response-Sequence

    ....   00   00   00   01  

    000024

         Last-TSN

    ....   8f   d2   b7   d4  

    000028

         Streams

    ....   00   00   00   01  

    00002c

       Second

    ()  

             

    不要轻易说这么简单的bug真是不应该,FreeBSD的大牛们写代码时都会犯错,何况我们呢?当然,最新的FreeBSD早就修掉这个bug啦。

    Correction很简单,增加对param_len的判断即可。

    在13行取得param_len之后。

             param_len = ntohs(ph->param_length);
            if (param_len < (int)sizeof(struct sctp_stream_reset_request)) {
                 /* bad param */
                 break;
            }

    如果细心点,你会发现在这个if里的表达式中有个(int)类型强转,这涉及到C语言的整型提升问题。这又是一个编写安全代码的良好习惯哦!

    不明白或有兴趣的可以参考我这篇博文:

    C语言拾遗(一):整型提升

    ---End---

  • 相关阅读:
    淡季买房注意细节 防售楼部“挂羊头卖狗肉”
    买房容易选房难 八大把关教您如何选好房
    socket发送接收字段采用Base64加密笔记
    深入理解JDK、JRE
    Socket读取JSONArray字串越界等相关问题
    android采用MediaPlayer监听EditText实现语音播报手机号码(阿拉伯数字)
    读取properties文件
    关于android客户端在线版本更新的总结(json源码)
    验证码
    base64举例
  • 原文地址:https://www.cnblogs.com/RandyXu/p/3450386.html
Copyright © 2020-2023  润新知