Skip to content

Commit d10bccc

Browse files
committed
bpo-30610: [Security] Python's libexpat vulnerable to CVE-2016-0718
CVE-2016-0718: Expat allows context-dependent attackers to cause a denial of service (crash) or possibly execute arbitrary code via a malformed input document, which triggers a buffer overflow. https://nvd.nist.gov/vuln/detail/CVE-2016-0718 Upgrade to Expat 2.2.0, which is not vulnerable https://github.com/libexpat/libexpat/blob/R_2_2_0/expat/Changes Read the description: https://bugs.python.org/issue30610
1 parent 59fdf0f commit d10bccc

File tree

10 files changed

+522
-344
lines changed

10 files changed

+522
-344
lines changed

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ Extension Modules
350350
Library
351351
-------
352352

353+
- bpo-30610: [Security] Python's libexpat vulnerable to CVE-2016-0718.
354+
Patch by Stéphane Wirtel.
355+
353356
- bpo-30418: On Windows, subprocess.Popen.communicate() now also ignore EINVAL
354357
on stdin.write() if the child process is still running but closed the pipe.
355358

Modules/expat/amigaconfig.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
/* Define to 1 if you have the `bcopy' function. */
88
#define HAVE_BCOPY 1
99

10-
/* Define to 1 if you have the <check.h> header file. */
11-
#undef HAVE_CHECK_H
12-
1310
/* Define to 1 if you have the `memmove' function. */
1411
#define HAVE_MEMMOVE 1
1512

Modules/expat/expat.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ XML_SetEntityDeclHandler(XML_Parser parser,
342342
XML_EntityDeclHandler handler);
343343

344344
/* OBSOLETE -- OBSOLETE -- OBSOLETE
345-
This handler has been superceded by the EntityDeclHandler above.
345+
This handler has been superseded by the EntityDeclHandler above.
346346
It is provided here for backward compatibility.
347347
348348
This is called for a declaration of an unparsed (NDATA) entity.
@@ -915,8 +915,6 @@ XMLPARSEAPI(int)
915915
XML_SetHashSalt(XML_Parser parser,
916916
unsigned long hash_salt);
917917

918-
#define XML_HAS_SET_HASH_SALT /* Python Only: Defined for pyexpat.c. */
919-
920918
/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
921919
XML_GetErrorCode returns information about the error.
922920
*/
@@ -975,9 +973,12 @@ XML_FreeContentModel(XML_Parser parser, XML_Content *model);
975973

976974
/* Exposing the memory handling functions used in Expat */
977975
XMLPARSEAPI(void *)
976+
XML_ATTR_MALLOC
977+
XML_ATTR_ALLOC_SIZE(2)
978978
XML_MemMalloc(XML_Parser parser, size_t size);
979979

980980
XMLPARSEAPI(void *)
981+
XML_ATTR_ALLOC_SIZE(3)
981982
XML_MemRealloc(XML_Parser parser, void *ptr, size_t size);
982983

983984
XMLPARSEAPI(void)
@@ -1033,14 +1034,12 @@ XMLPARSEAPI(const XML_Feature *)
10331034
XML_GetFeatureList(void);
10341035

10351036

1036-
/* Expat follows the GNU/Linux convention of odd number minor version for
1037-
beta/development releases and even number minor version for stable
1038-
releases. Micro is bumped with each release, and set to 0 with each
1039-
change to major or minor version.
1037+
/* Expat follows the semantic versioning convention.
1038+
See http://semver.org.
10401039
*/
10411040
#define XML_MAJOR_VERSION 2
1042-
#define XML_MINOR_VERSION 1
1043-
#define XML_MICRO_VERSION 1
1041+
#define XML_MINOR_VERSION 2
1042+
#define XML_MICRO_VERSION 0
10441043

10451044
#ifdef __cplusplus
10461045
}

Modules/expat/expat_external.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77

88
/* External API definitions */
99

10-
/* Namespace external symbols to allow multiple libexpat version to
11-
co-exist. */
12-
#include "pyexpatns.h"
13-
1410
#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
1511
#define XML_USE_MSC_EXTENSIONS 1
1612
#endif
@@ -69,12 +65,26 @@
6965
#endif
7066
#endif /* not defined XML_STATIC */
7167

68+
#if !defined(XMLIMPORT) && defined(__GNUC__) && (__GNUC__ >= 4)
69+
#define XMLIMPORT __attribute__ ((visibility ("default")))
70+
#endif
7271

7372
/* If we didn't define it above, define it away: */
7473
#ifndef XMLIMPORT
7574
#define XMLIMPORT
7675
#endif
7776

77+
#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
78+
#define XML_ATTR_MALLOC __attribute__((__malloc__))
79+
#else
80+
#define XML_ATTR_MALLOC
81+
#endif
82+
83+
#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
84+
#define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
85+
#else
86+
#define XML_ATTR_ALLOC_SIZE(x)
87+
#endif
7888

7989
#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
8090

Modules/expat/internal.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,25 @@
7171
#define inline
7272
#endif
7373
#endif
74+
75+
#ifndef UNUSED_P
76+
# ifdef __GNUC__
77+
# define UNUSED_P(p) UNUSED_ ## p __attribute__((__unused__))
78+
# else
79+
# define UNUSED_P(p) UNUSED_ ## p
80+
# endif
81+
#endif
82+
83+
84+
#ifdef __cplusplus
85+
extern "C" {
86+
#endif
87+
88+
89+
void
90+
align_limit_to_full_utf8_characters(const char * from, const char ** fromLimRef);
91+
92+
93+
#ifdef __cplusplus
94+
}
95+
#endif

Modules/expat/xmlparse.c

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,22 @@
22
See the file COPYING for copying permission.
33
*/
44

5+
#include <stddef.h>
6+
#include <string.h> /* memset(), memcpy() */
7+
#include <assert.h>
8+
#include <limits.h> /* UINT_MAX */
9+
10+
#ifdef WIN32
11+
#define getpid GetCurrentProcessId
12+
#else
13+
#include <sys/time.h> /* gettimeofday() */
14+
#include <sys/types.h> /* getpid() */
15+
#include <unistd.h> /* getpid() */
16+
#endif
17+
518
#define XML_BUILDING_EXPAT 1
619

7-
#ifdef COMPILED_FROM_DSP
20+
#ifdef WIN32
821
#include "winconfig.h"
922
#elif defined(MACOS_CLASSIC)
1023
#include "macconfig.h"
@@ -14,13 +27,7 @@
1427
#include "watcomconfig.h"
1528
#elif defined(HAVE_EXPAT_CONFIG_H)
1629
#include <expat_config.h>
17-
#endif /* ndef COMPILED_FROM_DSP */
18-
19-
#include <stddef.h>
20-
#include <string.h> /* memset(), memcpy() */
21-
#include <assert.h>
22-
#include <limits.h> /* UINT_MAX */
23-
#include <time.h> /* time() */
30+
#endif /* ndef WIN32 */
2431

2532
#include "ascii.h"
2633
#include "expat.h"
@@ -432,7 +439,7 @@ static ELEMENT_TYPE *
432439
getElementType(XML_Parser parser, const ENCODING *enc,
433440
const char *ptr, const char *end);
434441

435-
static unsigned long generate_hash_secret_salt(void);
442+
static unsigned long generate_hash_secret_salt(XML_Parser parser);
436443
static XML_Bool startParsing(XML_Parser parser);
437444

438445
static XML_Parser
@@ -691,19 +698,46 @@ static const XML_Char implicitContext[] = {
691698
};
692699

693700
static unsigned long
694-
generate_hash_secret_salt(void)
701+
gather_time_entropy(void)
695702
{
696-
unsigned int seed = time(NULL) % UINT_MAX;
697-
srand(seed);
698-
return rand();
703+
#ifdef WIN32
704+
FILETIME ft;
705+
GetSystemTimeAsFileTime(&ft); /* never fails */
706+
return ft.dwHighDateTime ^ ft.dwLowDateTime;
707+
#else
708+
struct timeval tv;
709+
int gettimeofday_res;
710+
711+
gettimeofday_res = gettimeofday(&tv, NULL);
712+
assert (gettimeofday_res == 0);
713+
714+
/* Microseconds time is <20 bits entropy */
715+
return tv.tv_usec;
716+
#endif
717+
}
718+
719+
static unsigned long
720+
generate_hash_secret_salt(XML_Parser parser)
721+
{
722+
/* Process ID is 0 bits entropy if attacker has local access
723+
* XML_Parser address is few bits of entropy if attacker has local access */
724+
const unsigned long entropy =
725+
gather_time_entropy() ^ getpid() ^ (unsigned long)parser;
726+
727+
/* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
728+
if (sizeof(unsigned long) == 4) {
729+
return entropy * 2147483647;
730+
} else {
731+
return entropy * (unsigned long)2305843009213693951;
732+
}
699733
}
700734

701735
static XML_Bool /* only valid for root parser */
702736
startParsing(XML_Parser parser)
703737
{
704738
/* hash functions must be initialized before setContext() is called */
705739
if (hash_secret_salt == 0)
706-
hash_secret_salt = generate_hash_secret_salt();
740+
hash_secret_salt = generate_hash_secret_salt(parser);
707741
if (ns) {
708742
/* implicit context only set for root parser, since child
709743
parsers (i.e. external entity parsers) will inherit it
@@ -1695,15 +1729,15 @@ XML_GetBuffer(XML_Parser parser, int len)
16951729
if (len > bufferLim - bufferEnd) {
16961730
#ifdef XML_CONTEXT_BYTES
16971731
int keep;
1698-
#endif
1699-
int neededSize = len + (int)(bufferEnd - bufferPtr);
1732+
#endif /* defined XML_CONTEXT_BYTES */
1733+
/* Do not invoke signed arithmetic overflow: */
1734+
int neededSize = (int) ((unsigned)len + (unsigned)(bufferEnd - bufferPtr));
17001735
if (neededSize < 0) {
17011736
errorCode = XML_ERROR_NO_MEMORY;
17021737
return NULL;
17031738
}
17041739
#ifdef XML_CONTEXT_BYTES
17051740
keep = (int)(bufferPtr - buffer);
1706-
17071741
if (keep > XML_CONTEXT_BYTES)
17081742
keep = XML_CONTEXT_BYTES;
17091743
neededSize += keep;
@@ -1728,7 +1762,8 @@ XML_GetBuffer(XML_Parser parser, int len)
17281762
if (bufferSize == 0)
17291763
bufferSize = INIT_BUFFER_SIZE;
17301764
do {
1731-
bufferSize *= 2;
1765+
/* Do not invoke signed arithmetic overflow: */
1766+
bufferSize = (int) (2U * (unsigned) bufferSize);
17321767
} while (bufferSize < neededSize && bufferSize > 0);
17331768
if (bufferSize <= 0) {
17341769
errorCode = XML_ERROR_NO_MEMORY;
@@ -1855,7 +1890,7 @@ XML_Index XMLCALL
18551890
XML_GetCurrentByteIndex(XML_Parser parser)
18561891
{
18571892
if (eventPtr)
1858-
return parseEndByteIndex - (parseEndPtr - eventPtr);
1893+
return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr));
18591894
return -1;
18601895
}
18611896

@@ -2429,11 +2464,11 @@ doContent(XML_Parser parser,
24292464
for (;;) {
24302465
int bufSize;
24312466
int convLen;
2432-
XmlConvert(enc,
2467+
const enum XML_Convert_Result convert_res = XmlConvert(enc,
24332468
&fromPtr, rawNameEnd,
24342469
(ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
24352470
convLen = (int)(toPtr - (XML_Char *)tag->buf);
2436-
if (fromPtr == rawNameEnd) {
2471+
if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
24372472
tag->name.strLen = convLen;
24382473
break;
24392474
}
@@ -2654,11 +2689,11 @@ doContent(XML_Parser parser,
26542689
if (MUST_CONVERT(enc, s)) {
26552690
for (;;) {
26562691
ICHAR *dataPtr = (ICHAR *)dataBuf;
2657-
XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
2692+
const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
26582693
*eventEndPP = s;
26592694
charDataHandler(handlerArg, dataBuf,
26602695
(int)(dataPtr - (ICHAR *)dataBuf));
2661-
if (s == next)
2696+
if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
26622697
break;
26632698
*eventPP = s;
26642699
}
@@ -3264,11 +3299,11 @@ doCdataSection(XML_Parser parser,
32643299
if (MUST_CONVERT(enc, s)) {
32653300
for (;;) {
32663301
ICHAR *dataPtr = (ICHAR *)dataBuf;
3267-
XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3302+
const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
32683303
*eventEndPP = next;
32693304
charDataHandler(handlerArg, dataBuf,
32703305
(int)(dataPtr - (ICHAR *)dataBuf));
3271-
if (s == next)
3306+
if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
32723307
break;
32733308
*eventPP = s;
32743309
}
@@ -4927,9 +4962,9 @@ internalEntityProcessor(XML_Parser parser,
49274962

49284963
static enum XML_Error PTRCALL
49294964
errorProcessor(XML_Parser parser,
4930-
const char *s,
4931-
const char *end,
4932-
const char **nextPtr)
4965+
const char *UNUSED_P(s),
4966+
const char *UNUSED_P(end),
4967+
const char **UNUSED_P(nextPtr))
49334968
{
49344969
return errorCode;
49354970
}
@@ -5345,6 +5380,7 @@ reportDefault(XML_Parser parser, const ENCODING *enc,
53455380
const char *s, const char *end)
53465381
{
53475382
if (MUST_CONVERT(enc, s)) {
5383+
enum XML_Convert_Result convert_res;
53485384
const char **eventPP;
53495385
const char **eventEndPP;
53505386
if (enc == encoding) {
@@ -5357,11 +5393,11 @@ reportDefault(XML_Parser parser, const ENCODING *enc,
53575393
}
53585394
do {
53595395
ICHAR *dataPtr = (ICHAR *)dataBuf;
5360-
XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
5396+
convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
53615397
*eventEndPP = s;
53625398
defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
53635399
*eventPP = s;
5364-
} while (s != end);
5400+
} while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
53655401
}
53665402
else
53675403
defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
@@ -6166,8 +6202,8 @@ poolAppend(STRING_POOL *pool, const ENCODING *enc,
61666202
if (!pool->ptr && !poolGrow(pool))
61676203
return NULL;
61686204
for (;;) {
6169-
XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6170-
if (ptr == end)
6205+
const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6206+
if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
61716207
break;
61726208
if (!poolGrow(pool))
61736209
return NULL;
@@ -6251,8 +6287,13 @@ poolGrow(STRING_POOL *pool)
62516287
}
62526288
}
62536289
if (pool->blocks && pool->start == pool->blocks->s) {
6254-
int blockSize = (int)(pool->end - pool->start)*2;
6255-
BLOCK *temp = (BLOCK *)
6290+
BLOCK *temp;
6291+
int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
6292+
6293+
if (blockSize < 0)
6294+
return XML_FALSE;
6295+
6296+
temp = (BLOCK *)
62566297
pool->mem->realloc_fcn(pool->blocks,
62576298
(offsetof(BLOCK, s)
62586299
+ blockSize * sizeof(XML_Char)));
@@ -6267,6 +6308,10 @@ poolGrow(STRING_POOL *pool)
62676308
else {
62686309
BLOCK *tem;
62696310
int blockSize = (int)(pool->end - pool->start);
6311+
6312+
if (blockSize < 0)
6313+
return XML_FALSE;
6314+
62706315
if (blockSize < INIT_BLOCK_SIZE)
62716316
blockSize = INIT_BLOCK_SIZE;
62726317
else

0 commit comments

Comments
 (0)