Skip to content

Commit 406f4ec

Browse files
authored
Merge pull request #5678 from MartinNowak/merge_stable
Merge remote-tracking branch 'upstream/stable' into merge_stable
2 parents 81e921b + deb28da commit 406f4ec

File tree

4 files changed

+86
-18
lines changed

4 files changed

+86
-18
lines changed

std/functional.d

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ $(TR $(TH Function Name) $(TH Description)
1515
$(TD Joins a couple of functions into one that executes the original
1616
functions independently and returns a tuple with all the results.
1717
))
18-
$(TR $(TD $(LREF compose)), $(LREF pipe)
18+
$(TR $(TD $(LREF compose), $(LREF pipe))
1919
$(TD Join a couple of functions into one that executes the original
2020
functions one after the other, using one function's result for the next
2121
function's argument.
2222
))
2323
$(TR $(TD $(LREF forward))
2424
$(TD Forwards function arguments while saving ref-ness.
2525
))
26-
$(TR $(TD $(LREF lessThan)), $(LREF greaterThan)), $(D $(LREF equalTo)
26+
$(TR $(TD $(LREF lessThan), $(LREF greaterThan), $(LREF equalTo))
2727
$(TD Ready-made predicate functions to compare two values.
2828
))
2929
$(TR $(TD $(LREF memoize))
@@ -36,13 +36,13 @@ $(TR $(TH Function Name) $(TH Description)
3636
$(TD Creates a function that binds the first argument of a given function
3737
to a given value.
3838
))
39-
$(TR $(TD $(LREF reverseArgs)), $(LREF binaryReverseArgs)
39+
$(TR $(TD $(LREF reverseArgs), $(LREF binaryReverseArgs))
4040
$(TD Predicate that reverses the order of its arguments.
4141
))
4242
$(TR $(TD $(LREF toDelegate))
4343
$(TD Converts a callable to a delegate.
4444
))
45-
$(TR $(TD $(LREF unaryFun)), $(LREF binaryFun)
45+
$(TR $(TD $(LREF unaryFun), $(LREF binaryFun))
4646
$(TD Create a unary or binary function from a string. Most often
4747
used when defining algorithms on ranges.
4848
))

std/regex/internal/parser.d

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,8 @@ if (isForwardRange!R && is(ElementType!R : dchar))
11821182
state = State.Start;
11831183
break;
11841184
default:
1185+
if (current >= privateUseStart && current <= privateUseEnd)
1186+
enforce(false, "no matching ']' found while parsing character class");
11851187
enforce(false, "invalid escape sequence");
11861188
}
11871189
break;
@@ -1256,8 +1258,17 @@ if (isForwardRange!R && is(ElementType!R : dchar))
12561258
end = parseUniHex(pat, 8);
12571259
break;
12581260
default:
1261+
if (current >= privateUseStart && current <= privateUseEnd)
1262+
enforce(false, "no matching ']' found while parsing character class");
12591263
error("invalid escape sequence");
12601264
}
1265+
// Lookahead to check if it's a \T
1266+
// where T is sub-pattern terminator in multi-pattern scheme
1267+
if (end == '\\' && !pat.empty)
1268+
{
1269+
if (pat.front >= privateUseStart && pat.front <= privateUseEnd)
1270+
enforce(false, "invalid escape sequence");
1271+
}
12611272
enforce(last <= end,"inverted range");
12621273
set.add(last, end + 1);
12631274
state = State.Start;
@@ -1293,6 +1304,7 @@ if (isForwardRange!R && is(ElementType!R : dchar))
12931304
switch (op)
12941305
{
12951306
case Operator.Negate:
1307+
enforce(!stack.empty, "no operand for '^'");
12961308
stack.top = stack.top.inverted;
12971309
break;
12981310
case Operator.Union:
@@ -1364,8 +1376,7 @@ if (isForwardRange!R && is(ElementType!R : dchar))
13641376
"character class syntax error");
13651377
enforce(!opstack.empty, "unmatched ']'");
13661378
opstack.pop();
1367-
next();
1368-
if (opstack.empty)
1379+
if (!next() || opstack.empty)
13691380
break L_CharsetLoop;
13701381
auto pair = parseCharTerm();
13711382
if (!pair[0].empty)//not only operator e.g. -- or ~~
@@ -1390,10 +1401,13 @@ if (isForwardRange!R && is(ElementType!R : dchar))
13901401
}
13911402
vstack.push(pair[0]);
13921403
}
1393-
13941404
}while (!empty || !opstack.empty);
13951405
while (!opstack.empty)
1396-
apply(opstack.pop(),vstack);
1406+
{
1407+
enforce(opstack.top != Operator.Open,
1408+
"no matching ']' found while parsing character class");
1409+
apply(opstack.pop(), vstack);
1410+
}
13971411
assert(vstack.length == 1);
13981412
g.charsetToIr(vstack.top);
13991413
}
@@ -1483,6 +1497,13 @@ if (isForwardRange!R && is(ElementType!R : dchar))
14831497
g.markBackref(nref);
14841498
break;
14851499
default:
1500+
// Lookahead to check if it's a \T
1501+
// where T is sub-pattern terminator in multi-pattern scheme
1502+
if (current == '\\' && !pat.empty)
1503+
{
1504+
if (pat.front >= privateUseStart && current <= privateUseEnd)
1505+
enforce(false, "invalid escape sequence");
1506+
}
14861507
if (current >= privateUseStart && current <= privateUseEnd)
14871508
{
14881509
g.endPattern(current - privateUseStart + 1);

std/regex/internal/tests.d

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,3 +1082,27 @@ alias Sequence(int B, int E) = staticIota!(B, E);
10821082
assert(equal!equal(s.matchAll(ctr), outcomes));
10831083
assert(equal!equal(s.bmatch(r), outcomes));
10841084
}
1085+
1086+
// bugzilla 17667
1087+
@safe unittest
1088+
{
1089+
import std.algorithm.searching : canFind;
1090+
void willThrow(T)(T arg, string msg)
1091+
{
1092+
auto e = collectException(regex(arg));
1093+
assert(e.msg.canFind(msg), e.msg);
1094+
}
1095+
willThrow([r".", r"[\(\{[\]\}\)]"], "no matching ']' found while parsing character class");
1096+
willThrow([r"[\", r"123"], "no matching ']' found while parsing character class");
1097+
willThrow([r"[a-", r"123"], "no matching ']' found while parsing character class");
1098+
willThrow([r"[a-\", r"123"], "invalid escape sequence");
1099+
willThrow([r"\", r"123"], "invalid escape sequence");
1100+
}
1101+
1102+
// bugzilla 17668
1103+
@safe unittest
1104+
{
1105+
import std.algorithm.searching;
1106+
auto e = collectException!RegexException(regex(q"<[^]>"));
1107+
assert(e.msg.canFind("no operand for '^'"));
1108+
}

std/traits.d

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,20 +1262,32 @@ If a parameter doesn't have the default value, $(D void) is returned instead.
12621262
template ParameterDefaults(func...)
12631263
if (func.length == 1 && isCallable!func)
12641264
{
1265+
alias param_names = ParameterIdentifierTuple!func;
12651266
static if (is(FunctionTypeOf!(func[0]) PT == __parameters))
12661267
{
12671268
template Get(size_t i)
12681269
{
1269-
// workaround scope escape check, see
1270-
// https://issues.dlang.org/show_bug.cgi?id=16582
1271-
// should use return scope once available
1272-
enum get = (PT[i .. i+1] __args) @trusted
1273-
{
1274-
// If __args[0] is lazy, we force it to be evaluated like this.
1275-
PT[i] __pd_value = __args[0];
1276-
PT[i]* __pd_val = &__pd_value; // workaround Bugzilla 16582
1277-
return *__pd_val;
1278-
};
1270+
// `PT[i .. i+1]` declares a parameter with an arbitrary name.
1271+
// To avoid a name clash, generate local names that are distinct
1272+
// from the parameter name, and mix them in.
1273+
enum name = param_names[i];
1274+
enum args = "args" ~ (name == "args" ? "_" : "");
1275+
enum val = "val" ~ (name == "val" ? "_" : "");
1276+
enum ptr = "ptr" ~ (name == "ptr" ? "_" : "");
1277+
mixin("
1278+
// workaround scope escape check, see
1279+
// https://issues.dlang.org/show_bug.cgi?id=16582
1280+
// should use return scope once available
1281+
enum get = (PT[i .. i+1] " ~ args ~ ") @trusted
1282+
{
1283+
// If the parameter is lazy, we force it to be evaluated
1284+
// like this.
1285+
auto " ~ val ~ " = " ~ args ~ "[0];
1286+
auto " ~ ptr ~ " = &" ~ val ~ ";
1287+
// workaround Bugzilla 16582
1288+
return *" ~ ptr ~ ";
1289+
};
1290+
");
12791291
static if (is(typeof(get())))
12801292
enum Get = get();
12811293
else
@@ -1313,6 +1325,17 @@ template ParameterDefaults(func...)
13131325
static assert( ParameterDefaults!foo[3] == 0);
13141326
}
13151327

1328+
@safe unittest // issue 17192
1329+
{
1330+
static void func(int i, int PT, int __pd_value, int __pd_val, int __args,
1331+
int name, int args, int val, int ptr, int args_, int val_, int ptr_)
1332+
{
1333+
}
1334+
alias Voids = ParameterDefaults!func;
1335+
static assert(Voids.length == 12);
1336+
foreach (V; Voids) static assert(is(V == void));
1337+
}
1338+
13161339
/**
13171340
* Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility.
13181341
*/

0 commit comments

Comments
 (0)