1
0
mirror of https://github.com/GNOME/libxml2.git synced 2025-05-09 05:11:41 +08:00

xpath: Rewrite substring-before and substring-after

Don't use buffers. Check malloc failures.
This commit is contained in:
Nick Wellnhofer 2023-12-26 21:59:08 +01:00
parent 3874e5d0ea
commit b8313b589f
3 changed files with 69 additions and 42 deletions

View File

@ -143,6 +143,22 @@ Object is a string : 12
Expression: substring("12345",-5000000000,5000000004)
Object is a string : 123
========================
Expression: substring-after("12345678","345")
Object is a string : 678
========================
Expression: substring-after("12345678","999")
Object is a string :
========================
Expression: substring-before("12345678","345")
Object is a string : 12
========================
Expression: substring-before("12345678","999")
Object is a string :
========================
Expression: string-length("")
Object is a number : 0

View File

@ -34,6 +34,10 @@ substring("12345",-1 div 0, 1 div 0)
substring("12345",-1 div 0,5)
substring("12345",-0.7,4)
substring("12345",-5000000000,5000000004)
substring-after("12345678","345")
substring-after("12345678","999")
substring-before("12345678","345")
substring-before("12345678","999")
string-length("")
string-length("titi")
normalize-space(" abc def ")

91
xpath.c
View File

@ -8141,30 +8141,34 @@ xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
*/
void
xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr str;
xmlXPathObjectPtr find;
xmlBufPtr target;
const xmlChar *point;
int offset;
xmlXPathObjectPtr str = NULL;
xmlXPathObjectPtr find = NULL;
const xmlChar *point;
xmlChar *result;
CHECK_ARITY(2);
CAST_TO_STRING;
find = valuePop(ctxt);
CAST_TO_STRING;
str = valuePop(ctxt);
CHECK_ARITY(2);
CAST_TO_STRING;
find = valuePop(ctxt);
CAST_TO_STRING;
str = valuePop(ctxt);
if (ctxt->error != 0)
goto error;
target = xmlBufCreate();
if (target) {
point = xmlStrstr(str->stringval, find->stringval);
if (point) {
offset = point - str->stringval;
xmlBufAdd(target, str->stringval, offset);
if (point == NULL) {
result = xmlStrdup(BAD_CAST "");
} else {
result = xmlStrndup(str->stringval, point - str->stringval);
}
valuePush(ctxt, xmlXPathCacheNewString(ctxt, xmlBufContent(target)));
xmlBufFree(target);
}
xmlXPathReleaseObject(ctxt->context, str);
xmlXPathReleaseObject(ctxt->context, find);
if (result == NULL) {
xmlXPathPErrMemory(ctxt);
goto error;
}
valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
error:
xmlXPathReleaseObject(ctxt->context, str);
xmlXPathReleaseObject(ctxt->context, find);
}
/**
@ -8176,38 +8180,41 @@ xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
* string substring-after(string, string)
* The substring-after function returns the substring of the first
* argument string that follows the first occurrence of the second
* argument string in the first argument string, or the empty stringi
* argument string in the first argument string, or the empty string
* if the first argument string does not contain the second argument
* string. For example, substring-after("1999/04/01","/") returns 04/01,
* and substring-after("1999/04/01","19") returns 99/04/01.
*/
void
xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr str;
xmlXPathObjectPtr find;
xmlBufPtr target;
const xmlChar *point;
int offset;
xmlXPathObjectPtr str = NULL;
xmlXPathObjectPtr find = NULL;
const xmlChar *point;
xmlChar *result;
CHECK_ARITY(2);
CAST_TO_STRING;
find = valuePop(ctxt);
CAST_TO_STRING;
str = valuePop(ctxt);
CHECK_ARITY(2);
CAST_TO_STRING;
find = valuePop(ctxt);
CAST_TO_STRING;
str = valuePop(ctxt);
if (ctxt->error != 0)
goto error;
target = xmlBufCreate();
if (target) {
point = xmlStrstr(str->stringval, find->stringval);
if (point) {
offset = point - str->stringval + xmlStrlen(find->stringval);
xmlBufAdd(target, &str->stringval[offset],
xmlStrlen(str->stringval) - offset);
if (point == NULL) {
result = xmlStrdup(BAD_CAST "");
} else {
result = xmlStrdup(point + xmlStrlen(find->stringval));
}
valuePush(ctxt, xmlXPathCacheNewString(ctxt, xmlBufContent(target)));
xmlBufFree(target);
}
xmlXPathReleaseObject(ctxt->context, str);
xmlXPathReleaseObject(ctxt->context, find);
if (result == NULL) {
xmlXPathPErrMemory(ctxt);
goto error;
}
valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
error:
xmlXPathReleaseObject(ctxt->context, str);
xmlXPathReleaseObject(ctxt->context, find);
}
/**