untrusted comment: verify with openbsd-71-base.pub
RWR2eHwZTOEiTY1Jxus+/PJ9oBgm90vuhl3E2mwHQTPEOAj33i2mzTfwZSS4S4hnD+hMnpV9TJ4bIWiSQhSXCr9Y+ltE5cJwZAc=

OpenBSD 7.1 errata 012, November 1, 2022:

In libexpat fix heap use-after-free vulnerability CVE-2022-43680.

Apply by doing:
   signify -Vep /etc/signify/openbsd-71-base.pub -x 012_expat.patch.sig \
       -m - | (cd /usr/src && patch -p0)

And then rebuild and install libexpat:
   cd /usr/src/lib/libexpat
   make obj
   make
   make install

Index: lib/libexpat/Changes
===================================================================
RCS file: /cvs/src/lib/libexpat/Changes,v
retrieving revision 1.21.2.1
diff -u -p -r1.21.2.1 Changes
--- lib/libexpat/Changes        22 Sep 2022 19:13:06 -0000      1.21.2.1
+++ lib/libexpat/Changes        27 Oct 2022 13:53:19 -0000
@@ -2,6 +2,40 @@ NOTE: We are looking for help with a few
      https://github.com/libexpat/libexpat/labels/help%20wanted
      If you can help, please get in touch.  Thanks!

+Release 2.5.0 Tue October 25 2022
+        Security fixes:
+  #616 #649 #650  CVE-2022-43680 -- Fix heap use-after-free after overeager
+                    destruction of a shared DTD in function
+                    XML_ExternalEntityParserCreate in out-of-memory situations.
+                    Expected impact is denial of service or potentially
+                    arbitrary code execution.
+
+        Bug fixes:
+       #612 #645  Fix curruption from undefined entities
+       #613 #654  Fix case when parsing was suspended while processing nested
+                    entities
+  #616 #652 #653  Stop leaking opening tag bindings after a closing tag
+                    mismatch error where a parser is reset through
+                    XML_ParserReset and then reused to parse
+            #656  CMake: Fix generation of pkg-config file
+            #658  MinGW|CMake: Fix static library name
+
+        Other changes:
+            #663  Protect header expat_config.h from multiple inclusion
+            #666  examples: Make use of XML_GetBuffer and be more
+                    consistent across examples
+            #648  Address compiler warnings
+       #667 #668  Version info bumped from 9:9:8 to 9:10:8;
+                    see https://verbump.de/ for what these numbers do
+
+        Special thanks to:
+            Jann Horn
+            Mark Brand
+            Osyotr
+            Rhodri James
+                 and
+            Google Project Zero
+
Release 2.4.9 Tue September 20 2022
        Security fixes:
       #629 #640  CVE-2022-40674 -- Heap use-after-free vulnerability in
