Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:42.3:Update
libsass
7664114-Implement-nesting-guard-to-avoid-out-of...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 7664114-Implement-nesting-guard-to-avoid-out-of-stack-space.patch of Package libsass
From 7664114543757e932f5b1a2ff5295aa9b34f8623 Mon Sep 17 00:00:00 2001 From: Marcel Greter <marcel.greter@ocbnet.ch> Date: Tue, 11 Jul 2017 20:47:26 +0200 Subject: [PATCH] Implement nesting guard to avoid "out of stack space" Note that this limit is not an exact science it depends on various factors, which some are not under our control (compile time or even OS dependent settings on the available stack size) It should fix most common segfault cases though. --- src/ast_def_macros.hpp | 5 +++++ src/error_handling.cpp | 4 ++++ src/error_handling.hpp | 7 +++++++ src/parser.cpp | 15 +++++++++++++++ src/parser.hpp | 14 ++++++++++++-- 5 files changed, 43 insertions(+), 2 deletions(-) Index: libsass-3.3.2/src/ast_def_macros.hpp =================================================================== --- libsass-3.3.2.orig/src/ast_def_macros.hpp +++ libsass-3.3.2/src/ast_def_macros.hpp @@ -25,6 +25,11 @@ class LocalOption { }; #define LOCAL_FLAG(name,opt) LocalOption<bool> flag_##name(name, opt) +#define LOCAL_COUNT(name,opt) LocalOption<size_t> cnt_##name(name, opt) + +#define NESTING_GUARD(name) \ + LocalOption<size_t> cnt_##name(name, name + 1); \ + if (nestings > MAX_NESTING) throw Exception::NestingLimitError(pstate); \ #define ATTACH_OPERATIONS()\ virtual void perform(Operation<void>* op) { (*op)(this); }\ Index: libsass-3.3.2/src/error_handling.cpp =================================================================== --- libsass-3.3.2.orig/src/error_handling.cpp +++ libsass-3.3.2/src/error_handling.cpp @@ -49,6 +49,10 @@ namespace Sass { : Base(pstate, msg, import_stack) { } + NestingLimitError::NestingLimitError(ParserState pstate, std::string msg, std::vector<Sass_Import_Entry>* import_stack) + : Base(pstate, msg, import_stack) + { } + } Index: libsass-3.3.2/src/error_handling.hpp =================================================================== --- libsass-3.3.2.orig/src/error_handling.hpp +++ libsass-3.3.2/src/error_handling.hpp @@ -13,6 +13,7 @@ namespace Sass { namespace Exception { const std::string def_msg = "Invalid sass"; + const std::string def_nesting_limit = "Code too deeply neested"; class Base : public std::runtime_error { protected: @@ -58,6 +59,12 @@ namespace Sass { virtual ~InvalidSyntax() throw() {}; }; + class NestingLimitError : public Base { + public: + NestingLimitError(ParserState pstate, std::string msg = def_nesting_limit, std::vector<Sass_Import_Entry>* import_stack = 0); + virtual ~NestingLimitError() throw() {}; + }; + } void warn(std::string msg, ParserState pstate); Index: libsass-3.3.2/src/parser.cpp =================================================================== --- libsass-3.3.2.orig/src/parser.cpp +++ libsass-3.3.2/src/parser.cpp @@ -466,6 +466,7 @@ namespace Sass { // a ruleset connects a selector and a block Ruleset* Parser::parse_ruleset(Lookahead lookahead, bool is_root) { + NESTING_GUARD(nestings); // make sure to move up the the last position lex < optional_css_whitespace >(false, true); // create the connector object (add parts later) @@ -489,6 +490,7 @@ namespace Sass { // in the eval stage we will be re-parse it into an actual selector Selector_Schema* Parser::parse_selector_schema(const char* end_of_selector) { + NESTING_GUARD(nestings); // move up to the start lex< optional_spaces >(); const char* i = position; @@ -578,6 +580,7 @@ namespace Sass { { bool reloop = true; bool had_linefeed = false; + NESTING_GUARD(nestings); Complex_Selector* sel = 0; To_String to_string(&ctx); Selector_List* group = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate); @@ -630,6 +633,7 @@ namespace Sass { Complex_Selector* Parser::parse_complex_selector(bool in_root) { + NESTING_GUARD(nestings); String* reference = 0; lex < block_comment >(); // parse the left hand side @@ -970,6 +974,7 @@ namespace Sass { Expression* Parser::parse_map() { + NESTING_GUARD(nestings); Expression* key = parse_list(); Map* map = SASS_MEMORY_NEW(ctx.mem, Map, pstate, 1); if (String_Quoted* str = dynamic_cast<String_Quoted*>(key)) { @@ -1032,12 +1037,14 @@ namespace Sass { Expression* Parser::parse_list() { // parse list is relly just an alias + NESTING_GUARD(nestings); return parse_comma_list(); } // will return singletons unwrapped Expression* Parser::parse_comma_list() { + NESTING_GUARD(nestings); // check if we have an empty list // return the empty list as such if (peek_css< alternatives < @@ -1088,6 +1095,7 @@ namespace Sass { // will return singletons unwrapped Expression* Parser::parse_space_list() { + NESTING_GUARD(nestings); Expression* disj1 = parse_disjunction(); // if it's a singleton, return it (don't wrap it) if (peek_css< alternatives < @@ -1131,6 +1139,7 @@ namespace Sass { // parse logical OR operation Expression* Parser::parse_disjunction() { + NESTING_GUARD(nestings); // parse the left hand side conjunction Expression* conj = parse_conjunction(); // parse multiple right hand sides @@ -1147,6 +1156,7 @@ namespace Sass { // parse logical AND operation Expression* Parser::parse_conjunction() { + NESTING_GUARD(nestings); // parse the left hand side relation Expression* rel = parse_relation(); // parse multiple right hand sides @@ -1163,6 +1173,7 @@ namespace Sass { // parse comparison operations Expression* Parser::parse_relation() { + NESTING_GUARD(nestings); // parse the left hand side expression Expression* lhs = parse_expression(); // if it's a singleton, return it (don't wrap it) @@ -1199,6 +1210,7 @@ namespace Sass { // parse addition and subtraction operations Expression* Parser::parse_expression() { + NESTING_GUARD(nestings); Expression* lhs = parse_operators(); // if it's a singleton, return it (don't wrap it) if (!(peek< exactly<'+'> >(position) || @@ -1222,6 +1234,7 @@ namespace Sass { // parse addition and subtraction operations Expression* Parser::parse_operators() { + NESTING_GUARD(nestings); Expression* factor = parse_factor(); // Special case: Ruby sass never tries to modulo if the lhs contains an interpolant if (peek_css< exactly<'%'> >() && factor->concrete_type() == Expression::STRING) { @@ -1253,6 +1266,7 @@ namespace Sass { // called from parse_value_schema Expression* Parser::parse_factor() { + NESTING_GUARD(nestings); lex < css_comments >(false); if (lex_css< exactly<'('> >()) { // parse_map may return a list Index: libsass-3.3.2/src/parser.hpp =================================================================== --- libsass-3.3.2.orig/src/parser.hpp +++ libsass-3.3.2/src/parser.hpp @@ -10,6 +10,15 @@ #include "position.hpp" #include "prelexer.hpp" +#ifndef MAX_NESTING +// Note that this limit is not an exact science +// it depends on various factors, which some are +// not under our control (compile time or even OS +// dependent settings on the available stack size) +// It should fix most common segfault cases though. +#define MAX_NESTING 512 +#endif + struct Lookahead { const char* found; const char* error; @@ -35,7 +44,8 @@ namespace Sass { Position before_token; Position after_token; ParserState pstate; - int indentation; + size_t indentation; + size_t nestings; Token lexed; @@ -43,7 +53,7 @@ namespace Sass { Parser(Context& ctx, const ParserState& pstate) : ParserState(pstate), ctx(ctx), block_stack(0), stack(0), last_media_block(0), - source(0), position(0), end(0), before_token(pstate), after_token(pstate), pstate(pstate), indentation(0) + source(0), position(0), end(0), before_token(pstate), after_token(pstate), pstate(pstate), indentation(0), nestings(0) { in_at_root = false; stack.push_back(nothing); } // static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]"));
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor