Gentoo Archives: gentoo-commits

From: Sebastian Pipping <sping@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: dev-libs/expat/files/, dev-libs/expat/
Date: Sat, 28 May 2016 16:41:20
Message-Id: 1464453644.6bcf306fc93c86f15779e3e3f44ec856beb1414c.sping@gentoo
1 commit: 6bcf306fc93c86f15779e3e3f44ec856beb1414c
2 Author: Sebastian Pipping <sping <AT> gentoo <DOT> org>
3 AuthorDate: Sat May 28 16:39:40 2016 +0000
4 Commit: Sebastian Pipping <sping <AT> gentoo <DOT> org>
5 CommitDate: Sat May 28 16:40:44 2016 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=6bcf306f
7
8 dev-libs/expat: 2.1.1-r1 (bug #583268)
9
10 Package-Manager: portage-2.2.28
11
12 dev-libs/expat/expat-2.1.1-r1.ebuild | 94 +++
13 .../files/expat-2.1.1-CVE-2015-1283-refix.patch | 37 +
14 .../files/expat-2.1.1-CVE-2016-0718-v2-2-1.patch | 755 +++++++++++++++++++++
15 3 files changed, 886 insertions(+)
16
17 diff --git a/dev-libs/expat/expat-2.1.1-r1.ebuild b/dev-libs/expat/expat-2.1.1-r1.ebuild
18 new file mode 100644
19 index 0000000..afdbad1
20 --- /dev/null
21 +++ b/dev-libs/expat/expat-2.1.1-r1.ebuild
22 @@ -0,0 +1,94 @@
23 +# Copyright 1999-2016 Gentoo Foundation
24 +# Distributed under the terms of the GNU General Public License v2
25 +# $Id$
26 +
27 +EAPI=5
28 +inherit eutils libtool multilib toolchain-funcs multilib-minimal
29 +
30 +DESCRIPTION="Stream-oriented XML parser library"
31 +HOMEPAGE="http://expat.sourceforge.net/"
32 +SRC_URI="mirror://sourceforge/expat/${P}.tar.bz2"
33 +
34 +LICENSE="MIT"
35 +SLOT="0"
36 +KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~amd64-fbsd ~sparc-fbsd ~x86-fbsd ~arm-linux ~x86-linux"
37 +IUSE="elibc_FreeBSD examples static-libs unicode"
38 +RDEPEND="abi_x86_32? ( !<=app-emulation/emul-linux-x86-baselibs-20130224-r6
39 + !app-emulation/emul-linux-x86-baselibs[-abi_x86_32(-)] )"
40 +
41 +src_prepare() {
42 + # https://bugs.gentoo.org/show_bug.cgi?id=583268
43 + epatch "${FILESDIR}"/${P}-CVE-2015-1283-refix.patch
44 + epatch "${FILESDIR}"/${P}-CVE-2016-0718-v2-2-1.patch
45 +}
46 +
47 +multilib_src_configure() {
48 + local myconf="$(use_enable static-libs static)"
49 +
50 + mkdir -p "${BUILD_DIR}"{u,w} || die
51 +
52 + ECONF_SOURCE="${S}" econf ${myconf}
53 +
54 + if use unicode; then
55 + pushd "${BUILD_DIR}"u >/dev/null
56 + CPPFLAGS="${CPPFLAGS} -DXML_UNICODE" ECONF_SOURCE="${S}" econf ${myconf}
57 + popd >/dev/null
58 +
59 + pushd "${BUILD_DIR}"w >/dev/null
60 + CPPFLAGS="${CPPFLAGS} -DXML_UNICODE_WCHAR_T" ECONF_SOURCE="${S}" econf ${myconf}
61 + popd >/dev/null
62 + fi
63 +}
64 +
65 +multilib_src_compile() {
66 + emake
67 +
68 + if use unicode; then
69 + pushd "${BUILD_DIR}"u >/dev/null
70 + emake buildlib LIBRARY=libexpatu.la
71 + popd >/dev/null
72 +
73 + pushd "${BUILD_DIR}"w >/dev/null
74 + emake buildlib LIBRARY=libexpatw.la
75 + popd >/dev/null
76 + fi
77 +}
78 +
79 +multilib_src_install() {
80 + emake install DESTDIR="${D}"
81 +
82 + if use unicode; then
83 + pushd "${BUILD_DIR}"u >/dev/null
84 + emake installlib DESTDIR="${D}" LIBRARY=libexpatu.la
85 + popd >/dev/null
86 +
87 + pushd "${BUILD_DIR}"w >/dev/null
88 + emake installlib DESTDIR="${D}" LIBRARY=libexpatw.la
89 + popd >/dev/null
90 +
91 + pushd "${ED}"/usr/$(get_libdir)/pkgconfig >/dev/null
92 + cp expat.pc expatu.pc
93 + sed -i -e '/^Libs/s:-lexpat:&u:' expatu.pc || die
94 + cp expat.pc expatw.pc
95 + sed -i -e '/^Libs/s:-lexpat:&w:' expatw.pc || die
96 + popd >/dev/null
97 + fi
98 +
99 + if multilib_is_native_abi ; then
100 + # libgeom in /lib and ifconfig in /sbin require libexpat on FreeBSD since
101 + # we stripped the libbsdxml copy starting from freebsd-lib-8.2-r1
102 + use elibc_FreeBSD && gen_usr_ldscript -a expat
103 + fi
104 +}
105 +
106 +multilib_src_install_all() {
107 + dodoc Changes README
108 + dohtml doc/*
109 +
110 + if use examples; then
111 + insinto /usr/share/doc/${PF}/examples
112 + doins examples/*.c
113 + fi
114 +
115 + prune_libtool_files
116 +}
117
118 diff --git a/dev-libs/expat/files/expat-2.1.1-CVE-2015-1283-refix.patch b/dev-libs/expat/files/expat-2.1.1-CVE-2015-1283-refix.patch
119 new file mode 100644
120 index 0000000..0fd45ec
121 --- /dev/null
122 +++ b/dev-libs/expat/files/expat-2.1.1-CVE-2015-1283-refix.patch
123 @@ -0,0 +1,37 @@
124 +From 29a11774d8ebbafe8418b4a5ffb4cc1160b194a1 Mon Sep 17 00:00:00 2001
125 +From: Pascal Cuoq <cuoq@×××××××××××××.com>
126 +Date: Sun, 15 May 2016 09:05:46 +0200
127 +Subject: [PATCH] Avoid relying on undefined behavior in CVE-2015-1283 fix. It
128 + does not really work: https://godbolt.org/g/Zl8gdF
129 +
130 +---
131 + expat/lib/xmlparse.c | 6 ++++--
132 + 1 file changed, 4 insertions(+), 2 deletions(-)
133 +
134 +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
135 +index 13e080d..cdb12ef 100644
136 +--- a/expat/lib/xmlparse.c
137 ++++ b/expat/lib/xmlparse.c
138 +@@ -1693,7 +1693,8 @@ XML_GetBuffer(XML_Parser parser, int len)
139 + }
140 +
141 + if (len > bufferLim - bufferEnd) {
142 +- int neededSize = len + (int)(bufferEnd - bufferPtr);
143 ++ /* Do not invoke signed arithmetic overflow: */
144 ++ int neededSize = (int) ((unsigned)len + (unsigned)(bufferEnd - bufferPtr));
145 + if (neededSize < 0) {
146 + errorCode = XML_ERROR_NO_MEMORY;
147 + return NULL;
148 +@@ -1725,7 +1726,8 @@ XML_GetBuffer(XML_Parser parser, int len)
149 + if (bufferSize == 0)
150 + bufferSize = INIT_BUFFER_SIZE;
151 + do {
152 +- bufferSize *= 2;
153 ++ /* Do not invoke signed arithmetic overflow: */
154 ++ bufferSize = (int) (2U * (unsigned) bufferSize);
155 + } while (bufferSize < neededSize && bufferSize > 0);
156 + if (bufferSize <= 0) {
157 + errorCode = XML_ERROR_NO_MEMORY;
158 +--
159 +2.8.2
160 +
161
162 diff --git a/dev-libs/expat/files/expat-2.1.1-CVE-2016-0718-v2-2-1.patch b/dev-libs/expat/files/expat-2.1.1-CVE-2016-0718-v2-2-1.patch
163 new file mode 100644
164 index 0000000..8cc41bf
165 --- /dev/null
166 +++ b/dev-libs/expat/files/expat-2.1.1-CVE-2016-0718-v2-2-1.patch
167 @@ -0,0 +1,755 @@
168 +From cdfcb1b5c95e93b00ae9e9d25708b4a3bee72c15 Mon Sep 17 00:00:00 2001
169 +From: Sebastian Pipping <sebastian@×××××××.org>
170 +Date: Mon, 2 May 2016 00:02:44 +0200
171 +Subject: [PATCH] Address CVE-2016-0718 (/patch/ version 2.2.1)
172 +
173 +* Out of bounds memory access when doing text conversion on malformed input
174 +* Integer overflow related to memory allocation
175 +
176 +Reported by Gustavo Grieco
177 +
178 +Patch credits go to
179 +* Christian Heimes
180 +* Karl Waclawek
181 +* Gustavo Grieco
182 +* Sebastian Pipping
183 +* Pascal Cuoq
184 +---
185 + expat/lib/xmlparse.c | 34 +++++++++-----
186 + expat/lib/xmltok.c | 115 +++++++++++++++++++++++++++++++++++-------------
187 + expat/lib/xmltok.h | 10 ++++-
188 + expat/lib/xmltok_impl.c | 62 +++++++++++++-------------
189 + 4 files changed, 146 insertions(+), 75 deletions(-)
190 +
191 +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
192 +index e308c79..13e080d 100644
193 +--- a/expat/lib/xmlparse.c
194 ++++ b/expat/lib/xmlparse.c
195 +@@ -2426,11 +2426,11 @@ doContent(XML_Parser parser,
196 + for (;;) {
197 + int bufSize;
198 + int convLen;
199 +- XmlConvert(enc,
200 ++ const enum XML_Convert_Result convert_res = XmlConvert(enc,
201 + &fromPtr, rawNameEnd,
202 + (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
203 + convLen = (int)(toPtr - (XML_Char *)tag->buf);
204 +- if (fromPtr == rawNameEnd) {
205 ++ if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
206 + tag->name.strLen = convLen;
207 + break;
208 + }
209 +@@ -2651,11 +2651,11 @@ doContent(XML_Parser parser,
210 + if (MUST_CONVERT(enc, s)) {
211 + for (;;) {
212 + ICHAR *dataPtr = (ICHAR *)dataBuf;
213 +- XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
214 ++ const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
215 + *eventEndPP = s;
216 + charDataHandler(handlerArg, dataBuf,
217 + (int)(dataPtr - (ICHAR *)dataBuf));
218 +- if (s == next)
219 ++ if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
220 + break;
221 + *eventPP = s;
222 + }
223 +@@ -3261,11 +3261,11 @@ doCdataSection(XML_Parser parser,
224 + if (MUST_CONVERT(enc, s)) {
225 + for (;;) {
226 + ICHAR *dataPtr = (ICHAR *)dataBuf;
227 +- XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
228 ++ const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
229 + *eventEndPP = next;
230 + charDataHandler(handlerArg, dataBuf,
231 + (int)(dataPtr - (ICHAR *)dataBuf));
232 +- if (s == next)
233 ++ if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
234 + break;
235 + *eventPP = s;
236 + }
237 +@@ -5342,6 +5342,7 @@ reportDefault(XML_Parser parser, const ENCODING *enc,
238 + const char *s, const char *end)
239 + {
240 + if (MUST_CONVERT(enc, s)) {
241 ++ enum XML_Convert_Result convert_res;
242 + const char **eventPP;
243 + const char **eventEndPP;
244 + if (enc == encoding) {
245 +@@ -5354,11 +5355,11 @@ reportDefault(XML_Parser parser, const ENCODING *enc,
246 + }
247 + do {
248 + ICHAR *dataPtr = (ICHAR *)dataBuf;
249 +- XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
250 ++ convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
251 + *eventEndPP = s;
252 + defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
253 + *eventPP = s;
254 +- } while (s != end);
255 ++ } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
256 + }
257 + else
258 + defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
259 +@@ -6163,8 +6164,8 @@ poolAppend(STRING_POOL *pool, const ENCODING *enc,
260 + if (!pool->ptr && !poolGrow(pool))
261 + return NULL;
262 + for (;;) {
263 +- XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
264 +- if (ptr == end)
265 ++ const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
266 ++ if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
267 + break;
268 + if (!poolGrow(pool))
269 + return NULL;
270 +@@ -6248,8 +6249,13 @@ poolGrow(STRING_POOL *pool)
271 + }
272 + }
273 + if (pool->blocks && pool->start == pool->blocks->s) {
274 +- int blockSize = (int)(pool->end - pool->start)*2;
275 +- BLOCK *temp = (BLOCK *)
276 ++ BLOCK *temp;
277 ++ int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
278 ++
279 ++ if (blockSize < 0)
280 ++ return XML_FALSE;
281 ++
282 ++ temp = (BLOCK *)
283 + pool->mem->realloc_fcn(pool->blocks,
284 + (offsetof(BLOCK, s)
285 + + blockSize * sizeof(XML_Char)));
286 +@@ -6264,6 +6270,10 @@ poolGrow(STRING_POOL *pool)
287 + else {
288 + BLOCK *tem;
289 + int blockSize = (int)(pool->end - pool->start);
290 ++
291 ++ if (blockSize < 0)
292 ++ return XML_FALSE;
293 ++
294 + if (blockSize < INIT_BLOCK_SIZE)
295 + blockSize = INIT_BLOCK_SIZE;
296 + else
297 +diff --git a/expat/lib/xmltok.c b/expat/lib/xmltok.c
298 +index bf09dfc..cb98ce1 100644
299 +--- a/expat/lib/xmltok.c
300 ++++ b/expat/lib/xmltok.c
301 +@@ -318,39 +318,55 @@ enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
302 + UTF8_cval4 = 0xf0
303 + };
304 +
305 +-static void PTRCALL
306 ++static enum XML_Convert_Result PTRCALL
307 + utf8_toUtf8(const ENCODING *enc,
308 + const char **fromP, const char *fromLim,
309 + char **toP, const char *toLim)
310 + {
311 ++ enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
312 + char *to;
313 + const char *from;
314 + if (fromLim - *fromP > toLim - *toP) {
315 + /* Avoid copying partial characters. */
316 ++ res = XML_CONVERT_OUTPUT_EXHAUSTED;
317 + for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
318 + if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
319 + break;
320 + }
321 +- for (to = *toP, from = *fromP; from != fromLim; from++, to++)
322 ++ for (to = *toP, from = *fromP; (from < fromLim) && (to < toLim); from++, to++)
323 + *to = *from;
324 + *fromP = from;
325 + *toP = to;
326 ++
327 ++ if ((to == toLim) && (from < fromLim))
328 ++ return XML_CONVERT_OUTPUT_EXHAUSTED;
329 ++ else
330 ++ return res;
331 + }
332 +
333 +-static void PTRCALL
334 ++static enum XML_Convert_Result PTRCALL
335 + utf8_toUtf16(const ENCODING *enc,
336 + const char **fromP, const char *fromLim,
337 + unsigned short **toP, const unsigned short *toLim)
338 + {
339 ++ enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
340 + unsigned short *to = *toP;
341 + const char *from = *fromP;
342 +- while (from != fromLim && to != toLim) {
343 ++ while (from < fromLim && to < toLim) {
344 + switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
345 + case BT_LEAD2:
346 ++ if (fromLim - from < 2) {
347 ++ res = XML_CONVERT_INPUT_INCOMPLETE;
348 ++ break;
349 ++ }
350 + *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
351 + from += 2;
352 + break;
353 + case BT_LEAD3:
354 ++ if (fromLim - from < 3) {
355 ++ res = XML_CONVERT_INPUT_INCOMPLETE;
356 ++ break;
357 ++ }
358 + *to++ = (unsigned short)(((from[0] & 0xf) << 12)
359 + | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f));
360 + from += 3;
361 +@@ -358,8 +374,14 @@ utf8_toUtf16(const ENCODING *enc,
362 + case BT_LEAD4:
363 + {
364 + unsigned long n;
365 +- if (to + 1 == toLim)
366 ++ if (toLim - to < 2) {
367 ++ res = XML_CONVERT_OUTPUT_EXHAUSTED;
368 + goto after;
369 ++ }
370 ++ if (fromLim - from < 4) {
371 ++ res = XML_CONVERT_INPUT_INCOMPLETE;
372 ++ goto after;
373 ++ }
374 + n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
375 + | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
376 + n -= 0x10000;
377 +@@ -377,6 +399,7 @@ utf8_toUtf16(const ENCODING *enc,
378 + after:
379 + *fromP = from;
380 + *toP = to;
381 ++ return res;
382 + }
383 +
384 + #ifdef XML_NS
385 +@@ -425,7 +448,7 @@ static const struct normal_encoding internal_utf8_encoding = {
386 + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
387 + };
388 +
389 +-static void PTRCALL
390 ++static enum XML_Convert_Result PTRCALL
391 + latin1_toUtf8(const ENCODING *enc,
392 + const char **fromP, const char *fromLim,
393 + char **toP, const char *toLim)
394 +@@ -433,30 +456,35 @@ latin1_toUtf8(const ENCODING *enc,
395 + for (;;) {
396 + unsigned char c;
397 + if (*fromP == fromLim)
398 +- break;
399 ++ return XML_CONVERT_COMPLETED;
400 + c = (unsigned char)**fromP;
401 + if (c & 0x80) {
402 + if (toLim - *toP < 2)
403 +- break;
404 ++ return XML_CONVERT_OUTPUT_EXHAUSTED;
405 + *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
406 + *(*toP)++ = (char)((c & 0x3f) | 0x80);
407 + (*fromP)++;
408 + }
409 + else {
410 + if (*toP == toLim)
411 +- break;
412 ++ return XML_CONVERT_OUTPUT_EXHAUSTED;
413 + *(*toP)++ = *(*fromP)++;
414 + }
415 + }
416 + }
417 +
418 +-static void PTRCALL
419 ++static enum XML_Convert_Result PTRCALL
420 + latin1_toUtf16(const ENCODING *enc,
421 + const char **fromP, const char *fromLim,
422 + unsigned short **toP, const unsigned short *toLim)
423 + {
424 +- while (*fromP != fromLim && *toP != toLim)
425 ++ while (*fromP < fromLim && *toP < toLim)
426 + *(*toP)++ = (unsigned char)*(*fromP)++;
427 ++
428 ++ if ((*toP == toLim) && (*fromP < fromLim))
429 ++ return XML_CONVERT_OUTPUT_EXHAUSTED;
430 ++ else
431 ++ return XML_CONVERT_COMPLETED;
432 + }
433 +
434 + #ifdef XML_NS
435 +@@ -483,13 +511,18 @@ static const struct normal_encoding latin1_encoding = {
436 + STANDARD_VTABLE(sb_)
437 + };
438 +
439 +-static void PTRCALL
440 ++static enum XML_Convert_Result PTRCALL
441 + ascii_toUtf8(const ENCODING *enc,
442 + const char **fromP, const char *fromLim,
443 + char **toP, const char *toLim)
444 + {
445 +- while (*fromP != fromLim && *toP != toLim)
446 ++ while (*fromP < fromLim && *toP < toLim)
447 + *(*toP)++ = *(*fromP)++;
448 ++
449 ++ if ((*toP == toLim) && (*fromP < fromLim))
450 ++ return XML_CONVERT_OUTPUT_EXHAUSTED;
451 ++ else
452 ++ return XML_CONVERT_COMPLETED;
453 + }
454 +
455 + #ifdef XML_NS
456 +@@ -536,13 +569,14 @@ unicode_byte_type(char hi, char lo)
457 + }
458 +
459 + #define DEFINE_UTF16_TO_UTF8(E) \
460 +-static void PTRCALL \
461 ++static enum XML_Convert_Result PTRCALL \
462 + E ## toUtf8(const ENCODING *enc, \
463 + const char **fromP, const char *fromLim, \
464 + char **toP, const char *toLim) \
465 + { \
466 +- const char *from; \
467 +- for (from = *fromP; from != fromLim; from += 2) { \
468 ++ const char *from = *fromP; \
469 ++ fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */ \
470 ++ for (; from < fromLim; from += 2) { \
471 + int plane; \
472 + unsigned char lo2; \
473 + unsigned char lo = GET_LO(from); \
474 +@@ -552,7 +586,7 @@ E ## toUtf8(const ENCODING *enc, \
475 + if (lo < 0x80) { \
476 + if (*toP == toLim) { \
477 + *fromP = from; \
478 +- return; \
479 ++ return XML_CONVERT_OUTPUT_EXHAUSTED; \
480 + } \
481 + *(*toP)++ = lo; \
482 + break; \
483 +@@ -562,7 +596,7 @@ E ## toUtf8(const ENCODING *enc, \
484 + case 0x4: case 0x5: case 0x6: case 0x7: \
485 + if (toLim - *toP < 2) { \
486 + *fromP = from; \
487 +- return; \
488 ++ return XML_CONVERT_OUTPUT_EXHAUSTED; \
489 + } \
490 + *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
491 + *(*toP)++ = ((lo & 0x3f) | 0x80); \
492 +@@ -570,7 +604,7 @@ E ## toUtf8(const ENCODING *enc, \
493 + default: \
494 + if (toLim - *toP < 3) { \
495 + *fromP = from; \
496 +- return; \
497 ++ return XML_CONVERT_OUTPUT_EXHAUSTED; \
498 + } \
499 + /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
500 + *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
501 +@@ -580,7 +614,11 @@ E ## toUtf8(const ENCODING *enc, \
502 + case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
503 + if (toLim - *toP < 4) { \
504 + *fromP = from; \
505 +- return; \
506 ++ return XML_CONVERT_OUTPUT_EXHAUSTED; \
507 ++ } \
508 ++ if (fromLim - from < 4) { \
509 ++ *fromP = from; \
510 ++ return XML_CONVERT_INPUT_INCOMPLETE; \
511 + } \
512 + plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
513 + *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
514 +@@ -596,20 +634,32 @@ E ## toUtf8(const ENCODING *enc, \
515 + } \
516 + } \
517 + *fromP = from; \
518 ++ if (from < fromLim) \
519 ++ return XML_CONVERT_INPUT_INCOMPLETE; \
520 ++ else \
521 ++ return XML_CONVERT_COMPLETED; \
522 + }
523 +
524 + #define DEFINE_UTF16_TO_UTF16(E) \
525 +-static void PTRCALL \
526 ++static enum XML_Convert_Result PTRCALL \
527 + E ## toUtf16(const ENCODING *enc, \
528 + const char **fromP, const char *fromLim, \
529 + unsigned short **toP, const unsigned short *toLim) \
530 + { \
531 ++ enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
532 ++ fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \
533 + /* Avoid copying first half only of surrogate */ \
534 + if (fromLim - *fromP > ((toLim - *toP) << 1) \
535 +- && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
536 ++ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { \
537 + fromLim -= 2; \
538 +- for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
539 ++ res = XML_CONVERT_INPUT_INCOMPLETE; \
540 ++ } \
541 ++ for (; *fromP < fromLim && *toP < toLim; *fromP += 2) \
542 + *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
543 ++ if ((*toP == toLim) && (*fromP < fromLim)) \
544 ++ return XML_CONVERT_OUTPUT_EXHAUSTED; \
545 ++ else \
546 ++ return res; \
547 + }
548 +
549 + #define SET2(ptr, ch) \
550 +@@ -1288,7 +1338,7 @@ unknown_isInvalid(const ENCODING *enc, const char *p)
551 + return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
552 + }
553 +
554 +-static void PTRCALL
555 ++static enum XML_Convert_Result PTRCALL
556 + unknown_toUtf8(const ENCODING *enc,
557 + const char **fromP, const char *fromLim,
558 + char **toP, const char *toLim)
559 +@@ -1299,21 +1349,21 @@ unknown_toUtf8(const ENCODING *enc,
560 + const char *utf8;
561 + int n;
562 + if (*fromP == fromLim)
563 +- break;
564 ++ return XML_CONVERT_COMPLETED;
565 + utf8 = uenc->utf8[(unsigned char)**fromP];
566 + n = *utf8++;
567 + if (n == 0) {
568 + int c = uenc->convert(uenc->userData, *fromP);
569 + n = XmlUtf8Encode(c, buf);
570 + if (n > toLim - *toP)
571 +- break;
572 ++ return XML_CONVERT_OUTPUT_EXHAUSTED;
573 + utf8 = buf;
574 + *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
575 + - (BT_LEAD2 - 2));
576 + }
577 + else {
578 + if (n > toLim - *toP)
579 +- break;
580 ++ return XML_CONVERT_OUTPUT_EXHAUSTED;
581 + (*fromP)++;
582 + }
583 + do {
584 +@@ -1322,13 +1372,13 @@ unknown_toUtf8(const ENCODING *enc,
585 + }
586 + }
587 +
588 +-static void PTRCALL
589 ++static enum XML_Convert_Result PTRCALL
590 + unknown_toUtf16(const ENCODING *enc,
591 + const char **fromP, const char *fromLim,
592 + unsigned short **toP, const unsigned short *toLim)
593 + {
594 + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
595 +- while (*fromP != fromLim && *toP != toLim) {
596 ++ while (*fromP < fromLim && *toP < toLim) {
597 + unsigned short c = uenc->utf16[(unsigned char)**fromP];
598 + if (c == 0) {
599 + c = (unsigned short)
600 +@@ -1340,6 +1390,11 @@ unknown_toUtf16(const ENCODING *enc,
601 + (*fromP)++;
602 + *(*toP)++ = c;
603 + }
604 ++
605 ++ if ((*toP == toLim) && (*fromP < fromLim))
606 ++ return XML_CONVERT_OUTPUT_EXHAUSTED;
607 ++ else
608 ++ return XML_CONVERT_COMPLETED;
609 + }
610 +
611 + ENCODING *
612 +@@ -1503,7 +1558,7 @@ initScan(const ENCODING * const *encodingTable,
613 + {
614 + const ENCODING **encPtr;
615 +
616 +- if (ptr == end)
617 ++ if (ptr >= end)
618 + return XML_TOK_NONE;
619 + encPtr = enc->encPtr;
620 + if (ptr + 1 == end) {
621 +diff --git a/expat/lib/xmltok.h b/expat/lib/xmltok.h
622 +index ca867aa..752007e 100644
623 +--- a/expat/lib/xmltok.h
624 ++++ b/expat/lib/xmltok.h
625 +@@ -130,6 +130,12 @@ typedef int (PTRCALL *SCANNER)(const ENCODING *,
626 + const char *,
627 + const char **);
628 +
629 ++enum XML_Convert_Result {
630 ++ XML_CONVERT_COMPLETED = 0,
631 ++ XML_CONVERT_INPUT_INCOMPLETE = 1,
632 ++ XML_CONVERT_OUTPUT_EXHAUSTED = 2 /* and therefore potentially input remaining as well */
633 ++};
634 ++
635 + struct encoding {
636 + SCANNER scanners[XML_N_STATES];
637 + SCANNER literalScanners[XML_N_LITERAL_TYPES];
638 +@@ -158,12 +164,12 @@ struct encoding {
639 + const char *ptr,
640 + const char *end,
641 + const char **badPtr);
642 +- void (PTRCALL *utf8Convert)(const ENCODING *enc,
643 ++ enum XML_Convert_Result (PTRCALL *utf8Convert)(const ENCODING *enc,
644 + const char **fromP,
645 + const char *fromLim,
646 + char **toP,
647 + const char *toLim);
648 +- void (PTRCALL *utf16Convert)(const ENCODING *enc,
649 ++ enum XML_Convert_Result (PTRCALL *utf16Convert)(const ENCODING *enc,
650 + const char **fromP,
651 + const char *fromLim,
652 + unsigned short **toP,
653 +diff --git a/expat/lib/xmltok_impl.c b/expat/lib/xmltok_impl.c
654 +index 9c2895b..6c5a3ba 100644
655 +--- a/expat/lib/xmltok_impl.c
656 ++++ b/expat/lib/xmltok_impl.c
657 +@@ -93,13 +93,13 @@ static int PTRCALL
658 + PREFIX(scanComment)(const ENCODING *enc, const char *ptr,
659 + const char *end, const char **nextTokPtr)
660 + {
661 +- if (ptr != end) {
662 ++ if (ptr < end) {
663 + if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
664 + *nextTokPtr = ptr;
665 + return XML_TOK_INVALID;
666 + }
667 + ptr += MINBPC(enc);
668 +- while (ptr != end) {
669 ++ while (ptr < end) {
670 + switch (BYTE_TYPE(enc, ptr)) {
671 + INVALID_CASES(ptr, nextTokPtr)
672 + case BT_MINUS:
673 +@@ -147,7 +147,7 @@ PREFIX(scanDecl)(const ENCODING *enc, const char *ptr,
674 + *nextTokPtr = ptr;
675 + return XML_TOK_INVALID;
676 + }
677 +- while (ptr != end) {
678 ++ while (ptr < end) {
679 + switch (BYTE_TYPE(enc, ptr)) {
680 + case BT_PERCNT:
681 + if (ptr + MINBPC(enc) == end)
682 +@@ -233,7 +233,7 @@ PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
683 + *nextTokPtr = ptr;
684 + return XML_TOK_INVALID;
685 + }
686 +- while (ptr != end) {
687 ++ while (ptr < end) {
688 + switch (BYTE_TYPE(enc, ptr)) {
689 + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
690 + case BT_S: case BT_CR: case BT_LF:
691 +@@ -242,7 +242,7 @@ PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
692 + return XML_TOK_INVALID;
693 + }
694 + ptr += MINBPC(enc);
695 +- while (ptr != end) {
696 ++ while (ptr < end) {
697 + switch (BYTE_TYPE(enc, ptr)) {
698 + INVALID_CASES(ptr, nextTokPtr)
699 + case BT_QUEST:
700 +@@ -305,7 +305,7 @@ static int PTRCALL
701 + PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
702 + const char *end, const char **nextTokPtr)
703 + {
704 +- if (ptr == end)
705 ++ if (ptr >= end)
706 + return XML_TOK_NONE;
707 + if (MINBPC(enc) > 1) {
708 + size_t n = end - ptr;
709 +@@ -348,7 +348,7 @@ PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
710 + ptr += MINBPC(enc);
711 + break;
712 + }
713 +- while (ptr != end) {
714 ++ while (ptr < end) {
715 + switch (BYTE_TYPE(enc, ptr)) {
716 + #define LEAD_CASE(n) \
717 + case BT_LEAD ## n: \
718 +@@ -391,11 +391,11 @@ PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr,
719 + *nextTokPtr = ptr;
720 + return XML_TOK_INVALID;
721 + }
722 +- while (ptr != end) {
723 ++ while (ptr < end) {
724 + switch (BYTE_TYPE(enc, ptr)) {
725 + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
726 + case BT_S: case BT_CR: case BT_LF:
727 +- for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
728 ++ for (ptr += MINBPC(enc); ptr < end; ptr += MINBPC(enc)) {
729 + switch (BYTE_TYPE(enc, ptr)) {
730 + case BT_S: case BT_CR: case BT_LF:
731 + break;
732 +@@ -432,7 +432,7 @@ static int PTRCALL
733 + PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
734 + const char *end, const char **nextTokPtr)
735 + {
736 +- if (ptr != end) {
737 ++ if (ptr < end) {
738 + switch (BYTE_TYPE(enc, ptr)) {
739 + case BT_DIGIT:
740 + case BT_HEX:
741 +@@ -441,7 +441,7 @@ PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
742 + *nextTokPtr = ptr;
743 + return XML_TOK_INVALID;
744 + }
745 +- for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
746 ++ for (ptr += MINBPC(enc); ptr < end; ptr += MINBPC(enc)) {
747 + switch (BYTE_TYPE(enc, ptr)) {
748 + case BT_DIGIT:
749 + case BT_HEX:
750 +@@ -464,7 +464,7 @@ static int PTRCALL
751 + PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
752 + const char *end, const char **nextTokPtr)
753 + {
754 +- if (ptr != end) {
755 ++ if (ptr < end) {
756 + if (CHAR_MATCHES(enc, ptr, ASCII_x))
757 + return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
758 + switch (BYTE_TYPE(enc, ptr)) {
759 +@@ -474,7 +474,7 @@ PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
760 + *nextTokPtr = ptr;
761 + return XML_TOK_INVALID;
762 + }
763 +- for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
764 ++ for (ptr += MINBPC(enc); ptr < end; ptr += MINBPC(enc)) {
765 + switch (BYTE_TYPE(enc, ptr)) {
766 + case BT_DIGIT:
767 + break;
768 +@@ -506,7 +506,7 @@ PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
769 + *nextTokPtr = ptr;
770 + return XML_TOK_INVALID;
771 + }
772 +- while (ptr != end) {
773 ++ while (ptr < end) {
774 + switch (BYTE_TYPE(enc, ptr)) {
775 + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
776 + case BT_SEMI:
777 +@@ -529,7 +529,7 @@ PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
778 + #ifdef XML_NS
779 + int hadColon = 0;
780 + #endif
781 +- while (ptr != end) {
782 ++ while (ptr < end) {
783 + switch (BYTE_TYPE(enc, ptr)) {
784 + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
785 + #ifdef XML_NS
786 +@@ -716,7 +716,7 @@ PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
787 + hadColon = 0;
788 + #endif
789 + /* we have a start-tag */
790 +- while (ptr != end) {
791 ++ while (ptr < end) {
792 + switch (BYTE_TYPE(enc, ptr)) {
793 + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
794 + #ifdef XML_NS
795 +@@ -740,7 +740,7 @@ PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
796 + case BT_S: case BT_CR: case BT_LF:
797 + {
798 + ptr += MINBPC(enc);
799 +- while (ptr != end) {
800 ++ while (ptr < end) {
801 + switch (BYTE_TYPE(enc, ptr)) {
802 + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
803 + case BT_GT:
804 +@@ -785,7 +785,7 @@ static int PTRCALL
805 + PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
806 + const char **nextTokPtr)
807 + {
808 +- if (ptr == end)
809 ++ if (ptr >= end)
810 + return XML_TOK_NONE;
811 + if (MINBPC(enc) > 1) {
812 + size_t n = end - ptr;
813 +@@ -832,7 +832,7 @@ PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
814 + ptr += MINBPC(enc);
815 + break;
816 + }
817 +- while (ptr != end) {
818 ++ while (ptr < end) {
819 + switch (BYTE_TYPE(enc, ptr)) {
820 + #define LEAD_CASE(n) \
821 + case BT_LEAD ## n: \
822 +@@ -895,7 +895,7 @@ PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
823 + *nextTokPtr = ptr;
824 + return XML_TOK_INVALID;
825 + }
826 +- while (ptr != end) {
827 ++ while (ptr < end) {
828 + switch (BYTE_TYPE(enc, ptr)) {
829 + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
830 + case BT_SEMI:
831 +@@ -921,7 +921,7 @@ PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
832 + *nextTokPtr = ptr;
833 + return XML_TOK_INVALID;
834 + }
835 +- while (ptr != end) {
836 ++ while (ptr < end) {
837 + switch (BYTE_TYPE(enc, ptr)) {
838 + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
839 + case BT_CR: case BT_LF: case BT_S:
840 +@@ -941,7 +941,7 @@ PREFIX(scanLit)(int open, const ENCODING *enc,
841 + const char *ptr, const char *end,
842 + const char **nextTokPtr)
843 + {
844 +- while (ptr != end) {
845 ++ while (ptr < end) {
846 + int t = BYTE_TYPE(enc, ptr);
847 + switch (t) {
848 + INVALID_CASES(ptr, nextTokPtr)
849 +@@ -973,7 +973,7 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
850 + const char **nextTokPtr)
851 + {
852 + int tok;
853 +- if (ptr == end)
854 ++ if (ptr >= end)
855 + return XML_TOK_NONE;
856 + if (MINBPC(enc) > 1) {
857 + size_t n = end - ptr;
858 +@@ -1141,7 +1141,7 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
859 + *nextTokPtr = ptr;
860 + return XML_TOK_INVALID;
861 + }
862 +- while (ptr != end) {
863 ++ while (ptr < end) {
864 + switch (BYTE_TYPE(enc, ptr)) {
865 + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
866 + case BT_GT: case BT_RPAR: case BT_COMMA:
867 +@@ -1204,10 +1204,10 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
868 + const char *end, const char **nextTokPtr)
869 + {
870 + const char *start;
871 +- if (ptr == end)
872 ++ if (ptr >= end)
873 + return XML_TOK_NONE;
874 + start = ptr;
875 +- while (ptr != end) {
876 ++ while (ptr < end) {
877 + switch (BYTE_TYPE(enc, ptr)) {
878 + #define LEAD_CASE(n) \
879 + case BT_LEAD ## n: ptr += n; break;
880 +@@ -1262,10 +1262,10 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
881 + const char *end, const char **nextTokPtr)
882 + {
883 + const char *start;
884 +- if (ptr == end)
885 ++ if (ptr >= end)
886 + return XML_TOK_NONE;
887 + start = ptr;
888 +- while (ptr != end) {
889 ++ while (ptr < end) {
890 + switch (BYTE_TYPE(enc, ptr)) {
891 + #define LEAD_CASE(n) \
892 + case BT_LEAD ## n: ptr += n; break;
893 +@@ -1326,7 +1326,7 @@ PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr,
894 + end = ptr + n;
895 + }
896 + }
897 +- while (ptr != end) {
898 ++ while (ptr < end) {
899 + switch (BYTE_TYPE(enc, ptr)) {
900 + INVALID_CASES(ptr, nextTokPtr)
901 + case BT_LT:
902 +@@ -1373,7 +1373,7 @@ PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
903 + {
904 + ptr += MINBPC(enc);
905 + end -= MINBPC(enc);
906 +- for (; ptr != end; ptr += MINBPC(enc)) {
907 ++ for (; ptr < end; ptr += MINBPC(enc)) {
908 + switch (BYTE_TYPE(enc, ptr)) {
909 + case BT_DIGIT:
910 + case BT_HEX:
911 +@@ -1760,7 +1760,7 @@ PREFIX(updatePosition)(const ENCODING *enc,
912 + case BT_CR:
913 + pos->lineNumber++;
914 + ptr += MINBPC(enc);
915 +- if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
916 ++ if (ptr < end && BYTE_TYPE(enc, ptr) == BT_LF)
917 + ptr += MINBPC(enc);
918 + pos->columnNumber = (XML_Size)-1;
919 + break;
920 +--
921 +2.8.2
922 +