Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package aws-c-common for openSUSE:Factory 
checked in at 2026-07-21 22:59:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/aws-c-common (Old)
 and      /work/SRC/openSUSE:Factory/.aws-c-common.new.24530 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "aws-c-common"

Tue Jul 21 22:59:42 2026 rev:33 rq:1366706 version:0.14.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/aws-c-common/aws-c-common.changes        
2026-07-08 17:42:17.101488047 +0200
+++ /work/SRC/openSUSE:Factory/.aws-c-common.new.24530/aws-c-common.changes     
2026-07-21 22:59:49.016518765 +0200
@@ -1,0 +2,9 @@
+Fri Jul 17 08:50:50 UTC 2026 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to 0.14.2
+  * CI improvements by @azkrishpy in (#1252)
+  * Byte Buf Helper Func Dynamic or Static by @sbSteveK in (#1253)
+  * Update deprecated OpenBSD CI job by @sfod in (#1255)
+  * XML Parser Fixes by @sbSteveK in (#1254)
+
+-------------------------------------------------------------------

Old:
----
  v0.14.1.tar.gz

New:
----
  v0.14.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ aws-c-common.spec ++++++
--- /var/tmp/diff_new_pack.QHPZRL/_old  2026-07-21 22:59:50.256561022 +0200
+++ /var/tmp/diff_new_pack.QHPZRL/_new  2026-07-21 22:59:50.256561022 +0200
@@ -19,7 +19,7 @@
 %define library_version 1.0.0
 %define library_soversion 1
 Name:           aws-c-common
-Version:        0.14.1
+Version:        0.14.2
 Release:        0
 Summary:        Core C99 package for AWS SDK for C
 License:        Apache-2.0

++++++ v0.14.1.tar.gz -> v0.14.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-common-0.14.1/.github/workflows/ci.yml 
new/aws-c-common-0.14.2/.github/workflows/ci.yml
--- old/aws-c-common-0.14.1/.github/workflows/ci.yml    2026-06-24 
19:58:50.000000000 +0200
+++ new/aws-c-common-0.14.2/.github/workflows/ci.yml    2026-07-09 
18:53:07.000000000 +0200
@@ -6,7 +6,7 @@
       - 'main'
 
 env:
-  BUILDER_VERSION: v0.9.92
+  BUILDER_VERSION: v0.9.96
   BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net
   BUILDER_SOURCE: releases
   PACKAGE_NAME: aws-c-common
@@ -251,6 +251,11 @@
 
   openbsd:
     runs-on: ubuntu-24.04  # unit tests hang on macos; use ubuntu instead
+    strategy:
+      fail-fast: false
+      matrix:
+        # OpenBSD only supports the two most recent releases
+        version: ['7.8', '7.9']
     steps:
     - uses: aws-actions/configure-aws-credentials@v6
       with:
@@ -258,10 +263,10 @@
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
     - uses: actions/checkout@v6
     - name: Build ${{ env.PACKAGE_NAME }} + consumers
-      uses: cross-platform-actions/[email protected]
+      uses: cross-platform-actions/[email protected]
       with:
         operating_system: openbsd
-        version: '7.5'
+        version: ${{ matrix.version }}
         shell: bash
         run: |
           sudo pkg_add py3-urllib3
@@ -280,7 +285,7 @@
       with:
         submodules: true
     - name: Build ${{ env.PACKAGE_NAME }} + consumers
-      uses: cross-platform-actions/[email protected]
+      uses: cross-platform-actions/[email protected]
       with:
         operating_system: freebsd
         version: '14.1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aws-c-common-0.14.1/.github/workflows/issue-regression-labeler.yml 
new/aws-c-common-0.14.2/.github/workflows/issue-regression-labeler.yml
--- old/aws-c-common-0.14.1/.github/workflows/issue-regression-labeler.yml      
2026-06-24 19:58:50.000000000 +0200
+++ new/aws-c-common-0.14.2/.github/workflows/issue-regression-labeler.yml      
2026-07-09 18:53:07.000000000 +0200
@@ -24,9 +24,12 @@
     - name: Manage regression label
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        IS_REGRESSION: ${{ steps.check_regression.outputs.is_regression }}
+        ISSUE_NUMBER: ${{ github.event.issue.number }}
+        REPO: ${{ github.repository }}
       run: |
-        if [ "${{ steps.check_regression.outputs.is_regression }}" == "true" 
]; then
-          gh issue edit ${{ github.event.issue.number }} --add-label 
"potential-regression" -R ${{ github.repository }}
+        if [ "$IS_REGRESSION" == "true" ]; then
+          gh issue edit "$ISSUE_NUMBER" --add-label "potential-regression" -R 
"$REPO"
         else
-          gh issue edit ${{ github.event.issue.number }} --remove-label 
"potential-regression" -R ${{ github.repository }}
+          gh issue edit "$ISSUE_NUMBER" --remove-label "potential-regression" 
-R "$REPO"
         fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-common-0.14.1/include/aws/common/byte_buf.h 
new/aws-c-common-0.14.2/include/aws/common/byte_buf.h
--- old/aws-c-common-0.14.1/include/aws/common/byte_buf.h       2026-06-24 
19:58:50.000000000 +0200
+++ new/aws-c-common-0.14.2/include/aws/common/byte_buf.h       2026-07-09 
18:53:07.000000000 +0200
@@ -23,6 +23,19 @@
  * Note that this structure allocates memory at the buffer pointer only. The
  * struct itself does not get dynamically allocated and must be either
  * maintained or copied to avoid losing access to the memory.
+ *
+ * GROWABILITY CONTRACT:
+ * - When `allocator != NULL`: the buffer owns its memory and can be grown
+ *   via aws_byte_buf_reserve / aws_byte_buf_append_dynamic / etc.
+ * - When `allocator == NULL`: the buffer's memory is externally owned
+ *   (e.g. by a buffer pool, by static storage, or by a stack frame) and
+ *   MUST NOT be reallocated. Functions that would grow the buffer
+ *   (aws_byte_buf_reserve, aws_byte_buf_append_dynamic, etc.) fail with
+ *   AWS_ERROR_INVALID_ARGUMENT when called on such a buffer.
+ *
+ * Callers that may receive a buffer of either kind (e.g. from a buffer
+ * pool ticket) should use aws_byte_buf_append_auto, which selects
+ * the right append path automatically.
  */
 struct aws_byte_buf {
     /* do not reorder this, this struct lines up nicely with windows buffer 
structures--saving us allocations.*/
@@ -415,6 +428,28 @@
 int aws_byte_buf_append_dynamic(struct aws_byte_buf *to, const struct 
aws_byte_cursor *from);
 
 /**
+ * Copies `from` to `to`, selecting between static and dynamic append based
+ * on whether `to` has an allocator.
+ *
+ * - If `to->allocator != NULL`: uses aws_byte_buf_append_dynamic (grows
+ *   the buffer as needed; same behavior as calling that function directly).
+ * - If `to->allocator == NULL`: uses aws_byte_buf_append (no grow; returns
+ *   AWS_ERROR_DEST_COPY_TOO_SMALL if `from` does not fit in remaining
+ *   capacity).
+ *
+ * This is intended for callers that receive a buffer from a source whose
+ * growability is not known at the call site — most commonly a buffer
+ * obtained from an aws_s3_buffer_pool ticket, where pool-backed tickets
+ * return a fixed-size buffer (allocator == NULL) and the default pool may
+ * return a growable one.
+ *
+ * `from` and `to` may be the same buffer, permitting copying a buffer
+ * into itself.
+ */
+AWS_COMMON_API
+int aws_byte_buf_append_auto(struct aws_byte_buf *to, const struct 
aws_byte_cursor *from);
+
+/**
  * Copies `from` to `to`. If `to` is too small, the buffer will be grown 
appropriately and
  * the old contents copied over, before the new contents are appended.
  *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-common-0.14.1/source/byte_buf.c 
new/aws-c-common-0.14.2/source/byte_buf.c
--- old/aws-c-common-0.14.1/source/byte_buf.c   2026-06-24 19:58:50.000000000 
+0200
+++ new/aws-c-common-0.14.2/source/byte_buf.c   2026-07-09 18:53:07.000000000 
+0200
@@ -760,6 +760,21 @@
     return s_aws_byte_buf_append_dynamic(to, from, false);
 }
 
+int aws_byte_buf_append_auto(struct aws_byte_buf *to, const struct 
aws_byte_cursor *from) {
+    AWS_PRECONDITION(aws_byte_buf_is_valid(to));
+    AWS_PRECONDITION(aws_byte_cursor_is_valid(from));
+
+    /*
+     * Buffers without an allocator are externally-owned (e.g. by a
+     * buffer pool); they cannot grow, so use the static append path.
+     * Buffers with an allocator can grow, so use the dynamic path.
+     */
+    if (to->allocator != NULL) {
+        return aws_byte_buf_append_dynamic(to, from);
+    }
+    return aws_byte_buf_append(to, from);
+}
+
 int aws_byte_buf_append_dynamic_secure(struct aws_byte_buf *to, const struct 
aws_byte_cursor *from) {
     return s_aws_byte_buf_append_dynamic(to, from, true);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-common-0.14.1/source/xml_parser.c 
new/aws-c-common-0.14.2/source/xml_parser.c
--- old/aws-c-common-0.14.1/source/xml_parser.c 2026-06-24 19:58:50.000000000 
+0200
+++ new/aws-c-common-0.14.2/source/xml_parser.c 2026-07-09 18:53:07.000000000 
+0200
@@ -40,6 +40,11 @@
     AWS_PRECONDITION(decl_body);
     AWS_PRECONDITION(node);
 
+    if (decl_body->len == 0) {
+        AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document is invalid.");
+        return aws_raise_error(AWS_ERROR_INVALID_XML);
+    }
+
     node->is_empty = decl_body->ptr[decl_body->len - 1] == '/';
 
     struct aws_array_list splits;
@@ -159,6 +164,77 @@
     return parser.error;
 }
 
+/* Returns true if the byte can follow a tag name in a start or empty-element 
tag. */
+static bool s_is_tag_name_boundary(uint8_t c) {
+    return c == ' ' || c == '>' || c == '/' || c == '\t' || c == '\r' || c == 
'\n';
+}
+
+static struct aws_byte_cursor s_comment_prefix = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("<!--");
+static struct aws_byte_cursor s_comment_end = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("-->");
+static struct aws_byte_cursor s_cdata_prefix = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("<![CDATA[");
+static struct aws_byte_cursor s_cdata_end = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("]]>");
+static struct aws_byte_cursor s_pi_prefix = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("<?");
+static struct aws_byte_cursor s_pi_end = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("?>");
+static struct aws_byte_cursor s_self_close_suffix = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/>");
+static struct aws_byte_cursor s_decl_prefix = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("<!");
+static struct aws_byte_cursor s_close_bracket = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(">");
+static struct aws_byte_cursor s_closing_prefix = 
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("</");
+
+/*
+ * If `*input` points at a non-element construct (comment, CDATA, or PI), 
advances
+ * `*input` past the construct's closing delimiter, sets `*out_skipped = 
true`, and
+ * returns AWS_OP_SUCCESS.
+ *
+ * If `*input` does not start with a non-element construct, sets `*out_skipped 
= false`
+ * and returns AWS_OP_SUCCESS (caller should proceed with normal element 
handling).
+ *
+ * If the construct is unterminated (no closing delimiter found), returns 
AWS_OP_ERR
+ * and raises AWS_ERROR_INVALID_XML.
+ *
+ * WARNING: This function assumes `*input` starts with '<'. It will not 
produce correct
+ * results if called at an arbitrary position within a document.
+ */
+static int s_try_skip_non_element(struct aws_byte_cursor *input, bool 
*out_skipped) {
+    *out_skipped = false;
+
+    if (input->len == 0 || input->ptr[0] != '<') {
+        return AWS_OP_SUCCESS;
+    }
+
+    if (aws_byte_cursor_starts_with(input, &s_comment_prefix)) {
+        aws_byte_cursor_advance(input, s_comment_prefix.len);
+        struct aws_byte_cursor found;
+        if (aws_byte_cursor_find_exact(input, &s_comment_end, &found)) {
+            return aws_raise_error(AWS_ERROR_INVALID_XML);
+        }
+        aws_byte_cursor_advance(input, (found.ptr + s_comment_end.len) - 
input->ptr);
+        *out_skipped = true;
+        return AWS_OP_SUCCESS;
+    }
+    if (aws_byte_cursor_starts_with(input, &s_cdata_prefix)) {
+        aws_byte_cursor_advance(input, s_cdata_prefix.len);
+        struct aws_byte_cursor found;
+        if (aws_byte_cursor_find_exact(input, &s_cdata_end, &found)) {
+            return aws_raise_error(AWS_ERROR_INVALID_XML);
+        }
+        aws_byte_cursor_advance(input, (found.ptr + s_cdata_end.len) - 
input->ptr);
+        *out_skipped = true;
+        return AWS_OP_SUCCESS;
+    }
+    if (aws_byte_cursor_starts_with(input, &s_pi_prefix)) {
+        aws_byte_cursor_advance(input, s_pi_prefix.len);
+        struct aws_byte_cursor found;
+        if (aws_byte_cursor_find_exact(input, &s_pi_end, &found)) {
+            return aws_raise_error(AWS_ERROR_INVALID_XML);
+        }
+        aws_byte_cursor_advance(input, (found.ptr + s_pi_end.len) - 
input->ptr);
+        *out_skipped = true;
+        return AWS_OP_SUCCESS;
+    }
+
+    return AWS_OP_SUCCESS;
+}
+
 int s_advance_to_closing_tag(
     struct aws_xml_parser *parser,
     struct aws_xml_node *node,
@@ -208,45 +284,68 @@
     aws_byte_buf_append(&closing_cmp_buf, &node->name);
     aws_byte_buf_append(&closing_cmp_buf, &close_bracket);
 
-    size_t depth_count = 1;
     struct aws_byte_cursor to_find_open = 
aws_byte_cursor_from_buf(&open_cmp_buf);
     struct aws_byte_cursor to_find_close = 
aws_byte_cursor_from_buf(&closing_cmp_buf);
-    struct aws_byte_cursor close_find_result;
-    AWS_ZERO_STRUCT(close_find_result);
-    do {
-        if (aws_byte_cursor_find_exact(&parser->doc, &to_find_close, 
&close_find_result)) {
+
+    /* Single forward scan: jump between '<' characters, tracking nesting 
depth. */
+    size_t depth = 1;
+    while (parser->doc.len > 0) {
+        const uint8_t *open = memchr(parser->doc.ptr, '<', parser->doc.len);
+        if (!open) {
+            break;
+        }
+        aws_byte_cursor_advance(&parser->doc, open - parser->doc.ptr);
+
+        /* Skip non-element constructs (comments, CDATA, PI). */
+        bool skipped = false;
+        if (s_try_skip_non_element(&parser->doc, &skipped)) {
             AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document is 
invalid.");
-            return aws_raise_error(AWS_ERROR_INVALID_XML);
+            return AWS_OP_ERR;
+        }
+        if (skipped) {
+            continue;
         }
 
-        /* if we find an opening node with the same name, before the closing 
tag keep going. */
-        struct aws_byte_cursor open_find_result;
-        AWS_ZERO_STRUCT(open_find_result);
-
-        while (parser->doc.len) {
-            if (!aws_byte_cursor_find_exact(&parser->doc, &to_find_open, 
&open_find_result)) {
-                if (open_find_result.ptr < close_find_result.ptr) {
-                    size_t skip_len = open_find_result.ptr - parser->doc.ptr;
-                    aws_byte_cursor_advance(&parser->doc, skip_len + 1);
-                    depth_count++;
-                    continue;
+        /* Check for closing tag. */
+        if (aws_byte_cursor_starts_with(&parser->doc, &to_find_close)) {
+            depth--;
+            if (depth == 0) {
+                size_t len = parser->doc.ptr - node->doc_at_body.ptr;
+                if (out_body) {
+                    *out_body = 
aws_byte_cursor_from_array(node->doc_at_body.ptr, len);
                 }
+                aws_byte_cursor_advance(&parser->doc, to_find_close.len);
+                return parser->error;
             }
-            size_t skip_len = close_find_result.ptr - parser->doc.ptr;
-
-            aws_byte_cursor_advance(&parser->doc, skip_len + 
closing_cmp_buf.len);
-            depth_count--;
-            break;
+            aws_byte_cursor_advance(&parser->doc, to_find_close.len);
+            continue;
         }
-    } while (depth_count > 0);
 
-    size_t len = close_find_result.ptr - node->doc_at_body.ptr;
+        /* Check for opening tag with same name. */
+        if (aws_byte_cursor_starts_with(&parser->doc, &to_find_open)) {
 
-    if (out_body) {
-        *out_body = aws_byte_cursor_from_array(node->doc_at_body.ptr, len);
+            struct aws_byte_cursor after_open = parser->doc;
+            aws_byte_cursor_advance(&after_open, to_find_open.len);
+
+            if (after_open.len > 0 && s_is_tag_name_boundary(*after_open.ptr)) 
{
+                /* Check for self-closing tag (e.g. <a/>) — does not increment 
depth. */
+                if (!aws_byte_cursor_starts_with(&after_open, 
&s_self_close_suffix)) {
+                    depth++;
+                }
+            }
+            /* Advance past the '<' regardless — the name boundary / 
self-close checks
+             * only determine whether depth increments; we always move 
forward. */
+            aws_byte_cursor_advance(&parser->doc, 1);
+            continue;
+        }
+
+        /* Some other '<' — skip past it. */
+        aws_byte_cursor_advance(&parser->doc, 1);
     }
 
-    return parser->error;
+    AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document is invalid.");
+    parser->error = aws_raise_error(AWS_ERROR_INVALID_XML);
+    return AWS_OP_ERR;
 }
 
 int aws_xml_node_as_body(struct aws_xml_node *node, struct aws_byte_cursor 
*out_body) {
@@ -275,7 +374,7 @@
 
     size_t doc_depth = aws_array_list_length(&parser->callback_stack);
     if (doc_depth >= parser->max_depth) {
-        AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document exceeds max 
depth.");
+        AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document exceeds max 
depth of %zu.", parser->max_depth);
         aws_raise_error(AWS_ERROR_INVALID_XML);
         goto error;
     }
@@ -285,37 +384,64 @@
     /* look for the next node at the current level. do this until we encounter 
the parent node's
      * closing tag. */
     while (!parser->error) {
-        const uint8_t *next_location = memchr(parser->doc.ptr, '<', 
parser->doc.len);
+        const uint8_t *open = memchr(parser->doc.ptr, '<', parser->doc.len);
 
-        if (!next_location) {
+        if (!open) {
             AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document is 
invalid.");
             aws_raise_error(AWS_ERROR_INVALID_XML);
             goto error;
         }
 
-        const uint8_t *end_location = memchr(parser->doc.ptr, '>', 
parser->doc.len);
+        /* Advance to the '<'. Everything leading up to the `<` is 
disregarded. */
+        aws_byte_cursor_advance(&parser->doc, open - parser->doc.ptr);
 
-        if (!end_location || next_location >= end_location) {
+        /* Skip CDATA, comments, and processing instructions — they are not 
elements. */
+        bool skipped = false;
+        if (s_try_skip_non_element(&parser->doc, &skipped)) {
             AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document is 
invalid.");
-            aws_raise_error(AWS_ERROR_INVALID_XML);
             goto error;
         }
+        if (skipped) {
+            continue;
+        }
 
-        bool parent_closed = false;
+        /* Handle other <! declarations (e.g. <!DOCTYPE) not covered by the 
helper — skip to closing >. */
+        if (aws_byte_cursor_starts_with(&parser->doc, &s_decl_prefix)) {
+            struct aws_byte_cursor found;
+            if (aws_byte_cursor_find_exact(&parser->doc, &s_close_bracket, 
&found)) {
+                AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document is 
invalid.");
+                aws_raise_error(AWS_ERROR_INVALID_XML);
+                goto error;
+            }
+            aws_byte_cursor_advance(&parser->doc, (found.ptr + 1) - 
parser->doc.ptr);
+            continue;
+        }
 
-        if (*(next_location + 1) == '/') {
-            parent_closed = true;
+        /* parser->doc.ptr is now at '<'. Find the closing '>'. */
+        if (parser->doc.len < 2) {
+            AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document is 
invalid.");
+            aws_raise_error(AWS_ERROR_INVALID_XML);
+            goto error;
         }
+        const uint8_t *end_location = memchr(parser->doc.ptr + 1, '>', 
parser->doc.len - 1);
+
+        if (!end_location) {
+            AWS_LOGF_ERROR(AWS_LS_COMMON_XML_PARSER, "XML document is 
invalid.");
+            aws_raise_error(AWS_ERROR_INVALID_XML);
+            goto error;
+        }
+
+        bool parent_closed = aws_byte_cursor_starts_with(&parser->doc, 
&s_closing_prefix);
+
+        size_t node_name_len = end_location - parser->doc.ptr;
+        struct aws_byte_cursor decl_body = 
aws_byte_cursor_from_array(parser->doc.ptr + 1, node_name_len - 1);
 
-        size_t node_name_len = end_location - next_location;
         aws_byte_cursor_advance(&parser->doc, end_location - parser->doc.ptr + 
1);
 
         if (parent_closed) {
             break;
         }
 
-        struct aws_byte_cursor decl_body = 
aws_byte_cursor_from_array(next_location + 1, node_name_len - 1);
-
         struct aws_xml_node next_node = {
             .parser = parser,
             .doc_at_body = parser->doc,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-common-0.14.1/tests/CMakeLists.txt 
new/aws-c-common-0.14.2/tests/CMakeLists.txt
--- old/aws-c-common-0.14.1/tests/CMakeLists.txt        2026-06-24 
19:58:50.000000000 +0200
+++ new/aws-c-common-0.14.2/tests/CMakeLists.txt        2026-07-09 
18:53:07.000000000 +0200
@@ -289,6 +289,7 @@
 add_test_case(test_byte_buf_append_and_update_fail)
 add_test_case(test_byte_buf_append_and_update_success)
 add_test_case(test_byte_buf_append_dynamic)
+add_test_case(test_byte_buf_append_auto)
 add_test_case(test_byte_buf_append_byte)
 add_test_case(test_byte_buf_append_lookup_success)
 add_test_case(test_byte_buf_append_lookup_failure)
@@ -483,7 +484,7 @@
 add_test_case(cpuid_test)
 
 add_test_case(xml_parser_root_with_text)
-add_test_case(xml_parser_malformed_end_node_character_before_start_test)
+add_test_case(xml_parser_empty_element_name_test)
 add_test_case(xml_parser_child_with_text)
 add_test_case(xml_parser_siblings_with_text)
 add_test_case(xml_parser_preamble_and_attributes)
@@ -495,6 +496,17 @@
 add_test_case(xml_parser_unescape_test)
 add_test_case(xml_parser_unescape_error_test)
 add_test_case(xml_parser_child_with_text_escaped)
+add_test_case(xml_parser_prefix_collision_test)
+add_test_case(xml_parser_nested_same_name_with_prefix_children_test)
+add_test_case(xml_parser_comment_skipped_test)
+add_test_case(xml_parser_cdata_skipped_test)
+add_test_case(xml_parser_pi_skipped_test)
+add_test_case(xml_parser_comment_with_gt_test)
+add_test_case(xml_parser_nested_same_name_large_depth_test)
+add_test_case(xml_parser_self_closing_same_name_test)
+add_test_case(xml_parser_cdata_false_close_test)
+add_test_case(xml_parser_comment_false_open_test)
+add_test_case(xml_parser_trailing_open_bracket_test)
 
 add_test_case(test_thread_scheduler_ordering)
 add_test_case(test_thread_scheduler_happy_path_cancellation)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-common-0.14.1/tests/byte_buf_test.c 
new/aws-c-common-0.14.2/tests/byte_buf_test.c
--- old/aws-c-common-0.14.1/tests/byte_buf_test.c       2026-06-24 
19:58:50.000000000 +0200
+++ new/aws-c-common-0.14.2/tests/byte_buf_test.c       2026-07-09 
18:53:07.000000000 +0200
@@ -632,6 +632,81 @@
 }
 AWS_TEST_CASE(test_byte_buf_append_dynamic, s_test_byte_buf_append_dynamic)
 
+static int s_test_byte_buf_append_auto(struct aws_allocator *allocator, void 
*ctx) {
+    (void)ctx;
+
+    uint8_t src_bytes[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
+    struct aws_byte_cursor src = aws_byte_cursor_from_array(src_bytes, 
sizeof(src_bytes));
+
+    /*
+     * Case 1: growable buffer (allocator != NULL) — append_auto must
+     * grow the buffer when needed, matching aws_byte_buf_append_dynamic.
+     */
+    {
+        struct aws_byte_buf growable;
+        ASSERT_SUCCESS(aws_byte_buf_init(&growable, allocator, 4));
+        ASSERT_INT_EQUALS(0, growable.len);
+        ASSERT_INT_EQUALS(4, growable.capacity);
+
+        /* Source is 8 bytes; buffer capacity is 4 — must grow. */
+        ASSERT_SUCCESS(aws_byte_buf_append_auto(&growable, &src));
+        ASSERT_INT_EQUALS(8, growable.len);
+        ASSERT_TRUE(growable.capacity >= 8);
+        ASSERT_BIN_ARRAYS_EQUALS(src_bytes, sizeof(src_bytes), 
growable.buffer, growable.len);
+
+        aws_byte_buf_clean_up(&growable);
+    }
+
+    /*
+     * Case 2: fixed-size buffer (allocator == NULL) where the source
+     * fits — append_auto must succeed via the static path.
+     */
+    {
+        uint8_t backing[16] = {0};
+        struct aws_byte_buf fixed = aws_byte_buf_from_empty_array(backing, 
sizeof(backing));
+        ASSERT_PTR_EQUALS(NULL, fixed.allocator);
+
+        ASSERT_SUCCESS(aws_byte_buf_append_auto(&fixed, &src));
+        ASSERT_INT_EQUALS(8, fixed.len);
+        ASSERT_INT_EQUALS(16, fixed.capacity);
+        ASSERT_BIN_ARRAYS_EQUALS(src_bytes, sizeof(src_bytes), fixed.buffer, 
fixed.len);
+
+        /* No clean_up — fixed buffer is stack-backed. */
+    }
+
+    /*
+     * Case 3: fixed-size buffer (allocator == NULL) where the source
+     * does NOT fit — append_auto must fail with
+     * AWS_ERROR_DEST_COPY_TOO_SMALL (loud failure, no realloc attempt).
+     */
+    {
+        uint8_t backing[4] = {0};
+        struct aws_byte_buf too_small = aws_byte_buf_from_empty_array(backing, 
sizeof(backing));
+        ASSERT_PTR_EQUALS(NULL, too_small.allocator);
+
+        ASSERT_FAILS(aws_byte_buf_append_auto(&too_small, &src));
+        ASSERT_INT_EQUALS(AWS_ERROR_DEST_COPY_TOO_SMALL, aws_last_error());
+        ASSERT_INT_EQUALS(0, too_small.len);
+        ASSERT_INT_EQUALS(4, too_small.capacity);
+    }
+
+    /*
+     * Case 4: empty source on a fixed-size buffer — should succeed
+     * without modifying state.
+     */
+    {
+        uint8_t backing[4] = {0};
+        struct aws_byte_buf fixed = aws_byte_buf_from_empty_array(backing, 
sizeof(backing));
+        struct aws_byte_cursor empty_src = {.len = 0, .ptr = NULL};
+
+        ASSERT_SUCCESS(aws_byte_buf_append_auto(&fixed, &empty_src));
+        ASSERT_INT_EQUALS(0, fixed.len);
+    }
+
+    return 0;
+}
+AWS_TEST_CASE(test_byte_buf_append_auto, s_test_byte_buf_append_auto)
+
 static uint8_t s_append_byte_array[] = {0xFF, 0xFE, 0xAB, 0x00, 0x55, 0x62};
 
 static int s_test_byte_buf_append_byte(struct aws_allocator *allocator, void 
*ctx) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-common-0.14.1/tests/xml_parser_test.c 
new/aws-c-common-0.14.2/tests/xml_parser_test.c
--- old/aws-c-common-0.14.1/tests/xml_parser_test.c     2026-06-24 
19:58:50.000000000 +0200
+++ new/aws-c-common-0.14.2/tests/xml_parser_test.c     2026-07-09 
18:53:07.000000000 +0200
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0.
  */
 
+#include <aws/common/clock.h>
 #include <aws/common/xml_parser.h>
 #include <aws/testing/aws_test_harness.h>
 
@@ -95,16 +96,16 @@
 
 AWS_TEST_CASE(xml_parser_child_with_text, s_xml_parser_child_with_text_test)
 
-const char *malformed_end_node_character_before_start =
-    "<?xml version=\"1.0\" 
encoding=\"UTF-8\"?><rootNode>><child1>TestBody</child1></rootNode>";
+const char *s_empty_element_name_doc =
+    "<?xml version=\"1.0\" 
encoding=\"UTF-8\"?><rootNode><><child1>TestBody</child1></rootNode>";
 
-static int s_xml_parser_malformed_end_node_character_before_start_test(struct 
aws_allocator *allocator, void *ctx) {
+static int s_xml_parser_empty_element_name_test(struct aws_allocator 
*allocator, void *ctx) {
     (void)ctx;
     struct child_text_capture capture;
     AWS_ZERO_STRUCT(capture);
 
     struct aws_xml_parser_options options = {
-        .doc = 
aws_byte_cursor_from_c_str(malformed_end_node_character_before_start),
+        .doc = aws_byte_cursor_from_c_str(s_empty_element_name_doc),
         .on_root_encountered = s_root_with_child,
         .user_data = &capture,
     };
@@ -113,9 +114,7 @@
     return AWS_OP_SUCCESS;
 }
 
-AWS_TEST_CASE(
-    xml_parser_malformed_end_node_character_before_start_test,
-    s_xml_parser_malformed_end_node_character_before_start_test)
+AWS_TEST_CASE(xml_parser_empty_element_name_test, 
s_xml_parser_empty_element_name_test)
 
 const char *siblings_with_text =
     "<?xml version=\"1.0\" "
@@ -617,3 +616,396 @@
 }
 
 AWS_TEST_CASE(xml_parser_child_with_text_escaped, 
s_xml_parser_child_with_text_escaped_test)
+
+/*
+ * Verify that skipping <Owner> does not falsely match <OwnerId> as a nested 
same-name open.
+ * The open-tag search must require a name-terminator after the tag name.
+ */
+const char *prefix_collision_doc = "<ListBucketResult>"
+                                   "<Contents>"
+                                   
"<Owner><OwnerId>abc123</OwnerId><DisplayName>test</DisplayName></Owner>"
+                                   "<Key>file.txt</Key>"
+                                   "</Contents>"
+                                   "</ListBucketResult>";
+
+struct prefix_collision_capture {
+    struct aws_byte_cursor owner_body;
+    struct aws_byte_cursor key_body;
+};
+
+int s_prefix_collision_contents_child(struct aws_xml_node *node, void 
*user_data) {
+    struct prefix_collision_capture *capture = user_data;
+    struct aws_byte_cursor name = aws_xml_node_get_name(node);
+    struct aws_byte_cursor owner_name = aws_byte_cursor_from_c_str("Owner");
+    struct aws_byte_cursor key_name = aws_byte_cursor_from_c_str("Key");
+
+    if (aws_byte_cursor_eq(&name, &owner_name)) {
+        return aws_xml_node_as_body(node, &capture->owner_body);
+    } else if (aws_byte_cursor_eq(&name, &key_name)) {
+        return aws_xml_node_as_body(node, &capture->key_body);
+    }
+    return AWS_OP_SUCCESS;
+}
+
+int s_prefix_collision_contents(struct aws_xml_node *node, void *user_data) {
+    return aws_xml_node_traverse(node, s_prefix_collision_contents_child, 
user_data);
+}
+
+int s_prefix_collision_root(struct aws_xml_node *node, void *user_data) {
+    return aws_xml_node_traverse(node, s_prefix_collision_contents, user_data);
+}
+
+static int s_xml_parser_prefix_collision_test(struct aws_allocator *allocator, 
void *ctx) {
+    (void)ctx;
+
+    struct prefix_collision_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(prefix_collision_doc),
+        .on_root_encountered = s_prefix_collision_root,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected_owner[] = 
"<OwnerId>abc123</OwnerId><DisplayName>test</DisplayName>";
+    const char expected_key[] = "file.txt";
+
+    ASSERT_BIN_ARRAYS_EQUALS(
+        expected_owner, sizeof(expected_owner) - 1, capture.owner_body.ptr, 
capture.owner_body.len);
+    ASSERT_BIN_ARRAYS_EQUALS(expected_key, sizeof(expected_key) - 1, 
capture.key_body.ptr, capture.key_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_prefix_collision_test, 
s_xml_parser_prefix_collision_test)
+
+/*
+ * Verify that true nested same-name elements (<a> inside <a>) and 
prefix-sharing
+ * siblings (<ab> inside <a>) both parse correctly.
+ */
+const char *nested_same_name_with_prefix_children_doc = 
"<a><a>inner</a><ab>other</ab></a>";
+
+struct nested_prefix_capture {
+    struct aws_byte_cursor a_body;
+};
+
+int s_nested_prefix_root(struct aws_xml_node *node, void *user_data) {
+    struct nested_prefix_capture *capture = user_data;
+    return aws_xml_node_as_body(node, &capture->a_body);
+}
+
+static int s_xml_parser_nested_same_name_with_prefix_children_test(struct 
aws_allocator *allocator, void *ctx) {
+    (void)ctx;
+
+    struct nested_prefix_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = 
aws_byte_cursor_from_c_str(nested_same_name_with_prefix_children_doc),
+        .on_root_encountered = s_nested_prefix_root,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected[] = "<a>inner</a><ab>other</ab>";
+    ASSERT_BIN_ARRAYS_EQUALS(expected, sizeof(expected) - 1, 
capture.a_body.ptr, capture.a_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(
+    xml_parser_nested_same_name_with_prefix_children_test,
+    s_xml_parser_nested_same_name_with_prefix_children_test)
+
+/*
+ * Verify that XML comments (<!-- ... -->) are skipped during child traversal.
+ */
+const char *comment_in_body_doc = "<root><!-- this is a comment 
--><child>value</child></root>";
+
+struct comment_capture {
+    struct aws_byte_cursor child_body;
+    struct aws_byte_cursor child_name;
+};
+
+int s_comment_child(struct aws_xml_node *node, void *user_data) {
+    struct comment_capture *capture = user_data;
+    capture->child_name = aws_xml_node_get_name(node);
+    return aws_xml_node_as_body(node, &capture->child_body);
+}
+
+int s_comment_root(struct aws_xml_node *node, void *user_data) {
+    return aws_xml_node_traverse(node, s_comment_child, user_data);
+}
+
+static int s_xml_parser_comment_skipped_test(struct aws_allocator *allocator, 
void *ctx) {
+    (void)ctx;
+
+    struct comment_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(comment_in_body_doc),
+        .on_root_encountered = s_comment_root,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected_name[] = "child";
+    const char expected_value[] = "value";
+    ASSERT_BIN_ARRAYS_EQUALS(expected_name, sizeof(expected_name) - 1, 
capture.child_name.ptr, capture.child_name.len);
+    ASSERT_BIN_ARRAYS_EQUALS(
+        expected_value, sizeof(expected_value) - 1, capture.child_body.ptr, 
capture.child_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_comment_skipped_test, 
s_xml_parser_comment_skipped_test)
+
+/*
+ * Verify that CDATA sections (<![CDATA[...]]>) are skipped during child 
traversal.
+ */
+const char *cdata_in_body_doc = 
"<root><![CDATA[<not>an</element>]]><child>value</child></root>";
+
+static int s_xml_parser_cdata_skipped_test(struct aws_allocator *allocator, 
void *ctx) {
+    (void)ctx;
+
+    struct comment_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(cdata_in_body_doc),
+        .on_root_encountered = s_comment_root,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected_name[] = "child";
+    const char expected_value[] = "value";
+    ASSERT_BIN_ARRAYS_EQUALS(expected_name, sizeof(expected_name) - 1, 
capture.child_name.ptr, capture.child_name.len);
+    ASSERT_BIN_ARRAYS_EQUALS(
+        expected_value, sizeof(expected_value) - 1, capture.child_body.ptr, 
capture.child_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_cdata_skipped_test, s_xml_parser_cdata_skipped_test)
+
+/*
+ * Verify that processing instructions (<?...?>) are skipped during child 
traversal.
+ */
+const char *pi_in_body_doc = "<root><?xml-stylesheet type=\"text/xsl\" 
href=\"style.xsl\"?><child>value</child></root>";
+
+static int s_xml_parser_pi_skipped_test(struct aws_allocator *allocator, void 
*ctx) {
+    (void)ctx;
+
+    struct comment_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(pi_in_body_doc),
+        .on_root_encountered = s_comment_root,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected_name[] = "child";
+    const char expected_value[] = "value";
+    ASSERT_BIN_ARRAYS_EQUALS(expected_name, sizeof(expected_name) - 1, 
capture.child_name.ptr, capture.child_name.len);
+    ASSERT_BIN_ARRAYS_EQUALS(
+        expected_value, sizeof(expected_value) - 1, capture.child_body.ptr, 
capture.child_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_pi_skipped_test, s_xml_parser_pi_skipped_test)
+
+/*
+ * Verify that '>' inside a comment does not terminate the comment early
+ * or cause subsequent content to be parsed as a sibling element.
+ */
+const char *comment_with_gt_doc = "<root><!-- contains > character 
--><child>safe</child></root>";
+
+static int s_xml_parser_comment_with_gt_test(struct aws_allocator *allocator, 
void *ctx) {
+    (void)ctx;
+
+    struct comment_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(comment_with_gt_doc),
+        .on_root_encountered = s_comment_root,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected_name[] = "child";
+    const char expected_value[] = "safe";
+    ASSERT_BIN_ARRAYS_EQUALS(expected_name, sizeof(expected_name) - 1, 
capture.child_name.ptr, capture.child_name.len);
+    ASSERT_BIN_ARRAYS_EQUALS(
+        expected_value, sizeof(expected_value) - 1, capture.child_body.ptr, 
capture.child_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_comment_with_gt_test, 
s_xml_parser_comment_with_gt_test)
+
+/*
+ * Verify that parsing deeply nested same-name elements (N=20000) completes in 
O(N) time.
+ * The test asserts the parse finishes within 2 seconds.
+ */
+static int s_xml_parser_nested_same_name_large_depth_test(struct aws_allocator 
*allocator, void *ctx) {
+    (void)ctx;
+
+    /* Build: <a><a><a>...(20000 opens)...</a></a></a>...(20000 closes) */
+    const size_t depth = 20000;
+    struct aws_byte_buf doc_buf;
+    aws_byte_buf_init(&doc_buf, allocator, depth * 10);
+
+    struct aws_byte_cursor a_open = aws_byte_cursor_from_c_str("<a>");
+    struct aws_byte_cursor a_close = aws_byte_cursor_from_c_str("</a>");
+
+    for (size_t i = 0; i < depth; i++) {
+        aws_byte_buf_append_dynamic(&doc_buf, &a_open);
+    }
+    for (size_t i = 0; i < depth; i++) {
+        aws_byte_buf_append_dynamic(&doc_buf, &a_close);
+    }
+
+    struct nested_node_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_buf(&doc_buf),
+        .on_root_encountered = s_nested_node,
+        .user_data = &capture,
+    };
+
+    uint64_t start_ns = 0;
+    aws_high_res_clock_get_ticks(&start_ns);
+
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    uint64_t end_ns = 0;
+    aws_high_res_clock_get_ticks(&end_ns);
+
+    uint64_t elapsed_ms = (end_ns - start_ns) / 1000000;
+    ASSERT_TRUE(
+        elapsed_ms < 2000,
+        "xml parse took %llu ms — expected < 2000 ms with depth=%zu",
+        (unsigned long long)elapsed_ms,
+        depth);
+
+    ASSERT_TRUE(capture.node_body.len > 0);
+
+    aws_byte_buf_clean_up(&doc_buf);
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_nested_same_name_large_depth_test, 
s_xml_parser_nested_same_name_large_depth_test)
+
+/*
+ * Verify that self-closing tags (<a/>) inside <a> do not increment depth 
count.
+ */
+const char *self_closing_same_name_doc = "<a><a/>inner</a>";
+
+static int s_xml_parser_self_closing_same_name_test(struct aws_allocator 
*allocator, void *ctx) {
+    (void)ctx;
+
+    struct nested_node_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(self_closing_same_name_doc),
+        .on_root_encountered = s_nested_node,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected[] = "<a/>inner";
+    ASSERT_BIN_ARRAYS_EQUALS(expected, sizeof(expected) - 1, 
capture.node_body.ptr, capture.node_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_self_closing_same_name_test, 
s_xml_parser_self_closing_same_name_test)
+
+/*
+ * Verify that a close tag inside CDATA is not treated as the real close tag.
+ */
+const char *cdata_false_close_doc = "<data><![CDATA[</data>]]>real</data>";
+
+int s_cdata_false_close_root(struct aws_xml_node *node, void *user_data) {
+    struct nested_node_capture *capture = user_data;
+    return aws_xml_node_as_body(node, &capture->node_body);
+}
+
+static int s_xml_parser_cdata_false_close_test(struct aws_allocator 
*allocator, void *ctx) {
+    (void)ctx;
+
+    struct nested_node_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(cdata_false_close_doc),
+        .on_root_encountered = s_cdata_false_close_root,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected[] = "<![CDATA[</data>]]>real";
+    ASSERT_BIN_ARRAYS_EQUALS(expected, sizeof(expected) - 1, 
capture.node_body.ptr, capture.node_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_cdata_false_close_test, 
s_xml_parser_cdata_false_close_test)
+
+/*
+ * Verify that an open tag inside a comment does not cause depth increment.
+ */
+const char *comment_false_open_doc = "<tag><!-- <tag> -->body</tag>";
+
+static int s_xml_parser_comment_false_open_test(struct aws_allocator 
*allocator, void *ctx) {
+    (void)ctx;
+
+    struct nested_node_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(comment_false_open_doc),
+        .on_root_encountered = s_nested_node,
+        .user_data = &capture,
+    };
+    ASSERT_SUCCESS(aws_xml_parse(allocator, &options));
+
+    const char expected[] = "<!-- <tag> -->body";
+    ASSERT_BIN_ARRAYS_EQUALS(expected, sizeof(expected) - 1, 
capture.node_body.ptr, capture.node_body.len);
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_comment_false_open_test, 
s_xml_parser_comment_false_open_test)
+
+/*
+ * Verify that a document ending with a bare '<' does not crash (out-of-bounds 
read).
+ */
+static int s_xml_parser_trailing_open_bracket_test(struct aws_allocator 
*allocator, void *ctx) {
+    (void)ctx;
+
+    const char *doc = "<a><";
+
+    struct nested_node_capture capture;
+    AWS_ZERO_STRUCT(capture);
+
+    struct aws_xml_parser_options options = {
+        .doc = aws_byte_cursor_from_c_str(doc),
+        .on_root_encountered = s_nested_node,
+        .user_data = &capture,
+    };
+    ASSERT_ERROR(AWS_ERROR_INVALID_XML, aws_xml_parse(allocator, &options));
+
+    return AWS_OP_SUCCESS;
+}
+
+AWS_TEST_CASE(xml_parser_trailing_open_bracket_test, 
s_xml_parser_trailing_open_bracket_test)

Reply via email to