mirror of
https://github.com/libexpat/libexpat.git
synced 2025-04-04 21:04:57 +00:00
Merge pull request #989 from berkayurun/fix-m_eventPtr
Stop updating event pointer on exit for reentry (fixes #980)
This commit is contained in:
commit
c8d69c6e0b
5 changed files with 112 additions and 3 deletions
|
@ -38,6 +38,16 @@
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
Release 2.7.1 ??? ????? ?? ????
|
Release 2.7.1 ??? ????? ?? ????
|
||||||
|
Bug fixes:
|
||||||
|
#980 #989 Restore event pointer behavior from Expat 2.6.4
|
||||||
|
(that the fix to CVE-2024-8176 changed in 2.7.0);
|
||||||
|
affected API functions are:
|
||||||
|
- XML_GetCurrentByteCount
|
||||||
|
- XML_GetCurrentByteIndex
|
||||||
|
- XML_GetCurrentColumnNumber
|
||||||
|
- XML_GetCurrentLineNumber
|
||||||
|
- XML_GetInputContext
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
#976 #977 Autotools: Integrate files "fuzz/xml_lpm_fuzzer.{cpp,proto}"
|
#976 #977 Autotools: Integrate files "fuzz/xml_lpm_fuzzer.{cpp,proto}"
|
||||||
with Automake that were missing from 2.7.0 release tarballs
|
with Automake that were missing from 2.7.0 release tarballs
|
||||||
|
@ -54,6 +64,11 @@ Release 2.7.1 ??? ????? ?? ????
|
||||||
#976 #977 CI: Protect against fuzzer files missing from future
|
#976 #977 CI: Protect against fuzzer files missing from future
|
||||||
release archives
|
release archives
|
||||||
|
|
||||||
|
Special thanks to:
|
||||||
|
Berkay Eren Ürün
|
||||||
|
and
|
||||||
|
Perl XML::Parser
|
||||||
|
|
||||||
Release 2.7.0 Thu March 13 2025
|
Release 2.7.0 Thu March 13 2025
|
||||||
Security fixes:
|
Security fixes:
|
||||||
#893 #973 CVE-2024-8176 -- Fix crash from chaining a large number
|
#893 #973 CVE-2024-8176 -- Fix crash from chaining a large number
|
||||||
|
|
|
@ -3402,12 +3402,13 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||||
break;
|
break;
|
||||||
/* LCOV_EXCL_STOP */
|
/* LCOV_EXCL_STOP */
|
||||||
}
|
}
|
||||||
*eventPP = s = next;
|
|
||||||
switch (parser->m_parsingStatus.parsing) {
|
switch (parser->m_parsingStatus.parsing) {
|
||||||
case XML_SUSPENDED:
|
case XML_SUSPENDED:
|
||||||
|
*eventPP = next;
|
||||||
*nextPtr = next;
|
*nextPtr = next;
|
||||||
return XML_ERROR_NONE;
|
return XML_ERROR_NONE;
|
||||||
case XML_FINISHED:
|
case XML_FINISHED:
|
||||||
|
*eventPP = next;
|
||||||
return XML_ERROR_ABORTED;
|
return XML_ERROR_ABORTED;
|
||||||
case XML_PARSING:
|
case XML_PARSING:
|
||||||
if (parser->m_reenter) {
|
if (parser->m_reenter) {
|
||||||
|
@ -3416,6 +3417,7 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||||
}
|
}
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
default:;
|
default:;
|
||||||
|
*eventPP = s = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* not reached */
|
/* not reached */
|
||||||
|
@ -4332,12 +4334,13 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
|
||||||
/* LCOV_EXCL_STOP */
|
/* LCOV_EXCL_STOP */
|
||||||
}
|
}
|
||||||
|
|
||||||
*eventPP = s = next;
|
|
||||||
switch (parser->m_parsingStatus.parsing) {
|
switch (parser->m_parsingStatus.parsing) {
|
||||||
case XML_SUSPENDED:
|
case XML_SUSPENDED:
|
||||||
|
*eventPP = next;
|
||||||
*nextPtr = next;
|
*nextPtr = next;
|
||||||
return XML_ERROR_NONE;
|
return XML_ERROR_NONE;
|
||||||
case XML_FINISHED:
|
case XML_FINISHED:
|
||||||
|
*eventPP = next;
|
||||||
return XML_ERROR_ABORTED;
|
return XML_ERROR_ABORTED;
|
||||||
case XML_PARSING:
|
case XML_PARSING:
|
||||||
if (parser->m_reenter) {
|
if (parser->m_reenter) {
|
||||||
|
@ -4345,6 +4348,7 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
|
||||||
}
|
}
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
default:;
|
default:;
|
||||||
|
*eventPP = s = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* not reached */
|
/* not reached */
|
||||||
|
@ -5951,12 +5955,13 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
|
||||||
default:
|
default:
|
||||||
return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
|
return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
|
||||||
}
|
}
|
||||||
parser->m_eventPtr = s = next;
|
|
||||||
switch (parser->m_parsingStatus.parsing) {
|
switch (parser->m_parsingStatus.parsing) {
|
||||||
case XML_SUSPENDED:
|
case XML_SUSPENDED:
|
||||||
|
parser->m_eventPtr = next;
|
||||||
*nextPtr = next;
|
*nextPtr = next;
|
||||||
return XML_ERROR_NONE;
|
return XML_ERROR_NONE;
|
||||||
case XML_FINISHED:
|
case XML_FINISHED:
|
||||||
|
parser->m_eventPtr = next;
|
||||||
return XML_ERROR_ABORTED;
|
return XML_ERROR_ABORTED;
|
||||||
case XML_PARSING:
|
case XML_PARSING:
|
||||||
if (parser->m_reenter) {
|
if (parser->m_reenter) {
|
||||||
|
@ -5964,6 +5969,7 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
|
||||||
}
|
}
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
default:;
|
default:;
|
||||||
|
parser->m_eventPtr = s = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h> // for SIZE_MAX
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -300,3 +302,26 @@ duff_reallocator(void *ptr, size_t size) {
|
||||||
g_reallocation_count--;
|
g_reallocation_count--;
|
||||||
return realloc(ptr, size);
|
return realloc(ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Portable remake of strndup(3) for C99; does not care about space efficiency
|
||||||
|
char *
|
||||||
|
portable_strndup(const char *s, size_t n) {
|
||||||
|
if ((s == NULL) || (n == SIZE_MAX)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *const buffer = (char *)malloc(n + 1);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
memcpy(buffer, s, n);
|
||||||
|
|
||||||
|
buffer[n] = '\0';
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
|
@ -146,6 +146,8 @@ extern void *duff_allocator(size_t size);
|
||||||
|
|
||||||
extern void *duff_reallocator(void *ptr, size_t size);
|
extern void *duff_reallocator(void *ptr, size_t size);
|
||||||
|
|
||||||
|
extern char *portable_strndup(const char *s, size_t n);
|
||||||
|
|
||||||
#endif /* XML_COMMON_H */
|
#endif /* XML_COMMON_H */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -618,6 +618,66 @@ START_TEST(test_renter_loop_finite_content) {
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
// Inspired by function XML_OriginalString of Perl's XML::Parser
|
||||||
|
static char *
|
||||||
|
dup_original_string(XML_Parser parser) {
|
||||||
|
const int byte_count = XML_GetCurrentByteCount(parser);
|
||||||
|
|
||||||
|
assert_true(byte_count >= 0);
|
||||||
|
|
||||||
|
int offset = -1;
|
||||||
|
int size = -1;
|
||||||
|
|
||||||
|
const char *const context = XML_GetInputContext(parser, &offset, &size);
|
||||||
|
|
||||||
|
#if XML_CONTEXT_BYTES > 0
|
||||||
|
assert_true(context != NULL);
|
||||||
|
assert_true(offset >= 0);
|
||||||
|
assert_true(size >= 0);
|
||||||
|
return portable_strndup(context + offset, byte_count);
|
||||||
|
#else
|
||||||
|
assert_true(context == NULL);
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_characters_issue_980(void *userData, const XML_Char *s, int len) {
|
||||||
|
(void)s;
|
||||||
|
(void)len;
|
||||||
|
XML_Parser parser = (XML_Parser)userData;
|
||||||
|
|
||||||
|
char *const original_string = dup_original_string(parser);
|
||||||
|
|
||||||
|
#if XML_CONTEXT_BYTES > 0
|
||||||
|
assert_true(original_string != NULL);
|
||||||
|
assert_true(strcmp(original_string, "&draft.day;") == 0);
|
||||||
|
free(original_string);
|
||||||
|
#else
|
||||||
|
assert_true(original_string == NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(test_misc_expected_event_ptr_issue_980) {
|
||||||
|
// NOTE: This is a tiny subset of sample "REC-xml-19980210.xml"
|
||||||
|
// from Perl's XML::Parser
|
||||||
|
const char *const doc = "<!DOCTYPE day [\n"
|
||||||
|
" <!ENTITY draft.day '10'>\n"
|
||||||
|
"]>\n"
|
||||||
|
"<day>&draft.day;</day>\n";
|
||||||
|
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
XML_SetUserData(parser, parser);
|
||||||
|
XML_SetCharacterDataHandler(parser, on_characters_issue_980);
|
||||||
|
|
||||||
|
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
|
||||||
|
/*isFinal=*/XML_TRUE)
|
||||||
|
== XML_STATUS_OK);
|
||||||
|
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
void
|
void
|
||||||
make_miscellaneous_test_case(Suite *s) {
|
make_miscellaneous_test_case(Suite *s) {
|
||||||
TCase *tc_misc = tcase_create("miscellaneous tests");
|
TCase *tc_misc = tcase_create("miscellaneous tests");
|
||||||
|
@ -645,4 +705,5 @@ make_miscellaneous_test_case(Suite *s) {
|
||||||
tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
|
tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
|
||||||
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
|
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
|
||||||
tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
|
tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
|
||||||
|
tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue