1
0
mirror of https://github.com/GNOME/libxml2.git synced 2025-10-14 02:58:39 +08:00

parser: Implement xmlCtxtGetInputWindow

See #762.
This commit is contained in:
Nick Wellnhofer
2025-07-22 23:57:03 +02:00
parent 469c847f4d
commit 8689523ad9
3 changed files with 129 additions and 2 deletions

View File

@@ -111,7 +111,11 @@ struct _xmlParserInput {
const char *directory XML_DEPRECATED_MEMBER;
/* Base of the array to parse */
const xmlChar *base;
/* Current char being parsed */
/**
* @deprecated Use #xmlCtxtGetInputWindow
*
* Current char being parsed
*/
const xmlChar *cur;
/* end of the array to parse */
const xmlChar *end;
@@ -1949,6 +1953,12 @@ XMLPUBFUN int
int *line,
int *col,
unsigned long *bytePos);
XMLPUBFUN int
xmlCtxtGetInputWindow (xmlParserCtxt *ctxt,
int inputIndex,
const xmlChar **startOut,
int *sizeInOut,
int *offsetOut);
XMLPUBFUN void
xmlCtxtSetErrorHandler (xmlParserCtxt *ctxt,
xmlStructuredErrorFunc handler,

View File

@@ -3436,13 +3436,60 @@ xmlCtxtGetInputPosition(xmlParserCtxt *ctxt, int inputIndex,
unsigned long consumed;
consumed = input->consumed;
xmlSaturatedAddSizeT(&consumed, input->end - input->base);
xmlSaturatedAddSizeT(&consumed, input->cur - input->base);
*utf8BytePos = consumed;
}
return 0;
}
/**
* Return window into input data.
*
* Should only be used by error handlers or SAX callbacks.
* The returned pointer is only valid until the callback returns.
*
* Because of entities, there can be multiple inputs. Non-negative
* values of `inputIndex` (0, 1, 2, ...) select inputs starting
* from the outermost input. Negative values (-1, -2, ...) select
* inputs starting from the innermost input.
*
* @since 2.15.0
*
* @param ctxt parser context
* @param inputIndex input index
* @param startOut start of window (output)
* @param sizeInOut maximum size of window (in)
* actual size of window (out)
* @param offsetOut offset of current position inside
* window (out)
* @returns 0 on success, -1 if arguments are invalid
*/
int
xmlCtxtGetInputWindow(xmlParserCtxt *ctxt, int inputIndex,
const xmlChar **startOut,
int *sizeInOut, int *offsetOut) {
xmlParserInput *input;
if (ctxt == NULL || startOut == NULL || sizeInOut == NULL ||
offsetOut == NULL)
return -1;
if (inputIndex < 0) {
inputIndex += ctxt->inputNr;
if (inputIndex < 0)
return -1;
}
if (inputIndex >= ctxt->inputNr)
return -1;
input = ctxt->inputTab[inputIndex];
xmlParserInputGetWindow(input, startOut, sizeInOut, offsetOut);
return 0;
}
/************************************************************************
* *
* Handling of node information *

View File

@@ -201,6 +201,75 @@ testInvalidCharRecovery(void) {
return err;
}
static void
testCtxtInputGetterError(void *errCtxt, const xmlError *error) {
int *err = errCtxt;
xmlParserCtxt *ctxt = error->ctxt;
const char *filename;
int line, col;
unsigned long bytePos;
const xmlChar *start;
int size, offset;
xmlCtxtGetInputPosition(ctxt, 0, &filename, &line, &col, &bytePos);
if (strcmp(filename, "test.xml") != 0 ||
line != 4 || col != 11 || bytePos != 62) {
fprintf(stderr, "unexpected position: %s %d %d %lu\n",
filename, line, col, bytePos);
*err = 1;
}
size = 80;
xmlCtxtGetInputWindow(ctxt, 0, &start, &size, &offset);
if (strncmp((char *) start, "<doc>&ent;", 10) != 0 ||
size != 16 || offset != 10) {
fprintf(stderr, "unexpected window: %.10s %d %d\n",
start, size, offset);
*err = 1;
}
xmlCtxtGetInputPosition(ctxt, -1, &filename, &line, &col, &bytePos);
if (filename != NULL ||
line != 1 || col != 11 || bytePos != 10) {
fprintf(stderr, "unexpected position: %s %d %d %lu\n",
filename, line, col, bytePos);
*err = 1;
}
size = 80;
xmlCtxtGetInputWindow(ctxt, -1, &start, &size, &offset);
if (strncmp((char *) start, "xxx &fail;", 10) != 0 ||
size != 14 || offset != 10) {
fprintf(stderr, "unexpected window: %.10s %d %d\n",
start, size, offset);
*err = 1;
}
}
static int
testCtxtInputGetters(void) {
const char *xml =
"<!DOCTYPE doc [\n"
" <!ENTITY ent 'xxx &fail; xxx'>\n"
"]>\n"
"<doc>&ent;</doc>\n";
xmlParserCtxt *ctxt;
xmlDoc *doc;
int err = 0;
ctxt = xmlNewParserCtxt();
xmlCtxtSetErrorHandler(ctxt, testCtxtInputGetterError, &err);
doc = xmlCtxtReadDoc(ctxt, BAD_CAST xml, "test.xml", NULL, 0);
xmlFreeDoc(doc);
xmlFreeParserCtxt(ctxt);
return err;
}
#ifdef LIBXML_VALID_ENABLED
static void
testSwitchDtdExtSubset(void *vctxt, const xmlChar *name ATTRIBUTE_UNUSED,
@@ -1428,6 +1497,7 @@ main(void) {
err |= testCFileIO();
err |= testUndeclEntInContent();
err |= testInvalidCharRecovery();
err |= testCtxtInputGetters();
#ifdef LIBXML_VALID_ENABLED
err |= testSwitchDtd();
#endif