From 990b5427fd3bf5c00ac7c5820d5f455378776b62 Mon Sep 17 00:00:00 2001 From: Armin Kuster Date: Sat, 9 Jul 2016 15:03:43 -0700 Subject: libxml2: Security fix for CVE-2016-1833 Affects libxml2 < 2.9.4 Signed-off-by: Armin Kuster --- .../libxml/libxml2/CVE-2016-1833.patch | 368 +++++++++++++++++++++ meta/recipes-core/libxml/libxml2_2.9.2.bb | 1 + 2 files changed, 369 insertions(+) create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2016-1833.patch (limited to 'meta/recipes-core/libxml') diff --git a/meta/recipes-core/libxml/libxml2/CVE-2016-1833.patch b/meta/recipes-core/libxml/libxml2/CVE-2016-1833.patch new file mode 100644 index 0000000000..26a19b86e7 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2016-1833.patch @@ -0,0 +1,368 @@ +From 0bcd05c5cd83dec3406c8f68b769b1d610c72f76 Mon Sep 17 00:00:00 2001 +From: Pranjal Jumde +Date: Tue, 1 Mar 2016 15:18:04 -0800 +Subject: [PATCH] Heap-based buffer overread in htmlCurrentChar + +For https://bugzilla.gnome.org/show_bug.cgi?id=758606 + +* parserInternals.c: +(xmlNextChar): Add an test to catch other issues on ctxt->input +corruption proactively. +For non-UTF-8 charsets, xmlNextChar() failed to check for the end +of the input buffer and would continuing reading. Fix this by +pulling out the check for the end of the input buffer into common +code, and return if we reach the end of the input buffer +prematurely. +* result/HTML/758606.html: Added. +* result/HTML/758606.html.err: Added. +* result/HTML/758606.html.sax: Added. +* result/HTML/758606_2.html: Added. +* result/HTML/758606_2.html.err: Added. +* result/HTML/758606_2.html.sax: Added. +* test/HTML/758606.html: Added test case. +* test/HTML/758606_2.html: Added test case. + +Upstream-Status: Backport +CVE: CVE-2016-1833 +Signed-off-by: Armin Kuster + +--- + parserInternals.c | 172 ++++++++++++++++++++++-------------------- + result/HTML/758606.html | 2 + + result/HTML/758606.html.err | 16 ++++ + result/HTML/758606.html.sax | 10 +++ + result/HTML/758606_2.html | 2 + + result/HTML/758606_2.html.err | 16 ++++ + result/HTML/758606_2.html.sax | 17 +++++ + test/HTML/758606.html | 1 + + test/HTML/758606_2.html | 1 + + 9 files changed, 154 insertions(+), 83 deletions(-) + create mode 100644 result/HTML/758606.html + create mode 100644 result/HTML/758606.html.err + create mode 100644 result/HTML/758606.html.sax + create mode 100644 result/HTML/758606_2.html + create mode 100644 result/HTML/758606_2.html.err + create mode 100644 result/HTML/758606_2.html.sax + create mode 100644 test/HTML/758606.html + create mode 100644 test/HTML/758606_2.html + +diff --git a/parserInternals.c b/parserInternals.c +index 8c79678..bfc778a 100644 +--- a/parserInternals.c ++++ b/parserInternals.c +@@ -55,6 +55,10 @@ + #include + #include + ++#define CUR(ctxt) ctxt->input->cur ++#define END(ctxt) ctxt->input->end ++#define VALID_CTXT(ctxt) (CUR(ctxt) <= END(ctxt)) ++ + #include "buf.h" + #include "enc.h" + +@@ -422,103 +426,105 @@ xmlNextChar(xmlParserCtxtPtr ctxt) + (ctxt->input == NULL)) + return; + +- if (ctxt->charset == XML_CHAR_ENCODING_UTF8) { +- if ((*ctxt->input->cur == 0) && +- (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0) && +- (ctxt->instate != XML_PARSER_COMMENT)) { +- /* +- * If we are at the end of the current entity and +- * the context allows it, we pop consumed entities +- * automatically. +- * the auto closing should be blocked in other cases +- */ ++ if (!(VALID_CTXT(ctxt))) { ++ xmlErrInternal(ctxt, "Parser input data memory error\n", NULL); ++ ctxt->errNo = XML_ERR_INTERNAL_ERROR; ++ xmlStopParser(ctxt); ++ return; ++ } ++ ++ if ((*ctxt->input->cur == 0) && ++ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) { ++ if ((ctxt->instate != XML_PARSER_COMMENT)) + xmlPopInput(ctxt); +- } else { +- const unsigned char *cur; +- unsigned char c; ++ return; ++ } + +- /* +- * 2.11 End-of-Line Handling +- * the literal two-character sequence "#xD#xA" or a standalone +- * literal #xD, an XML processor must pass to the application +- * the single character #xA. +- */ +- if (*(ctxt->input->cur) == '\n') { +- ctxt->input->line++; ctxt->input->col = 1; +- } else +- ctxt->input->col++; ++ if (ctxt->charset == XML_CHAR_ENCODING_UTF8) { ++ const unsigned char *cur; ++ unsigned char c; + +- /* +- * We are supposed to handle UTF8, check it's valid +- * From rfc2044: encoding of the Unicode values on UTF-8: +- * +- * UCS-4 range (hex.) UTF-8 octet sequence (binary) +- * 0000 0000-0000 007F 0xxxxxxx +- * 0000 0080-0000 07FF 110xxxxx 10xxxxxx +- * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx +- * +- * Check for the 0x110000 limit too +- */ +- cur = ctxt->input->cur; ++ /* ++ * 2.11 End-of-Line Handling ++ * the literal two-character sequence "#xD#xA" or a standalone ++ * literal #xD, an XML processor must pass to the application ++ * the single character #xA. ++ */ ++ if (*(ctxt->input->cur) == '\n') { ++ ctxt->input->line++; ctxt->input->col = 1; ++ } else ++ ctxt->input->col++; + +- c = *cur; +- if (c & 0x80) { +- if (c == 0xC0) +- goto encoding_error; +- if (cur[1] == 0) { ++ /* ++ * We are supposed to handle UTF8, check it's valid ++ * From rfc2044: encoding of the Unicode values on UTF-8: ++ * ++ * UCS-4 range (hex.) UTF-8 octet sequence (binary) ++ * 0000 0000-0000 007F 0xxxxxxx ++ * 0000 0080-0000 07FF 110xxxxx 10xxxxxx ++ * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx ++ * ++ * Check for the 0x110000 limit too ++ */ ++ cur = ctxt->input->cur; ++ ++ c = *cur; ++ if (c & 0x80) { ++ if (c == 0xC0) ++ goto encoding_error; ++ if (cur[1] == 0) { ++ xmlParserInputGrow(ctxt->input, INPUT_CHUNK); ++ cur = ctxt->input->cur; ++ } ++ if ((cur[1] & 0xc0) != 0x80) ++ goto encoding_error; ++ if ((c & 0xe0) == 0xe0) { ++ unsigned int val; ++ ++ if (cur[2] == 0) { + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + cur = ctxt->input->cur; + } +- if ((cur[1] & 0xc0) != 0x80) ++ if ((cur[2] & 0xc0) != 0x80) + goto encoding_error; +- if ((c & 0xe0) == 0xe0) { +- unsigned int val; +- +- if (cur[2] == 0) { ++ if ((c & 0xf0) == 0xf0) { ++ if (cur[3] == 0) { + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + cur = ctxt->input->cur; + } +- if ((cur[2] & 0xc0) != 0x80) ++ if (((c & 0xf8) != 0xf0) || ++ ((cur[3] & 0xc0) != 0x80)) + goto encoding_error; +- if ((c & 0xf0) == 0xf0) { +- if (cur[3] == 0) { +- xmlParserInputGrow(ctxt->input, INPUT_CHUNK); +- cur = ctxt->input->cur; +- } +- if (((c & 0xf8) != 0xf0) || +- ((cur[3] & 0xc0) != 0x80)) +- goto encoding_error; +- /* 4-byte code */ +- ctxt->input->cur += 4; +- val = (cur[0] & 0x7) << 18; +- val |= (cur[1] & 0x3f) << 12; +- val |= (cur[2] & 0x3f) << 6; +- val |= cur[3] & 0x3f; +- } else { +- /* 3-byte code */ +- ctxt->input->cur += 3; +- val = (cur[0] & 0xf) << 12; +- val |= (cur[1] & 0x3f) << 6; +- val |= cur[2] & 0x3f; +- } +- if (((val > 0xd7ff) && (val < 0xe000)) || +- ((val > 0xfffd) && (val < 0x10000)) || +- (val >= 0x110000)) { +- xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR, +- "Char 0x%X out of allowed range\n", +- val); +- } +- } else +- /* 2-byte code */ +- ctxt->input->cur += 2; ++ /* 4-byte code */ ++ ctxt->input->cur += 4; ++ val = (cur[0] & 0x7) << 18; ++ val |= (cur[1] & 0x3f) << 12; ++ val |= (cur[2] & 0x3f) << 6; ++ val |= cur[3] & 0x3f; ++ } else { ++ /* 3-byte code */ ++ ctxt->input->cur += 3; ++ val = (cur[0] & 0xf) << 12; ++ val |= (cur[1] & 0x3f) << 6; ++ val |= cur[2] & 0x3f; ++ } ++ if (((val > 0xd7ff) && (val < 0xe000)) || ++ ((val > 0xfffd) && (val < 0x10000)) || ++ (val >= 0x110000)) { ++ xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR, ++ "Char 0x%X out of allowed range\n", ++ val); ++ } + } else +- /* 1-byte code */ +- ctxt->input->cur++; ++ /* 2-byte code */ ++ ctxt->input->cur += 2; ++ } else ++ /* 1-byte code */ ++ ctxt->input->cur++; + +- ctxt->nbChars++; +- if (*ctxt->input->cur == 0) +- xmlParserInputGrow(ctxt->input, INPUT_CHUNK); +- } ++ ctxt->nbChars++; ++ if (*ctxt->input->cur == 0) ++ xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + } else { + /* + * Assume it's a fixed length encoding (1) with +diff --git a/result/HTML/758606.html b/result/HTML/758606.html +new file mode 100644 +index 0000000..4f21f62 +--- /dev/null ++++ b/result/HTML/758606.html +@@ -0,0 +1,2 @@ ++ ++ +diff --git a/result/HTML/758606.html.err b/result/HTML/758606.html.err +new file mode 100644 +index 0000000..060433a +--- /dev/null ++++ b/result/HTML/758606.html.err +@@ -0,0 +1,16 @@ ++./test/HTML/758606.html:1: HTML parser error : Comment not terminated ++