Improved handling of XML parser errors

This commit is contained in:
Takeshi Nakatani
2025-10-13 03:50:08 +00:00
committed by Andrew Gaul
parent a9b9631c5c
commit 52b263b99c
3 changed files with 56 additions and 1 deletions

View File

@ -3597,9 +3597,16 @@ static int list_bucket(const char* path, S3ObjList& head, const char* delimiter,
}
// xmlDocPtr
s3fsXmlBufferParserError parserError;
parserError.SetXmlParseError();
std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> doc(xmlReadMemory(encbody.c_str(), static_cast<int>(encbody.size()), "", nullptr, 0), xmlFreeDoc);
if(nullptr == doc){
S3FS_PRN_ERR("xmlReadMemory returns with error.");
if(parserError.IsXmlParseError()){
S3FS_PRN_ERR("xmlReadMemory returns with error: %s", parserError.GetXmlParseError().c_str());
}else{
S3FS_PRN_ERR("xmlReadMemory returns with error.");
}
return -EIO;
}
if(0 != append_objects_from_xml(path, doc.get(), head)){

View File

@ -461,8 +461,16 @@ bool simple_parse_xml(const char* data, size_t len, const char* key, std::string
// ":1: parser error : Document is empty" to stderr.
// Make sure len is not 0 beforehand.
//
s3fsXmlBufferParserError parserError;
parserError.SetXmlParseError();
std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> doc(xmlReadMemory(data, static_cast<int>(len), "", nullptr, 0), xmlFreeDoc);
if(nullptr == doc){
if(parserError.IsXmlParseError()){
S3FS_PRN_ERR("xmlReadMemory returns with error: %s", parserError.GetXmlParseError().c_str());
}else{
S3FS_PRN_ERR("xmlReadMemory returns with error.");
}
return false;
}

View File

@ -25,6 +25,8 @@
#include <libxml/parser.h> // [NOTE] nessetially include this header in some environments
#include <memory>
#include <string>
#include <array>
#include <cstring>
#include "mpu_util.h"
@ -35,6 +37,44 @@ typedef std::unique_ptr<xmlXPathObject, decltype(&xmlXPathFreeObject)> unique_pt
typedef std::unique_ptr<xmlXPathContext, decltype(&xmlXPathFreeContext)> unique_ptr_xmlXPathContext;
typedef std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> unique_ptr_xmlDoc;
//-------------------------------------------------------------------
// Utility Class
//-------------------------------------------------------------------
class s3fsXmlBufferParserError
{
private:
static constexpr int ERROR_BUFFER_SIZE = 1024;
std::array<char, ERROR_BUFFER_SIZE> error_buffer{};
static void ParserErrorHandler(void* ctx, const char *msg, ...)
{
auto* errbuf = static_cast<char*>(ctx);
if(errbuf){
va_list args;
va_start(args, msg);
vsnprintf(errbuf + strlen(errbuf), ERROR_BUFFER_SIZE - strlen(errbuf) - 1, msg, args);
va_end(args);
}
}
public:
void SetXmlParseError()
{
error_buffer.fill(0);
xmlSetGenericErrorFunc(error_buffer.data(), s3fsXmlBufferParserError::ParserErrorHandler);
}
std::string GetXmlParseError() const
{
return strlen(error_buffer.data()) ? error_buffer.data() : "";
}
bool IsXmlParseError() const
{
return (0 < strlen(error_buffer.data()));
}
};
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------