3-June-2004 Mike Slifcak

This patch fixes memory leak and array bound violations
that were reported in bug # 895679 .

Several strategy changes were implemented:
 f. IF there are no printers, do not allocate an array of
    pointers to printer descriptions.

 2. It is believed that the number of printers attached to the system
    will not shrink significantly.  Therefore, once an array of
    pointers to printer descriptions is allocated, re-use it.

 3. If any function that references pointers to printer descriptions
    is called before those descriptions are initialized, exit with
    error, gracefully.

 4. Array upper bound does not change if memory allocation fails.

 5. If array grows, free old array storage to prevent memory leak.


Patch using net-snmp-5.1.1 or V5-1-patdhes branch,
Built using FreeBSD 5.2.1

--- net-snmp-5.1.1/agent/mibgroup/host/hr_print.c	Sun Jun 22 15:42:19 2003
+++ net-snmp/agent/mibgroup/host/hr_print.c	Wed Jun  2 23:34:30 2004
@@ -194,9 +194,11 @@
 	 *
 	 *********************/
 
-static int      HRP_index;
-static char   **HRP_name;
-static int      HRP_names, HRP_maxnames;
+static int      HRP_index = 0;
+static char   **HRP_name = NULL;	/* array of printer descriptions */
+static int      HRP_names = 0;		/* number of printer descriptions */
+
+#define HRP_MAX_INCR 10
 
 void
 Init_HR_Print(void)
@@ -212,15 +214,16 @@
     FILE           *p;
 #endif
 
+static int HRP_maxnames = 0;	/* upper bound on array size */
+
+    HRP_index = 0;		/* safe fail at Get_Next_HR_Print */
+
     if (HRP_name) {
+	/* free the descriptions, and keep the array. */
         for (i = 0; i < HRP_names; i++)
             free(HRP_name[i]);
         HRP_names = 0;
-    } else {
-        HRP_maxnames = 5;
-        HRP_name = (char **) calloc(HRP_maxnames, sizeof(char *));
-        if (!HRP_name)
-            return;
+        memset(HRP_name, 0, HRP_maxnames * sizeof(char *));
     }
 
 #if HAVE_PRINTCAP
@@ -255,11 +258,14 @@
 #endif
             if (HRP_names == HRP_maxnames) {
                 char          **tmp;
-                HRP_maxnames += 5;
-                tmp = (char **) calloc(HRP_maxnames, sizeof(char *));
+                tmp = (char **) calloc(HRP_maxnames + HRP_MAX_INCR, sizeof(char *));
                 if (!tmp)
                     goto finish;
-                memcpy(tmp, HRP_name, HRP_names * sizeof(char *));
+                HRP_maxnames += HRP_MAX_INCR;
+		if (HRP_name) {
+			memcpy(tmp, HRP_name, HRP_names * sizeof(char *));
+			free(HRP_name);
+		}
                 HRP_name = tmp;
             }
             HRP_name[HRP_names++] = strdup(ptr);
@@ -279,8 +285,6 @@
 #endif
     }
 #endif                          /* HAVE_anything */
-
-    HRP_index = 0;
 }
 
 int
@@ -301,6 +305,9 @@
 const char     *
 describe_printer(int idx)
 {
+    if (HRP_index == 0)  /* return empty string if not initialized */
+	return "";
+
     DEBUGMSGTL(("host/hr_print", "describe p: %d/%d %s\n", HRP_index, idx,
                 HRP_name[HRP_index - 1]));
     return HRP_name[HRP_index - 1];
