Skip to content

Commit f6afdbb

Browse files
authored
Merge pull request #3156 from mgreter/feature/harden-endless-extend
Fix extend edge case going endlessly
2 parents f158280 + 8f1a5d9 commit f6afdbb

7 files changed

+34
-7
lines changed

src/ast_helpers.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ namespace Sass {
6161
// Implement compare and hashing operations for AST Nodes
6262
// ###########################################################################
6363

64-
// TODO: get rid of funtions and use ObjEquality<T>
64+
// TODO: get rid of functions and use ObjEquality<T>
6565

6666
template <class T>
6767
// Hash the raw pointer instead of object

src/ast_sel_unify.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace Sass {
2020
SASS_ASSERT(!complexes.empty(), "Can't unify empty list");
2121
if (complexes.size() == 1) return complexes;
2222

23-
CompoundSelectorObj unifiedBase = SASS_MEMORY_NEW(CompoundSelector, SourceSpan("[phony]"));
23+
CompoundSelectorObj unifiedBase = SASS_MEMORY_NEW(CompoundSelector, SourceSpan("[unify]"));
2424
for (auto complex : complexes) {
2525
SelectorComponentObj base = complex.back();
2626
if (CompoundSelector * comp = base->getCompound()) {

src/error_handling.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ namespace Sass {
8484
msg = "stack level too deep";
8585
}
8686

87+
EndlessExtendError::EndlessExtendError(Backtraces traces, const AST_Node& node)
88+
: Base(node.pstate(), def_msg, traces), node(node)
89+
{
90+
msg = "Extend is creating an absurdly big selector, aborting!";
91+
}
92+
8793
IncompatibleUnits::IncompatibleUnits(const Units& lhs, const Units& rhs)
8894
{
8995
msg = "Incompatible units: '" + rhs.unit() + "' and '" + lhs.unit() + "'.";

src/error_handling.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ namespace Sass {
134134
virtual ~StackError() throw() {};
135135
};
136136

137+
class EndlessExtendError : public Base {
138+
protected:
139+
const AST_Node& node;
140+
public:
141+
EndlessExtendError(Backtraces traces, const AST_Node& node);
142+
virtual const char* errtype() const { return "EndlessExtendError"; }
143+
virtual ~EndlessExtendError() throw() {};
144+
};
145+
137146
/* common virtual base class (has no pstate or trace) */
138147
class OperationError : public std::runtime_error {
139148
protected:

src/extender.cpp

+15-4
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ namespace Sass {
626626

627627
for (sass::vector<SelectorComponentObj>& components : weaved) {
628628

629-
ComplexSelectorObj cplx = SASS_MEMORY_NEW(ComplexSelector, "[phony]");
629+
ComplexSelectorObj cplx = SASS_MEMORY_NEW(ComplexSelector, complex->pstate());
630630
cplx->hasPreLineFeed(complex->hasPreLineFeed());
631631
for (auto& pp : path) {
632632
if (pp->hasPreLineFeed()) {
@@ -643,7 +643,18 @@ namespace Sass {
643643
}
644644
first = false;
645645

646-
result.push_back(cplx);
646+
auto it = result.begin();
647+
while (it != result.end()) {
648+
if (ObjEqualityFn(*it, cplx)) break;
649+
it += 1;
650+
}
651+
if (it == result.end()) {
652+
result.push_back(cplx);
653+
}
654+
655+
if (result.size() > 500) {
656+
throw Exception::EndlessExtendError(traces, complex);
657+
}
647658

648659
}
649660

@@ -838,7 +849,7 @@ namespace Sass {
838849
}
839850
if (!originals.empty()) {
840851
CompoundSelectorObj merged =
841-
SASS_MEMORY_NEW(CompoundSelector, "[phony]");
852+
SASS_MEMORY_NEW(CompoundSelector, "[compound]");
842853
merged->concat(originals);
843854
toUnify.insert(toUnify.begin(), { merged });
844855
}
@@ -1050,7 +1061,7 @@ namespace Sass {
10501061
}
10511062
}
10521063

1053-
SelectorListObj list = SASS_MEMORY_NEW(SelectorList, "[phony]");
1064+
SelectorListObj list = SASS_MEMORY_NEW(SelectorList, "[pseudo]");
10541065
list->concat(expanded);
10551066
return { pseudo->withSelector(list) };
10561067

src/fn_selectors.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ namespace Sass {
9696

9797
for (auto& complex : sel->elements()) {
9898
if (complex->empty()) {
99-
complex->append(SASS_MEMORY_NEW(CompoundSelector, "[phony]"));
99+
complex->append(SASS_MEMORY_NEW(CompoundSelector, "[append]"));
100100
}
101101
if (CompoundSelector* comp = Cast<CompoundSelector>(complex->first())) {
102102
comp->hasRealParent(true);

src/sass_context.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ namespace Sass {
7777
// now create the code trace (ToDo: maybe have util functions?)
7878
if (e.pstate.position.line != sass::string::npos &&
7979
e.pstate.position.column != sass::string::npos &&
80+
e.pstate.getRawData() != nullptr &&
8081
e.pstate.source != nullptr) {
8182
Offset offset(e.pstate.position);
8283
size_t lines = offset.line;

0 commit comments

Comments
 (0)