Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CVE-2021-45960] lib: Detect and prevent troublesome left shifts in function storeAtts (fixes #531) #534

Merged
merged 2 commits into from Jan 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 19 additions & 0 deletions expat/Changes
Expand Up @@ -3,13 +3,32 @@ NOTE: We are looking for help with a few things:
If you can help, please get in touch. Thanks!

Release x.x.x xxx xxxxxxxx xx xxxx
Security fixes:
#531 #534 CVE-2021-45960 -- Fix issues with left shifts by >=29 places
resulting in
a) realloc acting as free
b) realloc allocating too few bytes
c) undefined behavior
depending on architecture and precise value
for XML documents with >=2^27+1 prefixed attributes
on a single XML tag a la
"<r xmlns:a='[..]' a:a123='[..]' [..] />"
where XML_ParserCreateNS is used to create the parser
(which needs argument "-n" when running xmlwf).
Impact is denial of service, or more.

Other changes:
#535 CMake: Make call to file(GENERATE [..]) work for CMake <3.19
#527 #528 Address compiler warnings

Infrastructure:
#536 CI: Check for realistic minimum CMake version

Special thanks to:
Tyson Smith
and
GCC Farm Project

Release 2.4.2 Sun December 19 2021
Other changes:
#509 #510 Link againgst libm for function "isnan"
Expand Down
31 changes: 29 additions & 2 deletions expat/lib/xmlparse.c
Expand Up @@ -3414,7 +3414,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
if (nPrefixes) {
int j; /* hash table index */
unsigned long version = parser->m_nsAttsVersion;
int nsAttsSize = (int)1 << parser->m_nsAttsPower;

/* Detect and prevent invalid shift */
if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
return XML_ERROR_NO_MEMORY;
}

unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
unsigned char oldNsAttsPower = parser->m_nsAttsPower;
/* size of hash table must be at least 2 * (# of prefixed attributes) */
if ((nPrefixes << 1)
Expand All @@ -3425,7 +3431,28 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
;
if (parser->m_nsAttsPower < 3)
parser->m_nsAttsPower = 3;
nsAttsSize = (int)1 << parser->m_nsAttsPower;

/* Detect and prevent invalid shift */
if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
/* Restore actual size of memory in m_nsAtts */
parser->m_nsAttsPower = oldNsAttsPower;
return XML_ERROR_NO_MEMORY;
}

nsAttsSize = 1u << parser->m_nsAttsPower;

/* Detect and prevent integer overflow.
* The preprocessor guard addresses the "always false" warning
* from -Wtype-limits on platforms where
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
#if UINT_MAX >= SIZE_MAX
if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
/* Restore actual size of memory in m_nsAtts */
parser->m_nsAttsPower = oldNsAttsPower;
return XML_ERROR_NO_MEMORY;
}
#endif

temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
nsAttsSize * sizeof(NS_ATT));
if (! temp) {
Expand Down