DO NOT MERGE: Add validation for eternal enities

https://bugzilla.gnome.org/show_bug.cgi?id=780691

Bug: 36556310
Change-Id: I9450743e167c3c73af5e4071f3fc85e81d061648
(cherry picked from commit bef9af3d89d241bcb518c20cba6da2a2fd9ba049)

xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
    xmlChar *buf = NULL;
 int len = 0;
 int size = XML_PARSER_BUFFER_SIZE;
 int cur, l;
    xmlChar stop;
 int state = ctxt->instate;
 int count = 0;

    SHRINK;
 if (RAW == '"') {
        NEXT;
	stop = '"';
 } else if (RAW == '\'') {
        NEXT;
	stop = '\'';
 } else {
	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 return(NULL);
 }

    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 if (buf == NULL) {
        xmlErrMemory(ctxt, NULL);
 return(NULL);
 }
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
    cur = CUR_CHAR(l);
 while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
 if (len + 5 >= size) {
	    xmlChar *tmp;

 if ((size > XML_MAX_NAME_LENGTH) &&
 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
                xmlFree(buf);
		ctxt->instate = (xmlParserInputState) state;
 return(NULL);
 }
	    size *= 2;
	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 if (tmp == NULL) {
	        xmlFree(buf);
		xmlErrMemory(ctxt, NULL);
		ctxt->instate = (xmlParserInputState) state;
 return(NULL);
 }
	    buf = tmp;
 }
	count++;
 if (count > 50) {
	    GROW;
	    count = 0;
 if (ctxt->instate == XML_PARSER_EOF) {
	        xmlFree(buf);
 return(NULL);
 }
 }
	COPY_BUF(l,buf,len,cur);
	NEXTL(l);
	cur = CUR_CHAR(l);
 if (cur == 0) {
	    GROW;
	    SHRINK;
	    cur = CUR_CHAR(l);
 }
 }
    buf[len] = 0;
    ctxt->instate = (xmlParserInputState) state;
 if (!IS_CHAR(cur)) {
	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
 } else {
	NEXT;
 }
 return(buf);
}

xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
    xmlChar *buf = NULL;
 int len = 0;
 int size = XML_PARSER_BUFFER_SIZE;
 int cur, l;
    xmlChar stop;
 int state = ctxt->instate;
 int count = 0;

    SHRINK;
 if (RAW == '"') {
        NEXT;
	stop = '"';
 } else if (RAW == '\'') {
        NEXT;
	stop = '\'';
 } else {
	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
 return(NULL);
 }

    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
 if (buf == NULL) {
        xmlErrMemory(ctxt, NULL);
 return(NULL);
 }
    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
    cur = CUR_CHAR(l);
 while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
 if (len + 5 >= size) {
	    xmlChar *tmp;

 if ((size > XML_MAX_NAME_LENGTH) &&
 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
                xmlFree(buf);
		ctxt->instate = (xmlParserInputState) state;
 return(NULL);
 }
	    size *= 2;
	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
 if (tmp == NULL) {
	        xmlFree(buf);
		xmlErrMemory(ctxt, NULL);
		ctxt->instate = (xmlParserInputState) state;
 return(NULL);
 }
	    buf = tmp;
 }
	count++;
 if (count > 50) {
	    GROW;
	    count = 0;
 if (ctxt->instate == XML_PARSER_EOF) {
	        xmlFree(buf);
 return(NULL);
 }
 }
	COPY_BUF(l,buf,len,cur);
	NEXTL(l);
	cur = CUR_CHAR(l);
 if (cur == 0) {
	    GROW;
	    SHRINK;
	    cur = CUR_CHAR(l);
 }
 }
    buf[len] = 0;
    ctxt->instate = (xmlParserInputState) state;
 if (!IS_CHAR(cur)) {
	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
 } else {
	NEXT;
 }
 return(buf);
}
