From 228c7aaaa0e08d957a7948cc62acf1e7160e1ca3 Mon Sep 17 00:00:00 2001 From: ehofman Date: Mon, 27 Apr 2009 16:54:46 +0000 Subject: [PATCH] * add xmlInitBuffer() for processing of a preallocated buffer * add xmlErrorGetColumnNo to get the column number of the syntax error * pass an error at a higher level to lower levels * detect a number of extra syntax errors --- utils/xmlgrep/ChangeLog | 7 +++ utils/xmlgrep/README | 63 ++++++++++--------- utils/xmlgrep/xml.c | 132 +++++++++++++++++++++++++++++++--------- utils/xmlgrep/xml.h | 19 ++++++ utils/xmlgrep/xmlgrep.c | 3 +- 5 files changed, 165 insertions(+), 59 deletions(-) diff --git a/utils/xmlgrep/ChangeLog b/utils/xmlgrep/ChangeLog index 9d10d5f9d..47dd69e4f 100644 --- a/utils/xmlgrep/ChangeLog +++ b/utils/xmlgrep/ChangeLog @@ -1,3 +1,10 @@ +27-04-2009 + * add xmlInitBuffer() for processing of a preallocated buffer + * add xmlErrorGetColumnNo to get the column number of the syntax error + * pass an error at a higher level to lower levels + * detect a number of extra syntax errors + * fix a buffer overflow + 26-04-2009 * add support for comments inside xml-tags, e.g.: diff --git a/utils/xmlgrep/README b/utils/xmlgrep/README index 5d2fde2e9..33294ffbd 100644 --- a/utils/xmlgrep/README +++ b/utils/xmlgrep/README @@ -47,22 +47,23 @@ Overview of the available functions: # id = xmlOpen("/tmp/file.xml"); # xmlClose(id); # -void *xmlOpen(const char *); -void xmlClose(const void *); +void *xmlOpen(const char *filename); +void *xmlInitBuffer(const char *buffer, size_t size); +void xmlClose(void *xid); # # Get the Id of a node at the specified path # e.g. # xnid = xmlNodeGet(id, "/path/to/specified/node"); # -void *xmlNodeGet(const void *, const char *); -void *xmlNodeCopy(void *, const char *); +void *xmlNodeGet(const void *xid, const char *path); +void *xmlNodeCopy(const void *xid, const char *path); # # Functions to walk the node tree and process them one by one. # e.g. # xmid = xmlMarkId(id); -# num = xmlNodeGetNum(xmid); +# num = xmlNodeGetNum(xmid, "node"); # for (i=0; i /* free, malloc */ #include +#ifndef _MSC_VER +#include /* strncasecmp */ +#else +# define strncasecmp strnicmp +#endif #include #include #include #include #include -#ifndef _MSC_VER -# include /* strncasecmp */ -#else -# define strncasecmp strnicmp -#endif #ifndef XML_NONVALIDATING #include "xml.h" @@ -172,6 +172,25 @@ xmlOpen(const char *filename) return (void *)rid; } +void * +xmlInitBuffer(const char *buffer, size_t size) +{ + struct _root_id *rid = 0; + + if (buffer && (size>0)) + { + rid->fd = 0; + rid->start = (char *)buffer; + rid->len = size; + rid->name = 0; +#ifndef XML_NONVALIDATING + rid->info = 0; +#endif + } + + return (void *)rid; +} + void xmlClose(void *id) { @@ -180,8 +199,11 @@ xmlClose(void *id) assert(rid != 0); assert(rid->name == 0); - munmap(rid->start, rid->len); - close(rid->fd); + if (rid->fd) + { + munmap(rid->start, rid->len); + close(rid->fd); + } if (rid->info) free(rid->info); free(rid); @@ -1183,12 +1205,9 @@ xmlErrorGetLineNo(const void *id, int clear) while (pserr_no = 0; @@ -1198,6 +1217,45 @@ xmlErrorGetLineNo(const void *id, int clear) return ret; } +size_t +xmlErrorGetColumnNo(const void *id, int clear) +{ + size_t ret = 0; + + if (id) + { + struct _xml_id *xid = (struct _xml_id *)id; + struct _root_id *rid; + + if (xid->name) rid = xid->root; + else rid = (struct _root_id *)xid; + + assert(rid != 0); + + if (rid->info) + { + struct _xml_error *err = rid->info; + char *ps = rid->start; + char *pe = err->pos; + char *new; + + while (pserr_no = 0; + } + } + + return ret; +} + const char * xmlErrorGetString(const void *id, int clear) { @@ -1334,8 +1392,8 @@ __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *plen) char * __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum) { + char *element, *open, *start_tag=0; char *new, *cur, *ne, *ret = 0; - char *element, *start_tag=0; size_t restlen, elementlen; size_t return_len = 0; int found, num; @@ -1412,6 +1470,7 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t * /* * get element name and a pointer to after the opening tag */ + open = cur; element = *name; elementlen = *rlen; len_remaining = restlen; @@ -1514,6 +1573,14 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t * new = __xmlNodeGet(cur-1, &slen, &node, &nlen, &pos); if (!new) { + if (nlen == 0) /* error upstream */ + { + *rlen = nlen; + *name = node; + *len = slen; + return 0; + } + if (slen == restlen) { *rlen = 0; @@ -1557,24 +1624,31 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t * if (found == num) { - if (start_tag) - { - *len = new-ret-1; - *name = start_tag; - } - else /* report error */ - { - *rlen = 0; - *name = new; - *len = XML_ELEMENT_NO_OPENING_TAG; - return 0; - } + if (start_tag) + { + *len = new-ret-1; + *name = start_tag; + } + else /* report error */ + { + *rlen = 0; + *name = new; + *len = XML_ELEMENT_NO_OPENING_TAG; + return 0; + } } found++; } - /* else proper closing tag not yet found, continue. */ - /* TODO: could be a bad match to the opening tag though */ - /* like: */ +#ifndef XML_NONVALIDATING + /* strcmp is a heavy operation when not required */ + else if (strncmp(open, new+1, elementlen)) + { + *rlen = 0; + *name = new+1; + *len = XML_ELEMENT_NO_CLOSING_TAG; + return 0; + } +#endif new = memchr(cur, '>', restlen); if (!new) diff --git a/utils/xmlgrep/xml.h b/utils/xmlgrep/xml.h index 5602f50b9..88b233df7 100644 --- a/utils/xmlgrep/xml.h +++ b/utils/xmlgrep/xml.h @@ -52,6 +52,16 @@ enum */ void *xmlOpen(const char *); +/** + * Process a section of XML code in a preallocated buffer. + * The buffer may not be free'd until xmlClose has been called. + * + * @param buffer pointer to the buffer + * @param size size of the buffer + * @return XML-id which is used for further processing + */ +void *xmlInitBuffer(const char *, size_t); + /** * Close the XML file after which no further processing is possible. * @@ -329,6 +339,15 @@ int xmlErrorGetNo(const void *, int); */ size_t xmlErrorGetLineNo(const void *, int); +/** + * Get the column number of the last detected syntax error in the xml file. + * + * @param xid XML-id + * @param clear clear the error state if non zero + * @return the line number of the detected syntax error. + */ +size_t xmlErrorGetColumnNo(const void *, int); + /** * Get a string that explains the last error. * diff --git a/utils/xmlgrep/xmlgrep.c b/utils/xmlgrep/xmlgrep.c index f163620e1..b428504b2 100644 --- a/utils/xmlgrep/xmlgrep.c +++ b/utils/xmlgrep/xmlgrep.c @@ -323,8 +323,9 @@ void grep_file(unsigned num) if (r) { size_t n = xmlErrorGetLineNo(xrid, 0); + size_t c = xmlErrorGetColumnNo(xrid, 0); char *s = xmlErrorGetString(xrid, 1); /* clear the error */ - printf("%s: at line %u: '%s'\n",_filenames[num], n, s); + printf("%s: at line %u, column %u: '%s'\n",_filenames[num], n,c, s); } free(xrid);