ports/82148: net-snmp: problem with negative integers on 64-bit platforms

Deomid Ryabkov myself at rojer.pp.ru
Sat Jun 11 20:30:24 UTC 2005


>Number:         82148
>Category:       ports
>Synopsis:       net-snmp: problem with negative integers on 64-bit platforms
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Jun 11 20:30:13 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Deomid Ryabkov
>Release:        5.4
>Organization:
>Environment:
FreeBSD pizza.rbc.ru 5.4-STABLE FreeBSD 5.4-STABLE #0: Fri Jun 10 11:17:47 MSD 2005     rojer at pizza.rbc.ru:/usr/obj/usr/src/sys/RBCSMP64.toxin  amd64

>Description:
reading negative integer values (e.g. dskMinPercent) sends snmpd into infinte loop.
the problem is specific to platforms with sizeof int > 4 and is not present in original net-snmp, but is introduced by patch-asn1.c.
>How-To-Repeat:
snmpwalk -v 1 target_host dsk

this will output lines up to dskMinimum, getting stuck on dskMinPercent
at the same time, snmpd starts to grow in size and the cpu usage is close to 100%.
>Fix:
patch-asn1.c, including the fix:
--- snmplib/asn1.c.orig Fri Dec 10 18:07:16 2004
+++ snmplib/asn1.c      Fri Jun 10 20:09:34 2005
@@ -181,6 +181,9 @@
 #include <in.h>
 #endif

+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #if HAVE_DMALLOC_H
 #include <dmalloc.h>
 #endif
@@ -584,6 +587,11 @@
         return NULL;
     }
     integer = *intp;
+    if (intsize > 4) {
+       register u_long signmask = ((u_long)1 << ((8 * sizeof(long)) - 1));
+       register u_long signbit = ((integer & signmask) != 0);
+       integer &= (signbit << 31) | 0x7fffffff;
+    }
     /*
      * Truncate "unnecessary" bytes off of the most significant end of this
      * 2's complement integer.  There should be no sequence of 9
@@ -663,6 +671,9 @@
         return NULL;
     }
     integer = *intp;
+    if (intsize > 4) {
+       integer &= 0xffffffff;
+    }
     mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
     /*
      * mask is 0xFF000000 on a big-endian machine
@@ -2668,19 +2679,26 @@
     register long   integer = *intp;
     int             testvalue = (*intp < 0) ? -1 : 0;
     size_t          start_offset = *offset;
+    int             imaxbytes = 4;

     if (intsize != sizeof(long)) {
         _asn_size_err(errpre, intsize, sizeof(long));
         return 0;
     }

+    if (intsize > 4) {
+       register u_long signmask = ((u_long)1 << ((8 * sizeof(long)) - 1));
+       register u_long signbit = ((integer & signmask) != 0);
+       integer &= (signbit << 31) | 0x7fffffff;
+    }
+
     if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
         return 0;
     }
     *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
     integer >>= 8;

-    while (integer != testvalue) {
+    while (integer != testvalue && (--imaxbytes)) {
         if (((*pkt_len - *offset) < 1)
             && !(r && asn_realloc(pkt, pkt_len))) {
             return 0;
@@ -2823,6 +2841,10 @@
     if (intsize != sizeof(unsigned long)) {
         _asn_size_err(errpre, intsize, sizeof(unsigned long));
         return 0;
+    }
+
+    if (intsize > 4) {
+       integer &= 0xffffffff;
     }

     if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {

>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list