Skip to content

Commit 6769ca0

Browse files
committed
Merge pull request #1861 from mgreter/bugfix/error-check-in-for-loop
Improve lower/upper boundary check error in `for` loop
2 parents 1472b4e + fe26ff7 commit 6769ca0

File tree

4 files changed

+34
-17
lines changed

4 files changed

+34
-17
lines changed

src/error_handling.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ namespace Sass {
8181
msg += ").";
8282
}
8383

84+
TypeMismatch::TypeMismatch(const Expression& var, const std::string type)
85+
: var(var), type(type)
86+
{
87+
msg = var.to_string();
88+
msg += " is not an ";
89+
msg += type;
90+
msg += ".";
91+
}
92+
8493
InvalidValue::InvalidValue(const Expression& val)
8594
: Base(val.pstate()), val(val)
8695
{

src/error_handling.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ namespace Sass {
9696
virtual ~DuplicateKeyError() throw() {};
9797
};
9898

99+
class TypeMismatch : public OperationError {
100+
protected:
101+
const Expression& var;
102+
const std::string type;
103+
public:
104+
TypeMismatch(const Expression& var, const std::string type);
105+
virtual const char* errtype() const { return "TypeMismatch"; }
106+
virtual ~TypeMismatch() throw() {};
107+
};
108+
99109
class InvalidValue : public Base {
100110
protected:
101111
const Expression& val;

src/eval.cpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,11 @@ namespace Sass {
159159
std::string variable(f->variable());
160160
Expression* low = f->lower_bound()->perform(this);
161161
if (low->concrete_type() != Expression::NUMBER) {
162-
error("lower bound of `@for` directive must be numeric", low->pstate());
162+
throw Exception::TypeMismatch(*low, "integer");
163163
}
164164
Expression* high = f->upper_bound()->perform(this);
165165
if (high->concrete_type() != Expression::NUMBER) {
166-
error("upper bound of `@for` directive must be numeric", high->pstate());
166+
throw Exception::TypeMismatch(*high, "integer");
167167
}
168168
Number* sass_start = static_cast<Number*>(low);
169169
Number* sass_end = static_cast<Number*>(high);
@@ -268,6 +268,7 @@ namespace Sass {
268268
Expression* var = scalars;
269269
env.set_local(variables[0], var);
270270
} else {
271+
// XXX: this is never hit via spec tests
271272
for (size_t j = 0, K = variables.size(); j < K; ++j) {
272273
Expression* res = j >= scalars->length()
273274
? SASS_MEMORY_NEW(ctx.mem, Null, expr->pstate())
@@ -279,6 +280,7 @@ namespace Sass {
279280
if (variables.size() > 0) {
280281
env.set_local(variables[0], e);
281282
for (size_t j = 1, K = variables.size(); j < K; ++j) {
283+
// XXX: this is never hit via spec tests
282284
Expression* res = SASS_MEMORY_NEW(ctx.mem, Null, expr->pstate());
283285
env.set_local(variables[j], res);
284286
}
@@ -683,6 +685,7 @@ namespace Sass {
683685
Textual* front = dynamic_cast<Textual*>(s2->elements().front());
684686
if (front && !front->is_interpolant())
685687
{
688+
// XXX: this is never hit via spec tests
686689
schema_op = true;
687690
rhs = front->perform(this);
688691
}
@@ -781,6 +784,7 @@ namespace Sass {
781784

782785
if (rv) {
783786
if (schema_op) {
787+
// XXX: this is never hit via spec tests
784788
(*s2)[0] = rv;
785789
rv = s2->perform(this);
786790
}
@@ -823,6 +827,7 @@ namespace Sass {
823827
Expression* Eval::operator()(Function_Call* c)
824828
{
825829
if (backtrace()->parent != NULL && backtrace()->depth() > Constants::MaxCallStack) {
830+
// XXX: this is never hit via spec tests
826831
std::ostringstream stm;
827832
stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
828833
error(stm.str(), c->pstate(), backtrace());
@@ -1079,18 +1084,6 @@ namespace Sass {
10791084
return b;
10801085
}
10811086

1082-
char is_quoted(std::string str)
1083-
{
1084-
size_t len = str.length();
1085-
if (len < 2) return 0;
1086-
if ((str[0] == '"' && str[len-1] == '"') || (str[0] == '\'' && str[len-1] == '\'')) {
1087-
return str[0];
1088-
}
1089-
else {
1090-
return 0;
1091-
}
1092-
}
1093-
10941087
void Eval::interpolation(Context& ctx, std::string& res, Expression* ex, bool into_quotes, bool was_itpl) {
10951088

10961089
bool needs_closing_brace = false;
@@ -1113,7 +1106,7 @@ namespace Sass {
11131106
if (Argument* arg = dynamic_cast<Argument*>(ex)) {
11141107
ex = arg->value();
11151108
}
1116-
if (String_Constant* sq = dynamic_cast<String_Quoted*>(ex)) {
1109+
if (String_Quoted* sq = dynamic_cast<String_Quoted*>(ex)) {
11171110
if (was_itpl) {
11181111
bool was_interpolant = ex->is_interpolant();
11191112
ex = SASS_MEMORY_NEW(ctx.mem, String_Constant, sq->pstate(), sq->value());
@@ -1125,6 +1118,7 @@ namespace Sass {
11251118

11261119
// parent selector needs another go
11271120
if (dynamic_cast<Parent_Selector*>(ex)) {
1121+
// XXX: this is never hit via spec tests
11281122
ex = ex->perform(this);
11291123
}
11301124

@@ -1300,6 +1294,7 @@ namespace Sass {
13001294
Expression* value = e->value();
13011295
value = (value ? value->perform(this) : 0);
13021296
if (value && dynamic_cast<String_Quoted*>(value)) {
1297+
// XXX: this is never hit via spec tests
13031298
value = SASS_MEMORY_NEW(ctx.mem, String_Quoted,
13041299
value->pstate(),
13051300
dynamic_cast<String_Quoted*>(value)->value());
@@ -1432,9 +1427,11 @@ namespace Sass {
14321427
double lv = l.value();
14331428
double rv = r.value();
14341429
if (op == Sass_OP::DIV && rv == 0) {
1430+
// XXX: this is never hit via spec tests
14351431
return SASS_MEMORY_NEW(mem, String_Quoted, pstate ? *pstate : l.pstate(), lv ? "Infinity" : "NaN");
14361432
}
14371433
if (op == Sass_OP::MOD && !rv) {
1434+
// XXX: this is never hit via spec tests
14381435
throw Exception::ZeroDivisionError(l, r);
14391436
}
14401437

@@ -1687,6 +1684,7 @@ namespace Sass {
16871684

16881685
}
16891686

1687+
// XXX: this is never hit via spec tests
16901688
Attribute_Selector* Eval::operator()(Attribute_Selector* s)
16911689
{
16921690
String* attr = s->value();

src/expand.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,11 +397,11 @@ namespace Sass {
397397
std::string variable(f->variable());
398398
Expression* low = f->lower_bound()->perform(&eval);
399399
if (low->concrete_type() != Expression::NUMBER) {
400-
error("lower bound of `@for` directive must be numeric", low->pstate(), backtrace());
400+
throw Exception::TypeMismatch(*low, "integer");
401401
}
402402
Expression* high = f->upper_bound()->perform(&eval);
403403
if (high->concrete_type() != Expression::NUMBER) {
404-
error("upper bound of `@for` directive must be numeric", high->pstate(), backtrace());
404+
throw Exception::TypeMismatch(*high, "integer");
405405
}
406406
Number* sass_start = static_cast<Number*>(low);
407407
Number* sass_end = static_cast<Number*>(high);

0 commit comments

Comments
 (0)