--- ./lib/xmltok.c.orig	2026-03-17 14:51:51.000000000 -0500
+++ ./lib/xmltok.c	2026-08-11 15:01:27.041099208 -0500
@@ -703,9 +703,10 @@
     enum XML_Convert_Result res = XML_CONVERT_COMPLETED;                       \
     UNUSED_P(enc);                                                             \
     fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */  \
-    /* Avoid copying first half only of surrogate */                           \
+    /* Avoid copying the first half (2 bytes) of surrogate pairs (4 bytes) */  \
     if (fromLim - *fromP > ((toLim - *toP) << 1)                               \
-        && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) {                             \
+        && /* are the last two bytes a high surrogate (0xD800-0xDBFF)? */      \
+        (GET_HI(fromLim - 2) & 0xFC) == 0xD8) {                                \
       fromLim -= 2;                                                            \
       res = XML_CONVERT_INPUT_INCOMPLETE;                                      \
     }                                                                          \
--- ./lib/xmlparse.c.orig	2026-03-17 14:51:51.000000000 -0500
+++ ./lib/xmlparse.c	2026-08-11 15:01:27.041950456 -0500
@@ -6540,11 +6540,12 @@
         // Check if entity is complete, if not, mark down how much of it is
         // processed. A XML_SUSPENDED check here is not required as
         // appendAttributeValue will never suspend the parser.
-        if (textEnd != nextInEntity) {
+        if (nextInEntity < textEnd) {
           entity->processed
               = (int)(nextInEntity - (const char *)entity->textPtr);
           continue;
         }
+        assert(nextInEntity == textEnd);
 
         // Entity is complete. We cannot close it here since we need to first
         // process its possible inner entities (which are added to the
