From 5a31a4fb07d6f9f60e326da38a62255d86728fb4 Mon Sep 17 00:00:00 2001 From: Paul Fd Date: Wed, 10 Nov 2021 08:57:44 +0100 Subject: [PATCH] Update pugixml to v1.11 --- src/external/pugixml/src/pugiconfig.hpp | 9 ++- src/external/pugixml/src/pugixml.cpp | 96 +++++++++++++++++++++---- src/external/pugixml/src/pugixml.hpp | 25 ++++--- 3 files changed, 107 insertions(+), 23 deletions(-) diff --git a/src/external/pugixml/src/pugiconfig.hpp b/src/external/pugixml/src/pugiconfig.hpp index 2fb69180..405a66b6 100644 --- a/src/external/pugixml/src/pugiconfig.hpp +++ b/src/external/pugixml/src/pugiconfig.hpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.10 + * pugixml parser - version 1.11 * -------------------------------------------------------- - * Copyright (C) 2006-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -40,6 +40,9 @@ // #define PUGIXML_MEMORY_OUTPUT_STACK 10240 // #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 +// Tune this constant to adjust max nesting for XPath queries +// #define PUGIXML_XPATH_DEPTH_LIMIT 1024 + // Uncomment this to switch to header-only version // #define PUGIXML_HEADER_ONLY @@ -49,7 +52,7 @@ #endif /** - * Copyright (c) 2006-2019 Arseny Kapoulkine + * Copyright (c) 2006-2020 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/src/external/pugixml/src/pugixml.cpp b/src/external/pugixml/src/pugixml.cpp index c3df93b1..efdcdf69 100644 --- a/src/external/pugixml/src/pugixml.cpp +++ b/src/external/pugixml/src/pugixml.cpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.10 + * pugixml parser - version 1.11 * -------------------------------------------------------- - * Copyright (C) 2006-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -378,7 +378,7 @@ PUGI__NS_BEGIN static PUGI__UNSIGNED_OVERFLOW unsigned int hash(const void* key) { - unsigned int h = static_cast(reinterpret_cast(key)); + unsigned int h = static_cast(reinterpret_cast(key) & 0xffffffff); // MurmurHash3 32-bit finalizer h ^= h >> 16; @@ -4981,7 +4981,12 @@ PUGI__NS_BEGIN #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) { +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 + FILE* file = 0; + return _wfopen_s(&file, path, mode) == 0 ? file : 0; +#else return _wfopen(path, mode); +#endif } #else PUGI__FN char* convert_path_heap(const wchar_t* str) @@ -5025,6 +5030,16 @@ PUGI__NS_BEGIN } #endif + PUGI__FN FILE* open_file(const char* path, const char* mode) + { +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 + FILE* file = 0; + return fopen_s(&file, path, mode) == 0 ? file : 0; +#else + return fopen(path, mode); +#endif + } + PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) { if (!file) return false; @@ -6127,13 +6142,13 @@ namespace pugi impl::xml_allocator& alloc = impl::get_allocator(_root); if (!alloc.reserve()) return false; - for (xml_node_struct* child = _root->first_child; child; ) + for (xml_node_struct* cur = _root->first_child; cur; ) { - xml_node_struct* next = child->next_sibling; + xml_node_struct* next = cur->next_sibling; - impl::destroy_node(child, alloc); + impl::destroy_node(cur, alloc); - child = next; + cur = next; } _root->first_child = 0; @@ -7187,7 +7202,7 @@ namespace pugi reset(); using impl::auto_deleter; // MSVC7 workaround - auto_deleter file(fopen(path_, "rb"), impl::close_file); + auto_deleter file(impl::open_file(path_, "rb"), impl::close_file); return impl::load_file_impl(static_cast(_root), file.data, options, encoding, &_buffer); } @@ -7270,7 +7285,7 @@ namespace pugi PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const { using impl::auto_deleter; // MSVC7 workaround - auto_deleter file(fopen(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); + auto_deleter file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); return impl::save_file_impl(*this, file.data, indent, flags, encoding); } @@ -11143,6 +11158,14 @@ PUGI__NS_BEGIN } }; + static const size_t xpath_ast_depth_limit = + #ifdef PUGIXML_XPATH_DEPTH_LIMIT + PUGIXML_XPATH_DEPTH_LIMIT + #else + 1024 + #endif + ; + struct xpath_parser { xpath_allocator* _alloc; @@ -11155,6 +11178,8 @@ PUGI__NS_BEGIN char_t _scratch[32]; + size_t _depth; + xpath_ast_node* error(const char* message) { _result->error = message; @@ -11171,6 +11196,11 @@ PUGI__NS_BEGIN return 0; } + xpath_ast_node* error_rec() + { + return error("Exceeded maximum allowed query depth"); + } + void* alloc_node() { return _alloc->allocate(sizeof(xpath_ast_node)); @@ -11526,6 +11556,8 @@ PUGI__NS_BEGIN return error("Unrecognized function call"); _lexer.next(); + size_t old_depth = _depth; + while (_lexer.current() != lex_close_brace) { if (argc > 0) @@ -11535,6 +11567,9 @@ PUGI__NS_BEGIN _lexer.next(); } + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + xpath_ast_node* n = parse_expression(); if (!n) return 0; @@ -11547,6 +11582,8 @@ PUGI__NS_BEGIN _lexer.next(); + _depth = old_depth; + return parse_function(function, argc, args); } @@ -11563,10 +11600,15 @@ PUGI__NS_BEGIN xpath_ast_node* n = parse_primary_expression(); if (!n) return 0; + size_t old_depth = _depth; + while (_lexer.current() == lex_open_square_brace) { _lexer.next(); + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + if (n->rettype() != xpath_type_node_set) return error("Predicate has to be applied to node set"); @@ -11582,6 +11624,8 @@ PUGI__NS_BEGIN _lexer.next(); } + _depth = old_depth; + return n; } @@ -11733,12 +11777,17 @@ PUGI__NS_BEGIN xpath_ast_node* n = alloc_node(ast_step, set, axis, nt_type, nt_name_copy); if (!n) return 0; + size_t old_depth = _depth; + xpath_ast_node* last = 0; while (_lexer.current() == lex_open_square_brace) { _lexer.next(); + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + xpath_ast_node* expr = parse_expression(); if (!expr) return 0; @@ -11755,6 +11804,8 @@ PUGI__NS_BEGIN last = pred; } + _depth = old_depth; + return n; } @@ -11764,11 +11815,16 @@ PUGI__NS_BEGIN xpath_ast_node* n = parse_step(set); if (!n) return 0; + size_t old_depth = _depth; + while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) { lexeme_t l = _lexer.current(); _lexer.next(); + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + if (l == lex_double_slash) { n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); @@ -11779,6 +11835,8 @@ PUGI__NS_BEGIN if (!n) return 0; } + _depth = old_depth; + return n; } @@ -11964,6 +12022,9 @@ PUGI__NS_BEGIN { _lexer.next(); + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + xpath_ast_node* rhs = parse_path_or_unary_expression(); if (!rhs) return 0; @@ -12009,13 +12070,22 @@ PUGI__NS_BEGIN // | MultiplicativeExpr 'mod' UnaryExpr xpath_ast_node* parse_expression(int limit = 0) { + size_t old_depth = _depth; + + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + xpath_ast_node* n = parse_path_or_unary_expression(); if (!n) return 0; - return parse_expression_rec(n, limit); + n = parse_expression_rec(n, limit); + + _depth = old_depth; + + return n; } - xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result) + xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result), _depth(0) { } @@ -12024,6 +12094,8 @@ PUGI__NS_BEGIN xpath_ast_node* n = parse_expression(); if (!n) return 0; + assert(_depth == 0); + // check if there are unparsed tokens left if (_lexer.current() != lex_eof) return error("Incorrect query"); @@ -12923,7 +12995,7 @@ namespace pugi #endif /** - * Copyright (c) 2006-2019 Arseny Kapoulkine + * Copyright (c) 2006-2020 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/src/external/pugixml/src/pugixml.hpp b/src/external/pugixml/src/pugixml.hpp index f6581091..7e2ce777 100644 --- a/src/external/pugixml/src/pugixml.hpp +++ b/src/external/pugixml/src/pugixml.hpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.10 + * pugixml parser - version 1.11 * -------------------------------------------------------- - * Copyright (C) 2006-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end @@ -14,7 +14,7 @@ #ifndef PUGIXML_VERSION // Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons // Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits -# define PUGIXML_VERSION 1100 +# define PUGIXML_VERSION 1110 #endif // Include user configuration file (this can define various configuration macros) @@ -111,6 +111,15 @@ # endif #endif +// If C++ is 2011 or higher, use 'nullptr' +#ifndef PUGIXML_NULL +# if __cplusplus >= 201103 +# define PUGIXML_NULL nullptr +# else +# define PUGIXML_NULL 0 +# endif +#endif + // Character interface macros #ifdef PUGIXML_WCHAR_MODE # define PUGIXML_TEXT(t) L ## t @@ -661,15 +670,15 @@ namespace pugi #ifndef PUGIXML_NO_XPATH // Select single node by evaluating XPath query. Returns first node from the resulting node set. - xpath_node select_node(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node select_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; xpath_node select_node(const xpath_query& query) const; // Select node set by evaluating XPath query - xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; xpath_node_set select_nodes(const xpath_query& query) const; // (deprecated: use select_node instead) Select single node by evaluating XPath query. - PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const; + PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; PUGIXML_DEPRECATED xpath_node select_single_node(const xpath_query& query) const; #endif @@ -1212,7 +1221,7 @@ namespace pugi public: // Construct a compiled object from XPath expression. // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. - explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0); + explicit xpath_query(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL); // Constructor xpath_query(); @@ -1465,7 +1474,7 @@ namespace std #endif /** - * Copyright (c) 2006-2019 Arseny Kapoulkine + * Copyright (c) 2006-2020 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation