CHANGES: snmplib: PATCH: 1265: Fix a buffer overflow in dump_realloc_oid_to_inetaddress()
diff --git a/snmplib/mib.c b/snmplib/mib.c
index e498303..9d3ca41 100644
--- a/snmplib/mib.c
+++ b/snmplib/mib.c
@@ -3831,77 +3831,95 @@
                                 size_t * out_len, int allow_realloc, 
                                 char quotechar)
 {
-    if (buf) {
-        int             i, len;
-        char            intbuf[64], * p;
-        unsigned char  *zc;
-        unsigned long   zone;
+    int             i, len;
+    char            intbuf[64], *p;
+    char *const     end = intbuf + sizeof(intbuf);
+    unsigned char  *zc;
+    unsigned long   zone;
 
-        memset(intbuf, 0, 64);
+    if (!buf)
+        return 1;
 
-        p = intbuf;
-        *p = quotechar;
-        p++;
-        switch (addr_type) {
-            case IPV4:
-            case IPV4Z:
-                if ((addr_type == IPV4  && objidlen != 4) ||
-                    (addr_type == IPV4Z && objidlen != 8))
-                    return 2;
+    for (i = 0; i < objidlen; i++)
+        if (objid[i] < 0 || objid[i] > 255)
+            return 2;
 
-                len = sprintf(p, "%lu.%lu.%lu.%lu", objid[0], objid[1], objid[2], objid[3]);
-                p += len;
-                if (addr_type == IPV4Z) {
-                    zc = (unsigned char*)&zone;
-                    zc[0] = (u_char)(objid[4]);
-                    zc[1] = (u_char)(objid[5]);
-                    zc[2] = (u_char)(objid[6]);
-                    zc[3] = (u_char)(objid[7]);
-                    zone = ntohl(zone);
-                    len = sprintf(p, "%%%lu", zone);
-                    p += len;
-                }
+    p = intbuf;
+    *p++ = quotechar;
 
-                break;
+    switch (addr_type) {
+    case IPV4:
+    case IPV4Z:
+        if ((addr_type == IPV4  && objidlen != 4) ||
+            (addr_type == IPV4Z && objidlen != 8))
+            return 2;
 
-            case IPV6:
-            case IPV6Z:
-                if ((addr_type == IPV6 && objidlen != 16) ||
-                    (addr_type == IPV6Z && objidlen != 20))
-                    return 2;
-
-                len = 0;
-                for (i = 0; i < 16; i ++) {
-                    len = snprintf(p, 4, "%02lx:", objid[i]);
-                    p += len;
-                }
-                p-- ; /* do not include the last ':' */
-
-                if (addr_type == IPV6Z) {
-                    zc = (unsigned char*)&zone;
-                    zc[0] = (u_char)(objid[16]);
-                    zc[1] = (u_char)(objid[17]);
-                    zc[2] = (u_char)(objid[18]);
-                    zc[3] = (u_char)(objid[19]);
-                    zone = ntohl(zone);
-                    len = sprintf(p, "%%%lu", zone);
-                    p += len;
-                }
-
-                break;
-
-            case DNS:
-            default: 
-                /* DNS can just be handled by dump_realloc_oid_to_string() */
+        len = snprintf(p, end - p, "%" NETSNMP_PRIo "u.%" NETSNMP_PRIo "u."
+                      "%" NETSNMP_PRIo "u.%" NETSNMP_PRIo "u",
+                      objid[0], objid[1], objid[2], objid[3]);
+        p += len;
+        if (p >= end)
+            return 2;
+        if (addr_type == IPV4Z) {
+            zc = (unsigned char*)&zone;
+            zc[0] = objid[4];
+            zc[1] = objid[5];
+            zc[2] = objid[6];
+            zc[3] = objid[7];
+            zone = ntohl(zone);
+            len = snprintf(p, end - p, "%%%lu", zone);
+            p += len;
+            if (p >= end)
                 return 2;
         }
 
-        *p = quotechar;
+        break;
 
-        return snmp_strcat(buf, buf_len, out_len, allow_realloc, 
-                                               (const u_char *) intbuf);
+    case IPV6:
+    case IPV6Z:
+        if ((addr_type == IPV6 && objidlen != 16) ||
+            (addr_type == IPV6Z && objidlen != 20))
+            return 2;
+
+        len = 0;
+        for (i = 0; i < 16; i ++) {
+            len = snprintf(p, end - p, "%s%02" NETSNMP_PRIo "x", i ? ":" : "",
+                           objid[i]);
+            p += len;
+            if (p >= end)
+                return 2;
+        }
+
+        if (addr_type == IPV6Z) {
+            zc = (unsigned char*)&zone;
+            zc[0] = objid[16];
+            zc[1] = objid[17];
+            zc[2] = objid[18];
+            zc[3] = objid[19];
+            zone = ntohl(zone);
+            len = snprintf(p, end - p, "%%%lu", zone);
+            p += len;
+            if (p >= end)
+                return 2;
+        }
+
+        break;
+
+    case DNS:
+    default: 
+        /* DNS can just be handled by dump_realloc_oid_to_string() */
+        return 2;
     }
-    return 1;
+
+    *p++ = quotechar;
+    if (p >= end)
+        return 2;
+
+    *p++ = '\0';
+    if (p >= end)
+        return 2;
+
+    return snmp_cstrcat(buf, buf_len, out_len, allow_realloc, intbuf);
 }
 
 int