From d0277ca1ccd6ec8d786355a433717a9dbf41112e Mon Sep 17 00:00:00 2001
From: Bart Van Assche <bvanassche@acm.org>
Date: Sat, 7 Aug 2021 08:32:03 -0700
Subject: [PATCH] libsnmp: Fix a memory leak in a MIB parser error path

This patch should fix
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=36879.
---
 snmplib/parse.c | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/snmplib/parse.c b/snmplib/parse.c
index 6d9d84a..5eb675b 100644
--- a/snmplib/parse.c
+++ b/snmplib/parse.c
@@ -1865,18 +1865,22 @@ do_linkup(struct module *mp, struct node *np)
 }
 
 
-/*
+/**
+ * Read an OID from a file.
+ * @param[in]  file   File to read from.
+ * @param[out] id_arg Array to store the OID in.
+ * @param[in]  length Number of elements in the @id_arg array.
+ *
  * Takes a list of the form:
  * { iso org(3) dod(6) 1 }
  * and creates several nodes, one for each parent-child pair.
  * Returns 0 on error.
  */
 static int
-getoid(FILE * fp, struct subid_s *id,   /* an array of subids */
-       int length)
-{                               /* the length of the array */
-    register int    count;
-    int             type;
+getoid(FILE * fp, struct subid_s *id_arg, int length)
+{
+    struct subid_s *id = id_arg;
+    int             i, count, type;
     char            token[MAXTOKEN];
 
     if ((type = get_token(fp, token, MAXTOKEN)) != LEFTBRACKET) {
@@ -1904,11 +1908,11 @@ getoid(FILE * fp, struct subid_s *id,   /* an array of subids */
                          get_token(fp, token, MAXTOKEN)) != RIGHTPAREN) {
                         print_error("Expected a closing parenthesis",
                                     token, type);
-                        return 0;
+                        goto free_labels;
                     }
                 } else {
                     print_error("Expected a number", token, type);
-                    return 0;
+                    goto free_labels;
                 }
             } else {
                 continue;
@@ -1920,11 +1924,18 @@ getoid(FILE * fp, struct subid_s *id,   /* an array of subids */
             id->subid = strtoul(token, NULL, 10);
         } else {
             print_error("Expected label or number", token, type);
-            return 0;
+            goto free_labels;
         }
         type = get_token(fp, token, MAXTOKEN);
     }
     print_error("Too long OID", token, type);
+
+free_labels:
+    for (i = 0; i < count; i++) {
+        free(id[i].label);
+        id[i].label = NULL;
+    }
+
     return 0;
 }
 
-- 
1.8.3.1

