No public description

PiperOrigin-RevId: 951751486
diff --git a/src/hunspell/affixmgr.cxx b/src/hunspell/affixmgr.cxx
index 5cb2356..40b8a65 100644
--- a/src/hunspell/affixmgr.cxx
+++ b/src/hunspell/affixmgr.cxx
@@ -3725,13 +3725,21 @@
    }
    if (np != 2) {
       HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum());
+      if (*rl) {
+        delete *rl;
+        *rl = NULL;
+      }
       return 1;
    } 
  
    /* now parse the num lines to read in the remainder of the table */
    char * nl;
    for (int j=0; j < numrl; j++) {
-        if (!(nl = af->getline())) return 1;
+     if (!(nl = af->getline())) {
+       delete *rl;
+       *rl = NULL;
+       return 1;
+     }
         mychomp(nl);
         tp = nl;
         i = 0;
@@ -3767,6 +3775,8 @@
             if (pattern2)
                 free(pattern2);
             HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
+            delete *rl;
+            *rl = NULL;
             return 1;
         }
         (*rl)->add(pattern, pattern2);
@@ -3822,13 +3832,26 @@
    }
    if (np != 2) {
       HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum());
+      if (phone) {
+        if (phone->rules) free(phone->rules);
+        free(phone);
+        phone = NULL;
+      }
       return 1;
    } 
  
    /* now parse the phone->num lines to read in the remainder of the table */
    char * nl;
    for (int j=0; j < phone->num; j++) {
-        if (!(nl = af->getline())) return 1;
+     if (!(nl = af->getline())) {
+       for (int k = 0; k < 2 * (phone->num + 1); k++) {
+         if (phone->rules[k]) free(phone->rules[k]);
+       }
+       free(phone->rules);
+       free(phone);
+       phone = NULL;
+       return 1;
+     }
         mychomp(nl);
         tp = nl;
         i = 0;
@@ -3841,7 +3864,13 @@
                   case 0: {
                              if (strncmp(piece,"PHONE",5) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
-                                 phone->num = 0;
+                                 for (int k = 0; k < 2 * (phone->num + 1);
+                                      k++) {
+                                   if (phone->rules[k]) free(phone->rules[k]);
+                                 }
+                                 free(phone->rules);
+                                 free(phone);
+                                 phone = NULL;
                                  return 1;
                              }
                              break;
@@ -3856,7 +3885,12 @@
         }
         if ((!(phone->rules[j * 2])) || (!(phone->rules[j * 2 + 1]))) {
              HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
-             phone->num = 0;
+             for (int k = 0; k < 2 * (phone->num + 1); k++) {
+               if (phone->rules[k]) free(phone->rules[k]);
+             }
+             free(phone->rules);
+             free(phone);
+             phone = NULL;
              return 1;
         }
    }
@@ -3902,13 +3936,28 @@
    }
    if (np != 2) {
       HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",  af->getlinenum());
+      if (checkcpdtable) {
+        free(checkcpdtable);
+        checkcpdtable = NULL;
+      }
+      numcheckcpd = 0;
       return 1;
    }
 
    /* now parse the numcheckcpd lines to read in the remainder of the table */
    char * nl;
    for (int j=0; j < numcheckcpd; j++) {
-        if (!(nl = af->getline())) return 1;
+     if (!(nl = af->getline())) {
+       for (int k = 0; k < j; k++) {
+         if (checkcpdtable[k].pattern) free(checkcpdtable[k].pattern);
+         if (checkcpdtable[k].pattern2) free(checkcpdtable[k].pattern2);
+         if (checkcpdtable[k].pattern3) free(checkcpdtable[k].pattern3);
+       }
+       free(checkcpdtable);
+       checkcpdtable = NULL;
+       numcheckcpd = 0;
+       return 1;
+     }
         mychomp(nl);
         tp = nl;
         i = 0;
@@ -3924,6 +3973,16 @@
                   case 0: {
                              if (strncmp(piece,"CHECKCOMPOUNDPATTERN",20) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
+                                 for (int k = 0; k < j; k++) {
+                                   if (checkcpdtable[k].pattern)
+                                     free(checkcpdtable[k].pattern);
+                                   if (checkcpdtable[k].pattern2)
+                                     free(checkcpdtable[k].pattern2);
+                                   if (checkcpdtable[k].pattern3)
+                                     free(checkcpdtable[k].pattern3);
+                                 }
+                                 free(checkcpdtable);
+                                 checkcpdtable = NULL;
                                  numcheckcpd = 0;
                                  return 1;
                              }
@@ -3955,6 +4014,13 @@
         }
         if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) {
              HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
+             for (int k = 0; k <= j; k++) {
+               if (checkcpdtable[k].pattern) free(checkcpdtable[k].pattern);
+               if (checkcpdtable[k].pattern2) free(checkcpdtable[k].pattern2);
+               if (checkcpdtable[k].pattern3) free(checkcpdtable[k].pattern3);
+             }
+             free(checkcpdtable);
+             checkcpdtable = NULL;
              numcheckcpd = 0;
              return 1;
         }