Index: lib/libexpat/README.md
===================================================================
RCS file: /cvs/src/lib/libexpat/README.md,v
retrieving revision 1.13.2.1
diff -u -p -r1.13.2.1 README.md
--- lib/libexpat/README.md      22 Sep 2022 19:13:06 -0000      1.13.2.1
+++ lib/libexpat/README.md      27 Oct 2022 13:53:19 -0000
@@ -5,7 +5,7 @@
[![Downloads GitHub](https://img.shields.io/github/downloads/libexpat/libexpat/total?label=Downloads%20GitHub)](https://github.com/libexpat/libexpat/releases)


-# Expat, Release 2.4.9
+# Expat, Release 2.5.0

This is Expat, a C library for parsing XML, started by
[James Clark](https://en.wikipedia.org/wiki/James_Clark_%28programmer%29) in 1997.
Index: lib/libexpat/doc/reference.html
===================================================================
RCS file: /cvs/src/lib/libexpat/doc/reference.html,v
retrieving revision 1.17.2.1
diff -u -p -r1.17.2.1 reference.html
--- lib/libexpat/doc/reference.html     22 Sep 2022 19:13:06 -0000      1.17.2.1
+++ lib/libexpat/doc/reference.html     27 Oct 2022 13:53:19 -0000
@@ -50,7 +50,7 @@
  <div>
    <h1>
      The Expat XML Parser
-      <small>Release 2.4.9</small>
+      <small>Release 2.5.0</small>
    </h1>
  </div>
<div class="content">
Index: lib/libexpat/examples/elements.c
===================================================================
RCS file: /cvs/src/lib/libexpat/examples/elements.c,v
retrieving revision 1.11
diff -u -p -r1.11 elements.c
--- lib/libexpat/examples/elements.c    22 Feb 2022 10:53:11 -0000      1.11
+++ lib/libexpat/examples/elements.c    27 Oct 2022 13:53:20 -0000
@@ -14,7 +14,7 @@
   Copyright (c) 2001-2003 Fred L. Drake, Jr. <[email protected]>
   Copyright (c) 2004-2006 Karl Waclawek <[email protected]>
   Copyright (c) 2005-2007 Steven Solie <[email protected]>
-   Copyright (c) 2016-2019 Sebastian Pipping <[email protected]>
+   Copyright (c) 2016-2022 Sebastian Pipping <[email protected]>
   Copyright (c) 2017      Rhodri James <[email protected]>
   Copyright (c) 2019      Zhongyuan Zhou <[email protected]>
   Licensed under the MIT license:
@@ -49,7 +49,6 @@
#endif

#ifdef XML_UNICODE_WCHAR_T
-#  include <wchar.h>
#  define XML_FMT_STR "ls"
#else
#  define XML_FMT_STR "s"
@@ -58,7 +57,7 @@
static void XMLCALL
startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
  int i;
-  int *depthPtr = (int *)userData;
+  int *const depthPtr = (int *)userData;
  (void)atts;

  for (i = 0; i < *depthPtr; i++)
@@ -69,34 +68,54 @@ startElement(void *userData, const XML_C

static void XMLCALL
endElement(void *userData, const XML_Char *name) {
-  int *depthPtr = (int *)userData;
+  int *const depthPtr = (int *)userData;
  (void)name;

  *depthPtr -= 1;
}

int
-main(int argc, char *argv[]) {
-  char buf[BUFSIZ];
+main(void) {
  XML_Parser parser = XML_ParserCreate(NULL);
  int done;
  int depth = 0;
-  (void)argc;
-  (void)argv;
+
+  if (! parser) {
+    fprintf(stderr, "Couldn't allocate memory for parser\n");
+    return 1;
+  }

  XML_SetUserData(parser, &depth);
  XML_SetElementHandler(parser, startElement, endElement);
+
  do {
-    size_t len = fread(buf, 1, sizeof(buf), stdin);
-    done = len < sizeof(buf);
-    if (XML_Parse(parser, buf, (int)len, done) == XML_STATUS_ERROR) {
-      fprintf(stderr, "%" XML_FMT_STR " at line %" XML_FMT_INT_MOD "u\n",
-              XML_ErrorString(XML_GetErrorCode(parser)),
-              XML_GetCurrentLineNumber(parser));
+    void *const buf = XML_GetBuffer(parser, BUFSIZ);
+    if (! buf) {
+      fprintf(stderr, "Couldn't allocate memory for buffer\n");
+      XML_ParserFree(parser);
+      return 1;
+    }
+
+    const size_t len = fread(buf, 1, BUFSIZ, stdin);
+
+    if (ferror(stdin)) {
+      fprintf(stderr, "Read error\n");
+      XML_ParserFree(parser);
+      return 1;
+    }
+
+    done = feof(stdin);
+
+    if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) {
+      fprintf(stderr,
+              "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n",
+              XML_GetCurrentLineNumber(parser),
+              XML_ErrorString(XML_GetErrorCode(parser)));
      XML_ParserFree(parser);
      return 1;
    }
  } while (! done);
+
  XML_ParserFree(parser);
  return 0;
}
Index: lib/libexpat/examples/outline.c
===================================================================
RCS file: /cvs/src/lib/libexpat/examples/outline.c,v
retrieving revision 1.9
diff -u -p -r1.9 outline.c
--- lib/libexpat/examples/outline.c     22 Feb 2022 10:53:11 -0000      1.9
+++ lib/libexpat/examples/outline.c     27 Oct 2022 13:53:20 -0000
@@ -12,7 +12,7 @@
   Copyright (c) 2001-2003 Fred L. Drake, Jr. <[email protected]>
   Copyright (c) 2005-2007 Steven Solie <[email protected]>
   Copyright (c) 2005-2006 Karl Waclawek <[email protected]>
-   Copyright (c) 2016-2019 Sebastian Pipping <[email protected]>
+   Copyright (c) 2016-2022 Sebastian Pipping <[email protected]>
   Copyright (c) 2017      Rhodri James <[email protected]>
   Licensed under the MIT license:

@@ -51,73 +51,74 @@
#  define XML_FMT_STR "s"
#endif

-#define BUFFSIZE 8192
-
-char Buff[BUFFSIZE];
-
-int Depth;
-
static void XMLCALL
-start(void *data, const XML_Char *el, const XML_Char **attr) {
+startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
  int i;
-  (void)data;
+  int *const depthPtr = (int *)userData;

-  for (i = 0; i < Depth; i++)
+  for (i = 0; i < *depthPtr; i++)
    printf("  ");

-  printf("%" XML_FMT_STR, el);
+  printf("%" XML_FMT_STR, name);

-  for (i = 0; attr[i]; i += 2) {
-    printf(" %" XML_FMT_STR "='%" XML_FMT_STR "'", attr[i], attr[i + 1]);
+  for (i = 0; atts[i]; i += 2) {
+    printf(" %" XML_FMT_STR "='%" XML_FMT_STR "'", atts[i], atts[i + 1]);
  }

  printf("\n");
-  Depth++;
+  *depthPtr += 1;
}

static void XMLCALL
-end(void *data, const XML_Char *el) {
-  (void)data;
-  (void)el;
+endElement(void *userData, const XML_Char *name) {
+  int *const depthPtr = (int *)userData;
+  (void)name;

-  Depth--;
+  *depthPtr -= 1;
}

int
-main(int argc, char *argv[]) {
-  XML_Parser p = XML_ParserCreate(NULL);
-  (void)argc;
-  (void)argv;
+main(void) {
+  XML_Parser parser = XML_ParserCreate(NULL);
+  int done;
+  int depth = 0;

-  if (! p) {
+  if (! parser) {
    fprintf(stderr, "Couldn't allocate memory for parser\n");
-    exit(-1);
+    return 1;
  }

-  XML_SetElementHandler(p, start, end);
+  XML_SetUserData(parser, &depth);
+  XML_SetElementHandler(parser, startElement, endElement);

-  for (;;) {
-    int done;
-    int len;
+  do {
+    void *const buf = XML_GetBuffer(parser, BUFSIZ);
+    if (! buf) {
+      fprintf(stderr, "Couldn't allocate memory for buffer\n");
+      XML_ParserFree(parser);
+      return 1;
+    }
+
+    const size_t len = fread(buf, 1, BUFSIZ, stdin);

-    len = (int)fread(Buff, 1, BUFFSIZE, stdin);
    if (ferror(stdin)) {
      fprintf(stderr, "Read error\n");
-      exit(-1);
+      XML_ParserFree(parser);
+      return 1;
    }
+
    done = feof(stdin);

-    if (XML_Parse(p, Buff, len, done) == XML_STATUS_ERROR) {
+    if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) {
      fprintf(stderr,
              "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n",
-              XML_GetCurrentLineNumber(p),
-              XML_ErrorString(XML_GetErrorCode(p)));
-      exit(-1);
+              XML_GetCurrentLineNumber(parser),
+              XML_ErrorString(XML_GetErrorCode(parser)));
+      XML_ParserFree(parser);
+      return 1;
    }
+  } while (! done);

-    if (done)
-      break;
-  }
-  XML_ParserFree(p);
+  XML_ParserFree(parser);
  return 0;
}
Index: lib/libexpat/lib/xmlparse.c
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmlparse.c,v
retrieving revision 1.33.2.1
diff -u -p -r1.33.2.1 xmlparse.c
--- lib/libexpat/lib/xmlparse.c 22 Sep 2022 19:13:06 -0000      1.33.2.1
+++ lib/libexpat/lib/xmlparse.c 27 Oct 2022 13:53:21 -0000
@@ -1,4 +1,4 @@
-/* 90815a2b2c80c03b2b889fe1d427bb2b9e3282aa065e42784e001db4f23de324 (2.4.9+)
+/* 5ab094ffadd6edfc94c3eee53af44a86951f9f1f0933ada3114bbce2bfb02c99 (2.5.0+)
                            __  __            _
                         ___\ \/ /_ __   __ _| |_
                        / _ \\  /| '_ \ / _` | __|
@@ -35,6 +35,7 @@
   Copyright (c) 2021      Dong-hee Na <[email protected]>
   Copyright (c) 2022      Samanta Navarro <[email protected]>
   Copyright (c) 2022      Jeffrey Walton <[email protected]>
+   Copyright (c) 2022      Jann Horn <[email protected]>
   Licensed under the MIT license:

   Permission is  hereby granted,  free of charge,  to any  person obtaining
@@ -1068,6 +1069,14 @@ parserCreate(const XML_Char *encodingNam
  parserInit(parser, encodingName);

  if (encodingName && ! parser->m_protocolEncodingName) {
+    if (dtd) {
+      // We need to stop the upcoming call to XML_ParserFree from happily
+      // destroying parser->m_dtd because the DTD is shared with the parent
+      // parser and the only guard that keeps XML_ParserFree from destroying
+      // parser->m_dtd is parser->m_isParamEntity but it will be set to
+      // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all).
+      parser->m_dtd = NULL;
+    }
    XML_ParserFree(parser);
    return NULL;
  }
@@ -3011,9 +3020,6 @@ doContent(XML_Parser parser, int startTa
        int len;
        const char *rawName;
        TAG *tag = parser->m_tagStack;
-        parser->m_tagStack = tag->parent;
-        tag->parent = parser->m_freeTagList;
-        parser->m_freeTagList = tag;
        rawName = s + enc->minBytesPerChar * 2;
        len = XmlNameLength(enc, rawName);
        if (len != tag->rawNameLength
@@ -3021,6 +3027,9 @@ doContent(XML_Parser parser, int startTa
          *eventPP = rawName;
          return XML_ERROR_TAG_MISMATCH;
        }
+        parser->m_tagStack = tag->parent;
+        tag->parent = parser->m_freeTagList;
+        parser->m_freeTagList = tag;
        --parser->m_tagLevel;
        if (parser->m_endElementHandler) {
          const XML_Char *localPart;
@@ -4975,10 +4984,10 @@ doProlog(XML_Parser parser, const ENCODI
              parser->m_handlerArg, parser->m_declElementType->name,
              parser->m_declAttributeId->name, parser->m_declAttributeType, 0,
              role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
-          poolClear(&parser->m_tempPool);
          handleDefault = XML_FALSE;
        }
      }
+      poolClear(&parser->m_tempPool);
      break;
    case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
    case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
@@ -5386,7 +5395,7 @@ doProlog(XML_Parser parser, const ENCODI
             *
             * If 'standalone' is false, the DTD must have no
             * parameter entities or we wouldn't have passed the outer
-             * 'if' statement.  That measn the only entity in the hash
+             * 'if' statement.  That means the only entity in the hash
             * table is the external subset name "#" which cannot be
             * given as a parameter entity name in XML syntax, so the
             * lookup must have returned NULL and we don't even reach
@@ -5798,19 +5807,27 @@ internalEntityProcessor(XML_Parser parse

  if (result != XML_ERROR_NONE)
    return result;
-  else if (textEnd != next
-           && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
+
+  if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
    entity->processed = (int)(next - (const char *)entity->textPtr);
    return result;
-  } else {
+  }
+
#ifdef XML_DTD
-    entityTrackingOnClose(parser, entity, __LINE__);
+  entityTrackingOnClose(parser, entity, __LINE__);
#endif
-    entity->open = XML_FALSE;
-    parser->m_openInternalEntities = openEntity->next;
-    /* put openEntity back in list of free instances */
-    openEntity->next = parser->m_freeInternalEntities;
-    parser->m_freeInternalEntities = openEntity;
+  entity->open = XML_FALSE;
+  parser->m_openInternalEntities = openEntity->next;
+  /* put openEntity back in list of free instances */
+  openEntity->next = parser->m_freeInternalEntities;
+  parser->m_freeInternalEntities = openEntity;
+
+  // If there are more open entities we want to stop right here and have the
+  // upcoming call to XML_ResumeParser continue with entity content, or it would
+  // be ignored altogether.
+  if (parser->m_openInternalEntities != NULL
+      && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
+    return XML_ERROR_NONE;
  }

#ifdef XML_DTD
Index: lib/libexpat/lib/xmltok_impl.h
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmltok_impl.h,v
retrieving revision 1.4
diff -u -p -r1.4 xmltok_impl.h
--- lib/libexpat/lib/xmltok_impl.h      26 May 2021 19:14:32 -0000      1.4
+++ lib/libexpat/lib/xmltok_impl.h      27 Oct 2022 13:53:21 -0000
@@ -45,7 +45,7 @@ enum {
  BT_LF,       /* line feed = "\n" */
  BT_GT,       /* greater than = ">" */
  BT_QUOT,     /* quotation character = "\"" */
-  BT_APOS,     /* aposthrophe = "'" */
+  BT_APOS,     /* apostrophe = "'" */
  BT_EQUALS,   /* equal sign = "=" */
  BT_QUEST,    /* question mark = "?" */
  BT_EXCL,     /* exclamation mark = "!" */
Index: lib/libexpat/tests/runtests.c
===================================================================
RCS file: /cvs/src/lib/libexpat/tests/runtests.c,v
retrieving revision 1.16.2.1
diff -u -p -r1.16.2.1 runtests.c
--- lib/libexpat/tests/runtests.c       22 Sep 2022 19:13:07 -0000      1.16.2.1
+++ lib/libexpat/tests/runtests.c       27 Oct 2022 13:53:22 -0000
@@ -11,7 +11,7 @@
   Copyright (c) 2005-2007 Steven Solie <[email protected]>
   Copyright (c) 2005-2012 Karl Waclawek <[email protected]>
   Copyright (c) 2016-2022 Sebastian Pipping <[email protected]>
-   Copyright (c) 2017-2018 Rhodri James <[email protected]>
+   Copyright (c) 2017-2022 Rhodri James <[email protected]>
   Copyright (c) 2017      Joe Orton <[email protected]>
   Copyright (c) 2017      José Gutiérrez de la Concha <[email protected]>
   Copyright (c) 2018      Marco Maggi <[email protected]>
@@ -4990,7 +4990,7 @@ START_TEST(test_suspend_resume_internal_
}
END_TEST

-void
+static void XMLCALL
suspending_comment_handler(void *userData, const XML_Char *data) {
  UNUSED_P(data);
  XML_Parser parser = (XML_Parser)userData;
@@ -6734,6 +6734,102 @@ START_TEST(test_empty_element_abort) {
}
END_TEST

+/* Regression test for GH issue #612: unfinished m_declAttributeType
+ * allocation in ->m_tempPool can corrupt following allocation.
+ */
+static int XMLCALL
+external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context,
+                                   const XML_Char *base,
+                                   const XML_Char *systemId,
+                                   const XML_Char *publicId) {
+  const char *text = "<!ELEMENT barf ANY>\n"
+                     "<!ATTLIST barf my_attr (blah|%blah;a|foo) #REQUIRED>\n"
+                     "<!--COMMENT-->\n";
+  XML_Parser ext_parser;
+
+  UNUSED_P(base);
+  UNUSED_P(publicId);
+  if (systemId == NULL)
+    return XML_STATUS_OK;
+
+  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
+  if (ext_parser == NULL)
+    fail("Could not create external entity parser");
+
+  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
+      == XML_STATUS_ERROR)
+    xml_failure(ext_parser);
+
+  XML_ParserFree(ext_parser);
+  return XML_STATUS_OK;
+}
+
+START_TEST(test_pool_integrity_with_unfinished_attr) {
+  const char *text = "<?xml version='1.0' encoding='UTF-8'?>\n"
+                     "<!DOCTYPE foo [\n"
+                     "<!ELEMENT foo ANY>\n"
+                     "<!ENTITY % entp SYSTEM \"external.dtd\">\n"
+                     "%entp;\n"
+                     "]>\n"
+                     "<a></a>\n";
+  const XML_Char *expected = XCS("COMMENT");
+  CharData storage;
+
+  CharData_Init(&storage);
+  XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
+  XML_SetExternalEntityRefHandler(g_parser, external_entity_unfinished_attlist);
+  XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
+  XML_SetCommentHandler(g_parser, accumulate_comment);
+  XML_SetUserData(g_parser, &storage);
+  if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
+      == XML_STATUS_ERROR)
+    xml_failure(g_parser);
+  CharData_CheckXMLChars(&storage, expected);
+}
+END_TEST
+
+typedef struct {
+  XML_Parser parser;
+  CharData *storage;
+} ParserPlusStorage;
+
+static void XMLCALL
+accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) {
+  ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
+  accumulate_comment(parserPlusStorage->storage, data);
+  XML_StopParser(parserPlusStorage->parser, XML_TRUE);
+}
+
+START_TEST(test_nested_entity_suspend) {
+  const char *const text = "<!DOCTYPE a [\n"
+                           "  <!ENTITY e1 '<!--e1-->'>\n"
+                           "  <!ENTITY e2 '<!--e2 head-->&e1;<!--e2 tail-->'>\n"
+                           "  <!ENTITY e3 '<!--e3 head-->&e2;<!--e3 tail-->'>\n"
+                           "]>\n"
+                           "<a><!--start-->&e3;<!--end--></a>";
+  const XML_Char *const expected = XCS("start") XCS("e3 head") XCS("e2 head")
+      XCS("e1") XCS("e2 tail") XCS("e3 tail") XCS("end");
+  CharData storage;
+  XML_Parser parser = XML_ParserCreate(NULL);
+  ParserPlusStorage parserPlusStorage = {parser, &storage};
+
+  CharData_Init(&storage);
+  XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
+  XML_SetCommentHandler(parser, accumulate_and_suspend_comment_handler);
+  XML_SetUserData(parser, &parserPlusStorage);
+
+  enum XML_Status status = XML_Parse(parser, text, (int)strlen(text), XML_TRUE);
+  while (status == XML_STATUS_SUSPENDED) {
+    status = XML_ResumeParser(parser);
+  }
+  if (status != XML_STATUS_OK)
+    xml_failure(parser);
+
+  CharData_CheckXMLChars(&storage, expected);
+  XML_ParserFree(parser);
+}
+END_TEST
+
/*
 * Namespaces tests.
 */
@@ -7873,6 +7969,28 @@ START_TEST(test_misc_deny_internal_entit
}
END_TEST

+START_TEST(test_misc_tag_mismatch_reset_leak) {
+#ifdef XML_NS
+  const char *const text = "<open xmlns='https://namespace1.test'></close>";
+  XML_Parser parser = XML_ParserCreateNS(NULL, XCS('\n'));
+
+  if (XML_Parse(parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR)
+    fail("Call to parse was expected to fail");
+  if (XML_GetErrorCode(parser) != XML_ERROR_TAG_MISMATCH)
+    fail("Call to parse was expected to fail from a closing tag mismatch");
+
+  XML_ParserReset(parser, NULL);
+
+  if (XML_Parse(parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR)
+    fail("Call to parse was expected to fail");
+  if (XML_GetErrorCode(parser) != XML_ERROR_TAG_MISMATCH)
+    fail("Call to parse was expected to fail from a closing tag mismatch");
+
+  XML_ParserFree(parser);
+#endif
+}
+END_TEST
+
static void
alloc_setup(void) {
  XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
@@ -10090,6 +10208,53 @@ START_TEST(test_alloc_long_notation) {
}
END_TEST

+static int XMLCALL
+external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
+                                                 const XML_Char *context,
+                                                 const XML_Char *base,
+                                                 const XML_Char *systemId,
+                                                 const XML_Char *publicId) {
+  UNUSED_P(base);
+  UNUSED_P(systemId);
+  UNUSED_P(publicId);
+
+  if (context != NULL)
+    fail("Unexpected non-NULL context");
+
+  // The following number intends to fail the upcoming allocation in line
+  // "parser->m_protocolEncodingName = copyString(encodingName,
+  // &(parser->m_mem));" in function parserInit.
+  allocation_count = 3;
+
+  const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
+  const XML_Parser ext_parser
+      = XML_ExternalEntityParserCreate(parser, context, encodingName);
+  if (ext_parser != NULL)
+    fail(
+        "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
+
+  allocation_count = ALLOC_ALWAYS_SUCCEED;
+  return XML_STATUS_ERROR;
+}
+
+START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) {
+  const char *const text = "<!DOCTYPE doc SYSTEM 'foo'><doc/>";
+
+  XML_SetExternalEntityRefHandler(
+      g_parser, external_entity_parser_create_alloc_fail_handler);
+  XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
+
+  if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
+      != XML_STATUS_ERROR)
+    fail("Call to parse was expected to fail");
+
+  if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
+    fail("Call to parse was expected to fail from the external entity handler");
+
+  XML_ParserReset(g_parser, NULL);
+}
+END_TEST
+
static void
nsalloc_setup(void) {
  XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
@@ -12169,6 +12334,9 @@ make_suite(void) {
  tcase_add_test(tc_basic, test_bad_notation);
  tcase_add_test(tc_basic, test_default_doctype_handler);
  tcase_add_test(tc_basic, test_empty_element_abort);
+  tcase_add_test__ifdef_xml_dtd(tc_basic,
+                                test_pool_integrity_with_unfinished_attr);
+  tcase_add_test(tc_basic, test_nested_entity_suspend);

  suite_add_tcase(s, tc_namespace);
  tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
@@ -12221,6 +12389,7 @@ make_suite(void) {
  tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
  tcase_add_test__ifdef_xml_dtd(
      tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
+  tcase_add_test(tc_misc, test_misc_tag_mismatch_reset_leak);

  suite_add_tcase(s, tc_alloc);
  tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
@@ -12279,6 +12448,8 @@ make_suite(void) {
  tcase_add_test(tc_alloc, test_alloc_long_public_id);
  tcase_add_test(tc_alloc, test_alloc_long_entity_value);
  tcase_add_test(tc_alloc, test_alloc_long_notation);
+  tcase_add_test__ifdef_xml_dtd(
+      tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail);

  suite_add_tcase(s, tc_nsalloc);
  tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);