From 5bb0ea0c4b2ebebe542933f788ffacba459a717a Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Thu, 14 Dec 2023 14:40:04 +0100 Subject: [PATCH] Fix most urgent issues in 2023 - Fix recursion when resolving parents - Fix potential memory leak in `sass_not` - Fix potential NPE in selector list inspector --- src/ast_selectors.cpp | 14 ++++++++------ src/debugger.hpp | 1 + src/fn_miscs.cpp | 12 ++++++++---- src/inspect.cpp | 3 ++- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/ast_selectors.cpp b/src/ast_selectors.cpp index c142842975..f5a4867e9e 100644 --- a/src/ast_selectors.cpp +++ b/src/ast_selectors.cpp @@ -868,7 +868,7 @@ namespace Sass { for (SimpleSelectorObj simple : elements()) { if (PseudoSelector * pseudo = Cast(simple)) { if (SelectorList* sel = Cast(pseudo->selector())) { - if (parent) { + if (parent && !parent->has_real_parent_ref()) { pseudo->selector(sel->resolve_parent_refs( pstack, traces, implicit_parent)); } @@ -976,20 +976,22 @@ namespace Sass { } /* better return sass::vector? only - is empty container anyway? */ - SelectorList* ComplexSelector::resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent) + SelectorList* ComplexSelector::resolve_parent_refs( + SelectorStack pstack, Backtraces& traces, bool implicit_parent) { sass::vector> vars; auto parent = pstack.back(); + auto hasRealParent = has_real_parent_ref(); - if (has_real_parent_ref() && !parent) { + if (hasRealParent && !parent) { throw Exception::TopLevelParent(traces, pstate()); } if (!chroots() && parent) { - if (!has_real_parent_ref() && !implicit_parent) { + if (!hasRealParent && !implicit_parent) { SelectorList* retval = SASS_MEMORY_NEW(SelectorList, pstate(), 1); retval->append(this); return retval; @@ -1020,10 +1022,10 @@ namespace Sass { for (auto items : res) { if (items.size() > 0) { ComplexSelectorObj first = SASS_MEMORY_COPY(items[0]); - first->hasPreLineFeed(first->hasPreLineFeed() || (!has_real_parent_ref() && hasPreLineFeed())); + first->hasPreLineFeed(first->hasPreLineFeed() || (!hasRealParent && hasPreLineFeed())); // ToDo: remove once we know how to handle line feeds // ToDo: currently a mashup between ruby and dart sass - // if (has_real_parent_ref()) first->has_line_feed(false); + // if (hasRealParent) first->has_line_feed(false); // first->has_line_break(first->has_line_break() || has_line_break()); first->chroots(true); // has been resolved by now for (size_t i = 1; i < items.size(); i += 1) { diff --git a/src/debugger.hpp b/src/debugger.hpp index 703d387183..31af47218a 100644 --- a/src/debugger.hpp +++ b/src/debugger.hpp @@ -430,6 +430,7 @@ inline void debug_ast(AST_Node* node, sass::string ind, Env* env) std::cerr << " <<" << selector->ns_name() << ">>"; std::cerr << (selector->isClass() ? " [isClass]": " -"); std::cerr << (selector->isSyntacticClass() ? " [isSyntacticClass]": " -"); + std::cerr << (selector->has_real_parent_ref(nullptr) ? " [real parent]" : " -"); std::cerr << std::endl; debug_ast(selector->argument(), ind + " <= ", env); debug_ast(selector->selector(), ind + " || ", env); diff --git a/src/fn_miscs.cpp b/src/fn_miscs.cpp index 38e8d2a820..d5e28ca6c4 100644 --- a/src/fn_miscs.cpp +++ b/src/fn_miscs.cpp @@ -160,10 +160,14 @@ namespace Sass { ExpressionObj cond = ARG("$condition", Expression)->perform(&expand.eval); bool is_true = !cond->is_false(); ExpressionObj res = ARG(is_true ? "$if-true" : "$if-false", Expression); - ValueObj qwe = Cast(res->perform(&expand.eval)); - // res = res->perform(&expand.eval.val_eval); - qwe->set_delayed(false); // clone? - return qwe.detach(); + ExpressionObj rv = res->perform(&expand.eval); + ValueObj value = Cast(rv); + if (value != nullptr) { + value->set_delayed(false); + return value.detach(); + } + rv->set_delayed(false); + return nullptr; } ////////////////////////// diff --git a/src/inspect.cpp b/src/inspect.cpp index 4d079bed8b..bdc73cdac3 100644 --- a/src/inspect.cpp +++ b/src/inspect.cpp @@ -463,6 +463,7 @@ namespace Sass { { sep[0] = i % 2 ? ':' : ','; } ExpressionObj list_item = list->at(i); if (output_style() != TO_SASS) { + if (list_item == nullptr) continue; if (list_item->is_invisible()) { // this fixes an issue with "" in a list if (!Cast(list_item)) { @@ -1088,7 +1089,7 @@ namespace Sass { void Inspect::operator()(CompoundSelector* sel) { - if (sel->hasRealParent()) { + if (sel->hasRealParent() /* || sel->has_real_parent_ref() */) { append_string("&"); } for (auto& item : sel->elements()) {