下一课:没有代码是没有bug的

之前的一篇blog Bug是你的,也是他们的,但归根到底是你的!刚写了我质疑开源代码结果最后发现是自己的bug,结果下一课马上来了。

还是snort的AC pattern search实现,某一天突然发现,这个模块又出问题了,原因是这个程序是要匹配字符串开头的,但是当一个状态有多个输出pattern的时候,该算法传给用户出入的Match函数的居然不是存放输出pattern的链表,而是该链表的第一个节点的用户数据(udata),pattern以及匹配的位置index,连next指针都没传入……

程序使用的Match函数是要判断index值的,也即是index == 0 表示匹配上了字符串开头。

但是如果第一个pattern恰巧是我们想要找的pattern的后缀的话, 就会导致index不等于0,也就是说,没有匹配上开头。例如,我们要找的是foobar,但是状态机中还有一个pattern为bar,那么输出的pattern有可能是bar,此时index值(即匹配字符串在输入字符串中的开头位置)等于3,导致Match函数返回失败。

当然,我想acsmx2.c的作者可以说这是feature而不是bug,但是把函数里的一个if换成while来迭代整个状态输出链表会有多难呢?

最后,给这个代码打了个简单的patch,用一个while循环迭代输出状态链表,直到遍历或找到所要的pattern为止,然后程序就正确工作了,如下:

--- /src/sfutil/snort/acsmx2.c
+++ /src/sfutil/snort/acsmx2new.c
@@ -2277,7 +2277,7 @@
       if( ps[1] )
       {
         mlist = MatchList[state];
-        if (mlist)
+        while (mlist)
         {
             index = T - mlist->n - Tx;
             nfound++;
@@ -2286,6 +2286,7 @@
                 *current_state = state;
                 return nfound;
             }
+            mlist = mlist->next;
         }
       }

@@ -2294,7 +2295,7 @@

   /* Check the last state for a pattern match */
   mlist = MatchList[state];
-  if (mlist)
+  while (mlist)
   {
     index = T - mlist->n - Tx;
     nfound++;
@@ -2303,6 +2304,7 @@
        *current_state = state;
        return nfound;
     }
+    mlist = mlist->next;
   }

   *current_state = state;

但是,其实给第三方代码打patch是很不情愿的,一是带来了额外的维护工作量(毕竟我默认开源代码比我的代码质量高多了……),二是代码升级起来不是很方便。或许把这个patch提交给开源项目是个不错的办法,但是至于这个patch能不能被他们接受就不知道了……而更杯具的是,snort项目好像已经被商业机构接管了?

总结如下(完整了):

不要轻易质疑他人的代码,多找找自己的问题;但是也不能完全相信别人的代码就是没有问题的,因为人家也是跟你一样的码农……

总之就是,没有神马事情是省心的……

本文网址:http://blog.perlfect.me/2011/01/23/no-code-is-bug-free.html

comments powered by Disqus