From 7e694a8fb887e6946800d7fe55874bd20e88c478 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 8 Aug 2019 14:21:24 +0200 Subject: [PATCH] Workaround for invalid access inside some character classification table when parsing localized file names by the PlaceholderParser: UTF8 characters were handled as chars, and the negative char values were used as indices into 7bit long tables. --- src/libslic3r/PlaceholderParser.cpp | 39 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index c3ac22e96..530d84907 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -175,6 +175,11 @@ void PlaceholderParser::apply_env_variables() } namespace spirit = boost::spirit; +// Using an encoding, which accepts unsigned chars. +// Don't use boost::spirit::ascii, as it crashes internally due to indexing with negative char values for UTF8 characters into some 7bit character classification tables. +//namespace spirit_encoding = boost::spirit::ascii; +//FIXME iso8859_1 is just a workaround for the problem above. Replace it with UTF8 support! +namespace spirit_encoding = boost::spirit::iso8859_1; namespace qi = boost::spirit::qi; namespace px = boost::phoenix; @@ -931,7 +936,7 @@ namespace client /////////////////////////////////////////////////////////////////////////// // Inspired by the C grammar rules https://www.lysator.liu.se/c/ANSI-C-grammar-y.html template - struct macro_processor : qi::grammar, spirit::ascii::space_type> + struct macro_processor : qi::grammar, spirit_encoding::space_type> { macro_processor() : macro_processor::base_type(start) { @@ -944,12 +949,12 @@ namespace client qi::lexeme_type lexeme; qi::no_skip_type no_skip; qi::real_parser strict_double; - spirit::ascii::char_type char_; + spirit_encoding::char_type char_; utf8_char_skipper_parser utf8char; spirit::bool_type bool_; spirit::int_type int_; spirit::double_type double_; - spirit::ascii::string_type string; + spirit_encoding::string_type string; spirit::eoi_type eoi; spirit::repository::qi::iter_pos_type iter_pos; auto kw = spirit::repository::qi::distinct(qi::copy(alnum | '_')); @@ -1178,20 +1183,20 @@ namespace client } // Generic expression over expr. - typedef qi::rule(const MyContext*), spirit::ascii::space_type> RuleExpression; + typedef qi::rule(const MyContext*), spirit_encoding::space_type> RuleExpression; // The start of the grammar. - qi::rule, spirit::ascii::space_type> start; + qi::rule, spirit_encoding::space_type> start; // A free-form text. - qi::rule text; + qi::rule text; // A free-form text, possibly empty, possibly containing macro expansions. - qi::rule text_block; + qi::rule text_block; // Statements enclosed in curely braces {} - qi::rule macro; + qi::rule macro; // Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index]. - qi::rule legacy_variable_expansion; + qi::rule legacy_variable_expansion; // Parsed identifier name. - qi::rule(), spirit::ascii::space_type> identifier; + qi::rule(), spirit_encoding::space_type> identifier; // Ternary operator (?:) over logical_or_expression. RuleExpression conditional_expression; // Logical or over logical_and_expressions. @@ -1209,16 +1214,16 @@ namespace client // Number literals, functions, braced expressions, variable references, variable indexing references. RuleExpression unary_expression; // Rule to capture a regular expression enclosed in //. - qi::rule(), spirit::ascii::space_type> regular_expression; + qi::rule(), spirit_encoding::space_type> regular_expression; // Evaluate boolean expression into bool. - qi::rule bool_expr_eval; + qi::rule bool_expr_eval; // Reference of a scalar variable, or reference to a field of a vector variable. - qi::rule(const MyContext*), qi::locals, int>, spirit::ascii::space_type> scalar_variable_reference; + qi::rule(const MyContext*), qi::locals, int>, spirit_encoding::space_type> scalar_variable_reference; // Rule to translate an identifier to a ConfigOption, or to fail. - qi::rule(const MyContext*), spirit::ascii::space_type> variable_reference; + qi::rule(const MyContext*), spirit_encoding::space_type> variable_reference; - qi::rule, spirit::ascii::space_type> if_else_output; -// qi::rule, bool, std::string>, spirit::ascii::space_type> switch_output; + qi::rule, spirit_encoding::space_type> if_else_output; +// qi::rule, bool, std::string>, spirit_encoding::space_type> switch_output; qi::symbols keywords; }; @@ -1230,7 +1235,7 @@ static std::string process_macro(const std::string &templ, client::MyContext &co typedef client::macro_processor macro_processor; // Our whitespace skipper. - spirit::ascii::space_type space; + spirit_encoding::space_type space; // Our grammar, statically allocated inside the method, meaning it will be allocated the first time // PlaceholderParser::process() runs. //FIXME this kind of initialization is not thread safe!