mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-20 18:50:08 +03:00
entities: Report malloc failures
Fix places where malloc failures aren't reported. Introduce new API function xmlAddEntity that returns separate error codes. Don't invoke global error handler for low-level errors which should be handled by higher layers. Invalid redelcaration warnings will be fixed later.
This commit is contained in:
parent
2e5d273beb
commit
a1f7ecaef8
337
entities.c
337
entities.c
@ -68,48 +68,6 @@ static xmlEntity xmlEntityApos = {
|
||||
NULL, NULL, NULL, NULL, 0, 0, 0
|
||||
};
|
||||
|
||||
/**
|
||||
* xmlEntitiesErrMemory:
|
||||
* @extra: extra information
|
||||
*
|
||||
* Handle an out of memory condition
|
||||
*/
|
||||
static void
|
||||
xmlEntitiesErrMemory(const char *extra)
|
||||
{
|
||||
__xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlEntitiesErr:
|
||||
* @code: the error code
|
||||
* @msg: the message
|
||||
*
|
||||
* Raise an error.
|
||||
*/
|
||||
static void LIBXML_ATTR_FORMAT(2,0)
|
||||
xmlEntitiesErr(xmlParserErrors code, const char *msg)
|
||||
{
|
||||
__xmlSimpleError(XML_FROM_TREE, code, NULL, msg, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlEntitiesWarn:
|
||||
* @code: the error code
|
||||
* @msg: the message
|
||||
*
|
||||
* Raise a warning.
|
||||
*/
|
||||
static void LIBXML_ATTR_FORMAT(2,0)
|
||||
xmlEntitiesWarn(xmlParserErrors code, const char *msg, const xmlChar *str1)
|
||||
{
|
||||
__xmlRaiseError(NULL, NULL, NULL,
|
||||
NULL, NULL, XML_FROM_TREE, code,
|
||||
XML_ERR_WARNING, NULL, 0,
|
||||
(const char *)str1, NULL, NULL, 0, 0,
|
||||
msg, (const char *)str1, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlFreeEntity : clean-up an entity record.
|
||||
*/
|
||||
@ -150,37 +108,43 @@ xmlFreeEntity(xmlEntityPtr entity)
|
||||
* internal routine doing the entity node structures allocations
|
||||
*/
|
||||
static xmlEntityPtr
|
||||
xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
|
||||
xmlCreateEntity(xmlDocPtr doc, const xmlChar *name, int type,
|
||||
const xmlChar *ExternalID, const xmlChar *SystemID,
|
||||
const xmlChar *content) {
|
||||
xmlEntityPtr ret;
|
||||
|
||||
ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
|
||||
if (ret == NULL) {
|
||||
xmlEntitiesErrMemory("xmlCreateEntity: malloc failed");
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlEntity));
|
||||
ret->doc = doc;
|
||||
ret->type = XML_ENTITY_DECL;
|
||||
|
||||
/*
|
||||
* fill the structure.
|
||||
*/
|
||||
ret->etype = (xmlEntityType) type;
|
||||
if (dict == NULL) {
|
||||
if ((doc == NULL) || (doc->dict == NULL))
|
||||
ret->name = xmlStrdup(name);
|
||||
if (ExternalID != NULL)
|
||||
ret->ExternalID = xmlStrdup(ExternalID);
|
||||
if (SystemID != NULL)
|
||||
ret->SystemID = xmlStrdup(SystemID);
|
||||
} else {
|
||||
ret->name = xmlDictLookup(dict, name, -1);
|
||||
ret->ExternalID = xmlStrdup(ExternalID);
|
||||
ret->SystemID = xmlStrdup(SystemID);
|
||||
else
|
||||
ret->name = xmlDictLookup(doc->dict, name, -1);
|
||||
if (ret->name == NULL)
|
||||
goto error;
|
||||
if (ExternalID != NULL) {
|
||||
ret->ExternalID = xmlStrdup(ExternalID);
|
||||
if (ret->ExternalID == NULL)
|
||||
goto error;
|
||||
}
|
||||
if (SystemID != NULL) {
|
||||
ret->SystemID = xmlStrdup(SystemID);
|
||||
if (ret->SystemID == NULL)
|
||||
goto error;
|
||||
}
|
||||
if (content != NULL) {
|
||||
ret->length = xmlStrlen(content);
|
||||
ret->content = xmlStrndup(content, ret->length);
|
||||
if (ret->content == NULL)
|
||||
goto error;
|
||||
} else {
|
||||
ret->length = 0;
|
||||
ret->content = NULL;
|
||||
@ -191,25 +155,49 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
|
||||
ret->owner = 0;
|
||||
|
||||
return(ret);
|
||||
|
||||
error:
|
||||
xmlFreeEntity(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlAddEntity : register a new entity for an entities table.
|
||||
/**
|
||||
* xmlAddEntity:
|
||||
* @doc: the document
|
||||
* @extSubset: add to the external or internal subset
|
||||
* @name: the entity name
|
||||
* @type: the entity type XML_xxx_yyy_ENTITY
|
||||
* @ExternalID: the entity external ID if available
|
||||
* @SystemID: the entity system ID if available
|
||||
* @content: the entity content
|
||||
* @out: pointer to resulting entity (optional)
|
||||
*
|
||||
* Register a new entity for this document.
|
||||
*
|
||||
* Returns an xmlParserErrors error code.
|
||||
*/
|
||||
static xmlEntityPtr
|
||||
xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
|
||||
int
|
||||
xmlAddEntity(xmlDocPtr doc, int extSubset, const xmlChar *name, int type,
|
||||
const xmlChar *ExternalID, const xmlChar *SystemID,
|
||||
const xmlChar *content) {
|
||||
const xmlChar *content, xmlEntityPtr *out) {
|
||||
xmlDtdPtr dtd;
|
||||
xmlDictPtr dict = NULL;
|
||||
xmlEntitiesTablePtr table = NULL;
|
||||
xmlEntityPtr ret, predef;
|
||||
int res;
|
||||
|
||||
if (name == NULL)
|
||||
return(NULL);
|
||||
if (out != NULL)
|
||||
*out = NULL;
|
||||
if ((doc == NULL) || (name == NULL))
|
||||
return(XML_ERR_ARGUMENT);
|
||||
dict = doc->dict;
|
||||
|
||||
if (extSubset)
|
||||
dtd = doc->extSubset;
|
||||
else
|
||||
dtd = doc->intSubset;
|
||||
if (dtd == NULL)
|
||||
return(NULL);
|
||||
if (dtd->doc != NULL)
|
||||
dict = dtd->doc->dict;
|
||||
return(XML_DTD_NO_DTD);
|
||||
|
||||
switch (type) {
|
||||
case XML_INTERNAL_GENERAL_ENTITY:
|
||||
@ -246,41 +234,59 @@ xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!valid) {
|
||||
xmlEntitiesWarn(XML_ERR_ENTITY_PROCESSING,
|
||||
"xmlAddEntity: invalid redeclaration of predefined"
|
||||
" entity '%s'", name);
|
||||
return(NULL);
|
||||
}
|
||||
if (!valid)
|
||||
return(XML_ERR_REDECL_PREDEF_ENTITY);
|
||||
}
|
||||
if (dtd->entities == NULL)
|
||||
if (dtd->entities == NULL) {
|
||||
dtd->entities = xmlHashCreateDict(0, dict);
|
||||
if (dtd->entities == NULL)
|
||||
return(XML_ERR_NO_MEMORY);
|
||||
}
|
||||
table = dtd->entities;
|
||||
break;
|
||||
case XML_INTERNAL_PARAMETER_ENTITY:
|
||||
case XML_EXTERNAL_PARAMETER_ENTITY:
|
||||
if (dtd->pentities == NULL)
|
||||
if (dtd->pentities == NULL) {
|
||||
dtd->pentities = xmlHashCreateDict(0, dict);
|
||||
if (dtd->pentities == NULL)
|
||||
return(XML_ERR_NO_MEMORY);
|
||||
}
|
||||
table = dtd->pentities;
|
||||
break;
|
||||
case XML_INTERNAL_PREDEFINED_ENTITY:
|
||||
return(NULL);
|
||||
return(XML_ERR_ARGUMENT);
|
||||
}
|
||||
if (table == NULL)
|
||||
return(NULL);
|
||||
ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content);
|
||||
ret = xmlCreateEntity(dtd->doc, name, type, ExternalID, SystemID, content);
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
ret->doc = dtd->doc;
|
||||
return(XML_ERR_NO_MEMORY);
|
||||
|
||||
if (xmlHashAddEntry(table, name, ret)) {
|
||||
res = xmlHashAdd(table, name, ret);
|
||||
if (res < 0) {
|
||||
xmlFreeEntity(ret);
|
||||
return(XML_ERR_NO_MEMORY);
|
||||
} else if (res == 0) {
|
||||
/*
|
||||
* entity was already defined at another level.
|
||||
*/
|
||||
xmlFreeEntity(ret);
|
||||
return(NULL);
|
||||
return(XML_WAR_ENTITY_REDEFINED);
|
||||
}
|
||||
return(ret);
|
||||
|
||||
/*
|
||||
* Link it to the DTD
|
||||
*/
|
||||
ret->parent = dtd;
|
||||
ret->doc = dtd->doc;
|
||||
if (dtd->last == NULL) {
|
||||
dtd->children = dtd->last = (xmlNodePtr) ret;
|
||||
} else {
|
||||
dtd->last->next = (xmlNodePtr) ret;
|
||||
ret->prev = dtd->last;
|
||||
dtd->last = (xmlNodePtr) ret;
|
||||
}
|
||||
|
||||
*out = ret;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -337,34 +343,8 @@ xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
|
||||
const xmlChar *ExternalID, const xmlChar *SystemID,
|
||||
const xmlChar *content) {
|
||||
xmlEntityPtr ret;
|
||||
xmlDtdPtr dtd;
|
||||
|
||||
if (doc == NULL) {
|
||||
xmlEntitiesErr(XML_DTD_NO_DOC,
|
||||
"xmlAddDtdEntity: document is NULL");
|
||||
return(NULL);
|
||||
}
|
||||
if (doc->extSubset == NULL) {
|
||||
xmlEntitiesErr(XML_DTD_NO_DTD,
|
||||
"xmlAddDtdEntity: document without external subset");
|
||||
return(NULL);
|
||||
}
|
||||
dtd = doc->extSubset;
|
||||
ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
|
||||
if (ret == NULL) return(NULL);
|
||||
|
||||
/*
|
||||
* Link it to the DTD
|
||||
*/
|
||||
ret->parent = dtd;
|
||||
ret->doc = dtd->doc;
|
||||
if (dtd->last == NULL) {
|
||||
dtd->children = dtd->last = (xmlNodePtr) ret;
|
||||
} else {
|
||||
dtd->last->next = (xmlNodePtr) ret;
|
||||
ret->prev = dtd->last;
|
||||
dtd->last = (xmlNodePtr) ret;
|
||||
}
|
||||
xmlAddEntity(doc, 1, name, type, ExternalID, SystemID, content, &ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -386,34 +366,8 @@ xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
|
||||
const xmlChar *ExternalID, const xmlChar *SystemID,
|
||||
const xmlChar *content) {
|
||||
xmlEntityPtr ret;
|
||||
xmlDtdPtr dtd;
|
||||
|
||||
if (doc == NULL) {
|
||||
xmlEntitiesErr(XML_DTD_NO_DOC,
|
||||
"xmlAddDocEntity: document is NULL");
|
||||
return(NULL);
|
||||
}
|
||||
if (doc->intSubset == NULL) {
|
||||
xmlEntitiesErr(XML_DTD_NO_DTD,
|
||||
"xmlAddDocEntity: document without internal subset");
|
||||
return(NULL);
|
||||
}
|
||||
dtd = doc->intSubset;
|
||||
ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
|
||||
if (ret == NULL) return(NULL);
|
||||
|
||||
/*
|
||||
* Link it to the DTD
|
||||
*/
|
||||
ret->parent = dtd;
|
||||
ret->doc = dtd->doc;
|
||||
if (dtd->last == NULL) {
|
||||
dtd->children = dtd->last = (xmlNodePtr) ret;
|
||||
} else {
|
||||
dtd->last->next = (xmlNodePtr) ret;
|
||||
ret->prev = dtd->last;
|
||||
dtd->last = (xmlNodePtr) ret;
|
||||
}
|
||||
xmlAddEntity(doc, 0, name, type, ExternalID, SystemID, content, &ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -438,21 +392,10 @@ xmlEntityPtr
|
||||
xmlNewEntity(xmlDocPtr doc, const xmlChar *name, int type,
|
||||
const xmlChar *ExternalID, const xmlChar *SystemID,
|
||||
const xmlChar *content) {
|
||||
xmlEntityPtr ret;
|
||||
xmlDictPtr dict;
|
||||
|
||||
if ((doc != NULL) && (doc->intSubset != NULL)) {
|
||||
return(xmlAddDocEntity(doc, name, type, ExternalID, SystemID, content));
|
||||
}
|
||||
if (doc != NULL)
|
||||
dict = doc->dict;
|
||||
else
|
||||
dict = NULL;
|
||||
ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content);
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
ret->doc = doc;
|
||||
return(ret);
|
||||
return(xmlCreateEntity(doc, name, type, ExternalID, SystemID, content));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -604,10 +547,8 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
|
||||
*/
|
||||
buffer_size = 1000;
|
||||
buffer = (xmlChar *) xmlMalloc(buffer_size);
|
||||
if (buffer == NULL) {
|
||||
xmlEntitiesErrMemory("xmlEncodeEntities: malloc failed");
|
||||
if (buffer == NULL)
|
||||
return(NULL);
|
||||
}
|
||||
out = buffer;
|
||||
|
||||
while (*cur != '\0') {
|
||||
@ -707,47 +648,12 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
|
||||
* cur[3] is 10xxxxxx if cur[0] is 1111xxxx
|
||||
* cur[0] is not 11111xxx
|
||||
*/
|
||||
char buf[11], *ptr;
|
||||
int val = 0, l = 1;
|
||||
char buf[13], *ptr;
|
||||
int val, l;
|
||||
|
||||
if (((cur[0] & 0xC0) != 0xC0) ||
|
||||
((cur[1] & 0xC0) != 0x80) ||
|
||||
(((cur[0] & 0xE0) == 0xE0) && ((cur[2] & 0xC0) != 0x80)) ||
|
||||
(((cur[0] & 0xF0) == 0xF0) && ((cur[3] & 0xC0) != 0x80)) ||
|
||||
(((cur[0] & 0xF8) == 0xF8))) {
|
||||
xmlEntitiesErr(XML_CHECK_NOT_UTF8,
|
||||
"xmlEncodeEntities: input not UTF-8");
|
||||
snprintf(buf, sizeof(buf), "&#%d;", *cur);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
ptr = buf;
|
||||
while (*ptr != 0) *out++ = *ptr++;
|
||||
cur++;
|
||||
continue;
|
||||
} else if (*cur < 0xE0) {
|
||||
val = (cur[0]) & 0x1F;
|
||||
val <<= 6;
|
||||
val |= (cur[1]) & 0x3F;
|
||||
l = 2;
|
||||
} else if (*cur < 0xF0) {
|
||||
val = (cur[0]) & 0x0F;
|
||||
val <<= 6;
|
||||
val |= (cur[1]) & 0x3F;
|
||||
val <<= 6;
|
||||
val |= (cur[2]) & 0x3F;
|
||||
l = 3;
|
||||
} else if (*cur < 0xF8) {
|
||||
val = (cur[0]) & 0x07;
|
||||
val <<= 6;
|
||||
val |= (cur[1]) & 0x3F;
|
||||
val <<= 6;
|
||||
val |= (cur[2]) & 0x3F;
|
||||
val <<= 6;
|
||||
val |= (cur[3]) & 0x3F;
|
||||
l = 4;
|
||||
}
|
||||
if ((l == 1) || (!IS_CHAR(val))) {
|
||||
xmlEntitiesErr(XML_ERR_INVALID_CHAR,
|
||||
"xmlEncodeEntities: char out of range\n");
|
||||
l = 4;
|
||||
val = xmlGetUTF8Char(cur, &l);
|
||||
if ((val < 0) || (!IS_CHAR(val))) {
|
||||
snprintf(buf, sizeof(buf), "&#%d;", *cur);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
ptr = buf;
|
||||
@ -779,7 +685,6 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
|
||||
return(buffer);
|
||||
|
||||
mem_error:
|
||||
xmlEntitiesErrMemory("xmlEncodeEntities: realloc failed");
|
||||
xmlFree(buffer);
|
||||
return(NULL);
|
||||
}
|
||||
@ -840,10 +745,8 @@ xmlEncodeSpecialChars(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlChar *input)
|
||||
*/
|
||||
buffer_size = 1000;
|
||||
buffer = (xmlChar *) xmlMalloc(buffer_size);
|
||||
if (buffer == NULL) {
|
||||
xmlEntitiesErrMemory("xmlEncodeSpecialChars: malloc failed");
|
||||
if (buffer == NULL)
|
||||
return(NULL);
|
||||
}
|
||||
out = buffer;
|
||||
|
||||
while (*cur != '\0') {
|
||||
@ -899,7 +802,6 @@ xmlEncodeSpecialChars(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlChar *input)
|
||||
return(buffer);
|
||||
|
||||
mem_error:
|
||||
xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
|
||||
xmlFree(buffer);
|
||||
return(NULL);
|
||||
}
|
||||
@ -956,27 +858,47 @@ xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
|
||||
xmlEntityPtr cur;
|
||||
|
||||
cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
|
||||
if (cur == NULL) {
|
||||
xmlEntitiesErrMemory("xmlCopyEntity:: malloc failed");
|
||||
if (cur == NULL)
|
||||
return(NULL);
|
||||
}
|
||||
memset(cur, 0, sizeof(xmlEntity));
|
||||
cur->type = XML_ENTITY_DECL;
|
||||
|
||||
cur->etype = ent->etype;
|
||||
if (ent->name != NULL)
|
||||
if (ent->name != NULL) {
|
||||
cur->name = xmlStrdup(ent->name);
|
||||
if (ent->ExternalID != NULL)
|
||||
if (cur->name == NULL)
|
||||
goto error;
|
||||
}
|
||||
if (ent->ExternalID != NULL) {
|
||||
cur->ExternalID = xmlStrdup(ent->ExternalID);
|
||||
if (ent->SystemID != NULL)
|
||||
if (cur->ExternalID == NULL)
|
||||
goto error;
|
||||
}
|
||||
if (ent->SystemID != NULL) {
|
||||
cur->SystemID = xmlStrdup(ent->SystemID);
|
||||
if (ent->content != NULL)
|
||||
if (cur->SystemID == NULL)
|
||||
goto error;
|
||||
}
|
||||
if (ent->content != NULL) {
|
||||
cur->content = xmlStrdup(ent->content);
|
||||
if (ent->orig != NULL)
|
||||
if (cur->content == NULL)
|
||||
goto error;
|
||||
}
|
||||
if (ent->orig != NULL) {
|
||||
cur->orig = xmlStrdup(ent->orig);
|
||||
if (ent->URI != NULL)
|
||||
if (cur->orig == NULL)
|
||||
goto error;
|
||||
}
|
||||
if (ent->URI != NULL) {
|
||||
cur->URI = xmlStrdup(ent->URI);
|
||||
if (cur->URI == NULL)
|
||||
goto error;
|
||||
}
|
||||
return(cur);
|
||||
|
||||
error:
|
||||
xmlFreeEntity(cur);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -989,7 +911,7 @@ xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
|
||||
*/
|
||||
xmlEntitiesTablePtr
|
||||
xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
|
||||
return(xmlHashCopy(table, xmlCopyEntity));
|
||||
return(xmlHashCopySafe(table, xmlCopyEntity, xmlFreeEntityWrapper));
|
||||
}
|
||||
#endif /* LIBXML_TREE_ENABLED */
|
||||
|
||||
@ -1116,8 +1038,7 @@ xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
|
||||
xmlBufferWriteChar(buf, ">\n");
|
||||
break;
|
||||
default:
|
||||
xmlEntitiesErr(XML_DTD_UNKNOWN_ENTITY,
|
||||
"xmlDumpEntitiesDecl: internal: unknown type entity type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,15 @@ XMLPUBFUN xmlEntityPtr
|
||||
const xmlChar *content);
|
||||
XMLPUBFUN void
|
||||
xmlFreeEntity (xmlEntityPtr entity);
|
||||
XMLPUBFUN int
|
||||
xmlAddEntity (xmlDocPtr doc,
|
||||
int extSubset,
|
||||
const xmlChar *name,
|
||||
int type,
|
||||
const xmlChar *ExternalID,
|
||||
const xmlChar *SystemID,
|
||||
const xmlChar *content,
|
||||
xmlEntityPtr *out);
|
||||
XMLPUBFUN xmlEntityPtr
|
||||
xmlAddDocEntity (xmlDocPtr doc,
|
||||
const xmlChar *name,
|
||||
|
@ -1 +0,0 @@
|
||||
warning : xmlAddEntity: invalid redeclaration of predefined entity 'lt'
|
@ -1 +0,0 @@
|
||||
warning : xmlAddEntity: invalid redeclaration of predefined entity 'lt'
|
@ -1 +0,0 @@
|
||||
warning : xmlAddEntity: invalid redeclaration of predefined entity 'lt'
|
Loading…
x
Reference in New Issue
Block a user