@@ -4211,13 +4277,26 @@
    }
    if (np != 2) {
       HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum());
+      if (breaktable) {
+        free(breaktable);
+        breaktable = NULL;
+      }
+      numbreak = -1;
       return 1;
    } 
  
    /* now parse the numbreak lines to read in the remainder of the table */
    char * nl;
    for (int j=0; j < numbreak; j++) {
-        if (!(nl = af->getline())) return 1;
+     if (!(nl = af->getline())) {
+       for (int k = 0; k < j; k++) {
+         if (breaktable[k]) free(breaktable[k]);
+       }
+       free(breaktable);
+       breaktable = NULL;
+       numbreak = -1;
+       return 1;
+     }
         mychomp(nl);
         tp = nl;
         i = 0;
@@ -4228,7 +4307,12 @@
                   case 0: {
                              if (strncmp(piece,"BREAK",5) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
-                                 numbreak = 0;
+                                 for (int k = 0; k < j; k++) {
+                                   if (breaktable[k]) free(breaktable[k]);
+                                 }
+                                 free(breaktable);
+                                 breaktable = NULL;
+                                 numbreak = -1;
                                  return 1;
                              }
                              break;
@@ -4245,7 +4329,12 @@
         }
         if (!breaktable) {
              HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum());
-             numbreak = 0;
+             for (int k = 0; k <= j; k++) {
+               if (breaktable[k]) free(breaktable[k]);
+             }
+             free(breaktable);
+             breaktable = NULL;
+             numbreak = -1;
              return 1;
         }
    }
@@ -4278,6 +4367,37 @@
     }
 }
 
+namespace {
+
+void clean_affentries(std::vector<affentry>& affentries) {
+  for (affentry& entry : affentries) {
+    if (entry.strip) {
+      free(entry.strip);
+      entry.strip = NULL;
+    }
+    if (entry.appnd) {
+      free(entry.appnd);
+      entry.appnd = NULL;
+    }
+    if (entry.opts & aeLONGCOND) {
+      if (entry.c.l.conds2) {
+        free(entry.c.l.conds2);
+        entry.c.l.conds2 = NULL;
+      }
+    }
+    if (entry.morphcode && !(entry.opts & aeALIASM)) {
+      free(entry.morphcode);
+      entry.morphcode = NULL;
+    }
+    if (entry.contclass && !(entry.opts & aeALIASF)) {
+      free(entry.contclass);
+      entry.contclass = NULL;
+    }
+  }
+}
+
+}  // namespace
+
 int  AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupflags)
 {
    int numents = 0;      // number of affentry structures to parse
@@ -4358,6 +4478,7 @@
             HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum());
             free(err);
        }
+       clean_affentries(affentries);
        return 1;
    }
  
@@ -4365,7 +4486,10 @@
    std::vector<affentry>::iterator start = affentries.begin();
    std::vector<affentry>::iterator end = affentries.end();
    for (std::vector<affentry>::iterator entry = start; entry != end; ++entry) {
-      if (!(nl = af->getline())) return 1;
+     if (!(nl = af->getline())) {
+       clean_affentries(affentries);
+       return 1;
+     }
       mychomp(nl);
       tp = nl;
       i = 0;
@@ -4394,6 +4518,7 @@
                                     af->getlinenum(), err);
                                 free(err);
                               }
+                              clean_affentries(affentries);
                               return 1;
                           }
 
@@ -4493,7 +4618,10 @@
                             reverseword(piece);
                             reverse_condition(piece);
                           }
-                          if (encodeit(*entry, piece)) return 1;
+                          if (encodeit(*entry, piece)) {
+                            clean_affentries(affentries);
+                            return 1;
+                          }
                          break;
                 }
 
@@ -4512,7 +4640,10 @@
                                 tp = tp + strlen(tp);
                             }
                             entry->morphcode = mystrdup(piece);
-                            if (!entry->morphcode) return 1;
+                            if (!entry->morphcode) {
+                              clean_affentries(affentries);
+                              return 1;
+                            }
                           }
                           break; 
                 }
@@ -4530,6 +4661,7 @@
                 af->getlinenum(), err);
             free(err);
           }
+          clean_affentries(affentries);
           return 1;
       }