Re: [PR] fix: add bounds check before memcpy in apr_buffer.c [apr-util]
Daniel Sahlberg <[email protected]> Tue, 23 Jun 2026 10:34:16 +0200
| Newsgroups | gmane.comp.apache.apr.devel |
|---|---|
| Message-ID | <CAMHy98N29a7B-4YtKoUxKBUAXh4STNzdZX+A1cxJoUVTgJdd+w@mail.gmail.com> |
--000000000000a8d5590654e7a016 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Very similar to https://github.com/apache/apr/pull/73 I'm inclined to just close this as "by design". However it seems I'm not able to close a PR in GitHub, I only have "comment". Is this just me? Maybe that is because I've changed by GitHub username. Cheers, Daniel Den tis 23 juni 2026 kl 04:10 skrev orbisai0security (via GitHub) < [email protected]>: > > orbisai0security opened a new pull request, #16: > URL: https://github.com/apache/apr-util/pull/16 > > ## Summary > Fix critical severity security issue in `buffer/apr_buffer.c`. > > ## Vulnerability > | Field | Value | > |-------|-------| > | **ID** | V-001 | > | **Severity** | CRITICAL | > | **Scanner** | multi_agent_ai | > | **Rule** | `V-001` | > | **File** | `buffer/apr_buffer.c:240` | > | **Assessment** | Confirmed exploitable | > > **Description**: Multiple memcpy operations in apr_buffer.c copy data > without validating that the destination buffer has sufficient capacity. T= he > code assumes the allocated buffer is large enough but doesn't verify the > size parameter against destination buffer bounds. > > ## Evidence > > **Exploitation scenario**: An attacker who can control the 'size' > parameter or the source data passed to apr_buffer_arraydup() or other > buffer functions can cause buffer overflow. > > **Scanner confirmation**: multi_agent_ai rule `V-001` flagged this > pattern. > > **Production code**: This file is in the production codebase, not > test-only code. > > ## Threat Model Context > > This is a local CLI tool - exploitation requires the attacker to > control command-line arguments or input files. > > ## Changes > - Security fix applied > > > **Note**: The following lines in the same file use a similar pattern > and may also need review: `buffer/apr_buffer.c:255`, > `buffer/apr_buffer.c:299`, `buffer/apr_buffer.c:385`, > `buffer/apr_buffer.c:390`, `buffer/apr_buffer.c:395` > > ## Verification > - [x] Build passes > - [x] Scanner re-scan confirms fix > - [x] LLM code review passed > > ## Security Invariant > > **Property**: The security boundary is maintained under adversarial > input > > <details> > <summary>Regression test</summary> > > ```c > #include <check.h> > #include <stdlib.h> > #include <string.h> > #include "buffer/apr_buffer.h" > > START_TEST(test_apr_buffer_arraydup_bounds_check) > { > // Invariant: apr_buffer_arraydup must not write beyond allocated > destination buffer bounds > // regardless of input size values > > // Payloads: exploit case (size causing overflow), boundary case > (zero size), valid input > struct { > apr_size_t size; > int zero_terminated; > int nelts; > const char *description; > } test_cases[] =3D { > {SIZE_MAX, 1, 2, "exploit: size + zero_terminated causes > overflow"}, > {0, 0, 1, "boundary: zero size"}, > {1024, 0, 3, "valid: normal operation"} > }; > > int num_cases =3D sizeof(test_cases) / sizeof(test_cases[0]); > > for (int i =3D 0; i < num_cases; i++) { > // Create source buffer array > apr_buffer_t *src_array =3D malloc(test_cases[i].nelts * > sizeof(apr_buffer_t)); > ck_assert_ptr_nonnull(src_array); > > // Initialize source buffers with test data > for (int j =3D 0; j < test_cases[i].nelts; j++) { > src_array[j].size =3D test_cases[i].size; > src_array[j].zero_terminated =3D > test_cases[i].zero_terminated; > > // Allocate source memory if size > 0 > if (test_cases[i].size > 0) { > src_array[j].d.mem =3D malloc(test_cases[i].size); > ck_assert_ptr_nonnull(src_array[j].d.mem); > memset(src_array[j].d.mem, 'A', test_cases[i].size); > } else { > src_array[j].d.mem =3D NULL; > } > } > > // Test the actual function > apr_buffer_t *dst_array =3D NULL; > apr_status_t result =3D apr_buffer_arraydup(&dst_array, > src_array, > > (apr_buffer_alloc)malloc, NULL, > test_cases[i].nelts)= ; > > // Property: Function must either succeed with valid buffers o= r > fail gracefully > // without writing beyond allocated memory bounds > if (result =3D=3D APR_SUCCESS) { > ck_assert_ptr_nonnull(dst_array); > > // Verify each destination buffer was properly allocated > for (int j =3D 0; j < test_cases[i].nelts; j++) { > if (test_cases[i].size + test_cases[i].zero_terminated > > 0) { > ck_assert_ptr_nonnull(dst_array[j].d.mem); > } > ck_assert_uint_eq(dst_array[j].size, > test_cases[i].size); > ck_assert_int_eq(dst_array[j].zero_terminated, > test_cases[i].zero_terminated); > } > > // Clean up destination > for (int j =3D 0; j < test_cases[i].nelts; j++) { > if (dst_array[j].d.mem) { > free(dst_array[j].d.mem); > } > } > free(dst_array); > } else { > // If function failed, ensure no partial writes corrupted > memory > ck_assert_ptr_null(dst_array); > } > > // Clean up source > for (int j =3D 0; j < test_cases[i].nelts; j++) { > if (src_array[j].d.mem) { > free(src_array[j].d.mem); > } > } > free(src_array); > } > } > END_TEST > > Suite *security_suite(void) > { > Suite *s; > TCase *tc_core; > > s =3D suite_create("Security"); > tc_core =3D tcase_create("Core"); > > tcase_add_test(tc_core, test_apr_buffer_arraydup_bounds_check); > suite_add_tcase(s, tc_core); > > return s; > } > > int main(void) > { > int number_failed; > Suite *s; > SRunner *sr; > > s =3D security_suite(); > sr =3D srunner_create(s); > > srunner_run_all(sr, CK_NORMAL); > number_failed =3D srunner_ntests_failed(sr); > srunner_free(sr); > > return (number_failed =3D=3D 0) ? EXIT_SUCCESS : EXIT_FAILURE; > } > ``` > > </details> > > This test guards against regressions =E2=80=94 it's useful independent= of the > code change above. > > --- > *Automated security fix by [OrbisAI Security](https://orbisappsec.com)= * > > > > -- > This is an automated message from the Apache Git Service. > To respond to the message, please log on to GitHub and use the > URL above to go to the specific comment. > > To unsubscribe, e-mail: [email protected] > > For queries about this service, please contact Infrastructure at: > [email protected] > > --000000000000a8d5590654e7a016 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div>Very similar to <a href=3D"https://github.com/apache/= apr/pull/73">https://github.com/apache/apr/pull/73</a></div><div><br></div>= <div><span style=3D"background-color:transparent">I'm inclined to just = close this as "by design". However it seems I'm not able to c= lose a PR in GitHub, I only have "comment". Is this just me? Mayb= e that is because I've changed by GitHub username.</span></div><div><br= ></div><div>Cheers,</div><div>Daniel</div><div><br></div></div><br><div cla= ss=3D"gmail_quote gmail_quote_container"><div dir=3D"ltr" class=3D"gmail_at= tr">Den tis 23 juni 2026 kl 04:10 skrev orbisai0security (via GitHub) <<= a href=3D"mailto:[email protected]">[email protected]</a>>:<br></div><blockquo= te class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px = solid rgb(204,204,204);padding-left:1ex"><br> orbisai0security opened a new pull request, #16:<br> URL: <a href=3D"https://github.com/apache/apr-util/pull/16" rel=3D"noreferr= er" target=3D"_blank">https://github.com/apache/apr-util/pull/16</a><br> <br> =C2=A0 =C2=A0## Summary<br> =C2=A0 =C2=A0Fix critical severity security issue in `buffer/apr_buffer.c`.= <br> <br> =C2=A0 =C2=A0## Vulnerability<br> =C2=A0 =C2=A0| Field | Value |<br> =C2=A0 =C2=A0|-------|-------|<br> =C2=A0 =C2=A0| **ID** | V-001 |<br> =C2=A0 =C2=A0| **Severity** | CRITICAL |<br> =C2=A0 =C2=A0| **Scanner** | multi_agent_ai |<br> =C2=A0 =C2=A0| **Rule** | `V-001` |<br> =C2=A0 =C2=A0| **File** | `buffer/apr_buffer.c:240` |<br> =C2=A0 =C2=A0| **Assessment** | Confirmed exploitable |<br> <br> =C2=A0 =C2=A0**Description**: Multiple memcpy operations in apr_buffer.c co= py data without validating that the destination buffer has sufficient capac= ity. The code assumes the allocated buffer is large enough but doesn't = verify the size parameter against destination buffer bounds.<br> <br> =C2=A0 =C2=A0## Evidence<br> <br> =C2=A0 =C2=A0**Exploitation scenario**: An attacker who can control the = 9;size' parameter or the source data passed to apr_buffer_arraydup() or= other buffer functions can cause buffer overflow.<br> <br> =C2=A0 =C2=A0**Scanner confirmation**: multi_agent_ai rule `V-001` flagged = this pattern.<br> <br> =C2=A0 =C2=A0**Production code**: This file is in the production codebase, = not test-only code.<br> <br> =C2=A0 =C2=A0## Threat Model Context<br> <br> =C2=A0 =C2=A0This is a local CLI tool - exploitation requires the attacker = to control command-line arguments or input files.<br> <br> =C2=A0 =C2=A0## Changes<br> =C2=A0 =C2=A0- Security fix applied<br> <br> =C2=A0 =C2=A0> **Note**: The following lines in the same file use a simi= lar pattern and may also need review: `buffer/apr_buffer.c:255`, `buffer/ap= r_buffer.c:299`, `buffer/apr_buffer.c:385`, `buffer/apr_buffer.c:390`, `buf= fer/apr_buffer.c:395`<br> <br> =C2=A0 =C2=A0## Verification<br> =C2=A0 =C2=A0- [x] Build passes<br> =C2=A0 =C2=A0- [x] Scanner re-scan confirms fix<br> =C2=A0 =C2=A0- [x] LLM code review passed<br> <br> =C2=A0 =C2=A0## Security Invariant<br> =C2=A0 =C2=A0> **Property**: The security boundary is maintained under a= dversarial input<br> <br> =C2=A0 =C2=A0<details><br> =C2=A0 =C2=A0<summary>Regression test</summary><br> <br> =C2=A0 =C2=A0```c<br> =C2=A0 =C2=A0#include <check.h><br> =C2=A0 =C2=A0#include <stdlib.h><br> =C2=A0 =C2=A0#include <string.h><br> =C2=A0 =C2=A0#include "buffer/apr_buffer.h"<br> <br> =C2=A0 =C2=A0START_TEST(test_apr_buffer_arraydup_bounds_check)<br> =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0// Invariant: apr_buffer_arraydup must not write= beyond allocated destination buffer bounds<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0// regardless of input size values<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0// Payloads: exploit case (size causing overflow= ), boundary case (zero size), valid input<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0apr_size_t size;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int zero_terminated;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int nelts;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0const char *description;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0} test_cases[] =3D {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{SIZE_MAX, 1, 2, "exploit: si= ze + zero_terminated causes overflow"},<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{0, 0, 1, "boundary: zero siz= e"},<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{1024, 0, 3, "valid: normal o= peration"}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0};<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0int num_cases =3D sizeof(test_cases) / sizeof(te= st_cases[0]);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0for (int i =3D 0; i < num_cases; i++) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Create source buffer array<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0apr_buffer_t *src_array =3D malloc= (test_cases[i].nelts * sizeof(apr_buffer_t));<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ck_assert_ptr_nonnull(src_array);<= br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Initialize source buffers with = test data<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (int j =3D 0; j < test_case= s[i].nelts; j++) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0src_array[j].size = =3D test_cases[i].size;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0src_array[j].zero_te= rminated =3D test_cases[i].zero_terminated;<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Allocate source m= emory if size > 0<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (test_cases[i].si= ze > 0) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0src_ar= ray[j].d.mem =3D malloc(test_cases[i].size);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ck_ass= ert_ptr_nonnull(src_array[j].d.mem);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0memset= (src_array[j].d.mem, 'A', test_cases[i].size);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0src_ar= ray[j].d.mem =3D NULL;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Test the actual function<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0apr_buffer_t *dst_array =3D NULL;<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0apr_status_t result =3D apr_buffer= _arraydup(&dst_array, src_array, <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(apr_buffer_alloc)malloc, NULL, <b= r> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0test_cases[i].nelts);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Property: Function must either = succeed with valid buffers or fail gracefully<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// without writing beyond allocate= d memory bounds<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (result =3D=3D APR_SUCCESS) {<b= r> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ck_assert_ptr_nonnul= l(dst_array);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Verify each desti= nation buffer was properly allocated<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (int j =3D 0; j = < test_cases[i].nelts; j++) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (te= st_cases[i].size + test_cases[i].zero_terminated > 0) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0ck_assert_ptr_nonnull(dst_array[j].d.mem);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ck_ass= ert_uint_eq(dst_array[j].size, test_cases[i].size);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ck_ass= ert_int_eq(dst_array[j].zero_terminated, test_cases[i].zero_terminated);<br= > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Clean up destinat= ion<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (int j =3D 0; j = < test_cases[i].nelts; j++) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (ds= t_array[j].d.mem) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0free(dst_array[j].d.mem);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0free(dst_array);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// If function faile= d, ensure no partial writes corrupted memory<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ck_assert_ptr_null(d= st_array);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Clean up source<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (int j =3D 0; j < test_case= s[i].nelts; j++) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (src_array[j].d.m= em) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0free(s= rc_array[j].d.mem);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0free(src_array);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0END_TEST<br> <br> =C2=A0 =C2=A0Suite *security_suite(void)<br> =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0Suite *s;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0TCase *tc_core;<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0s =3D suite_create("Security");<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0tc_core =3D tcase_create("Core");<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0tcase_add_test(tc_core, test_apr_buffer_arraydup= _bounds_check);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0suite_add_tcase(s, tc_core);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0return s;<br> =C2=A0 =C2=A0}<br> <br> =C2=A0 =C2=A0int main(void)<br> =C2=A0 =C2=A0{<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0int number_failed;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0Suite *s;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0SRunner *sr;<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0s =3D security_suite();<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0sr =3D srunner_create(s);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0srunner_run_all(sr, CK_NORMAL);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0number_failed =3D srunner_ntests_failed(sr);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0srunner_free(sr);<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0return (number_failed =3D=3D 0) ? EXIT_SUCCESS := EXIT_FAILURE;<br> =C2=A0 =C2=A0}<br> =C2=A0 =C2=A0```<br> <br> =C2=A0 =C2=A0</details><br> <br> =C2=A0 =C2=A0This test guards against regressions =E2=80=94 it's useful= independent of the code change above.<br> <br> =C2=A0 =C2=A0---<br> =C2=A0 =C2=A0*Automated security fix by [OrbisAI Security](<a href=3D"https= ://orbisappsec.com" rel=3D"noreferrer" target=3D"_blank">https://orbisappse= c.com</a>)*<br> <br> <br> <br> -- <br> This is an automated message from the Apache Git Service.<br> To respond to the message, please log on to GitHub and use the<br> URL above to go to the specific comment.<br> <br> To unsubscribe, e-mail: <a href=3D"mailto:[email protected]" t= arget=3D"_blank">[email protected]</a><br> <br> For queries about this service, please contact Infrastructure at:<br> <a href=3D"mailto:[email protected]" target=3D"_blank">[email protected]= che.org</a><br> <br> </blockquote></div> --000000000000a8d5590654e7a016--