| Index: lib/src/context.dart
|
| diff --git a/lib/src/context.dart b/lib/src/context.dart
|
| index b19aa71ee062bbe3c7f61fe95a7a2529c8e3e051..d10a29f148da84030400fb77cccfcdf4f7dcc431 100644
|
| --- a/lib/src/context.dart
|
| +++ b/lib/src/context.dart
|
| @@ -616,18 +616,63 @@ class Context {
|
| continue;
|
| }
|
|
|
| - // If a dot comes after a separator or another dot, it may be a
|
| - // directory traversal operator. Otherwise, it's just a normal
|
| - // non-matching character.
|
| - //
|
| - // isWithin("foo/./bar", "foo/bar/baz") //=> true
|
| - // isWithin("foo/bar/../baz", "foo/bar/.foo") //=> false
|
| - //
|
| - // We could stay on the fast path for "/./", but that adds a lot of
|
| - // complexity and isn't likely to come up much in practice.
|
| - if ((parentCodeUnit == chars.PERIOD || childCodeUnit == chars.PERIOD) &&
|
| - (style.isSeparator(lastCodeUnit) || lastCodeUnit == chars.PERIOD)) {
|
| - return null;
|
| + if (parentCodeUnit == chars.PERIOD) {
|
| + // If a dot comes after a separator, it may be a directory traversal
|
| + // operator. To check that, we need to know if it's followed by either
|
| + // "/" or "./". Otherwise, it's just a normal non-matching character.
|
| + //
|
| + // isWithin("foo/./bar", "foo/bar/baz") //=> true
|
| + // isWithin("foo/bar/../baz", "foo/bar/.foo") //=> false
|
| + if (style.isSeparator(lastCodeUnit)) {
|
| + parentIndex++;
|
| +
|
| + // We've hit "/." at the end of the parent path, which we can ignore,
|
| + // since the paths were equivalent up to this point.
|
| + if (parentIndex == parent.length) break;
|
| + parentCodeUnit = parentCodeUnits[parentIndex];
|
| +
|
| + // We've hit "/./", which we can ignore.
|
| + if (style.isSeparator(parentCodeUnit)) {
|
| + parentIndex++;
|
| + continue;
|
| + }
|
| +
|
| + // We've hit "/..", which may be a directory traversal operator that
|
| + // we can't handle on the fast track.
|
| + if (parentCodeUnit == chars.PERIOD) {
|
| + parentIndex++;
|
| + if (parentIndex == parent.length ||
|
| + style.isSeparator(parentCodeUnits[parentIndex])) {
|
| + return null;
|
| + }
|
| + }
|
| + }
|
| +
|
| + // If this isn't a directory traversal, fall through so we hit the
|
| + // normal handling for mismatched paths.
|
| + }
|
| +
|
| + // This is the same logic as above, but for the child path instead of the
|
| + // parent.
|
| + if (childCodeUnit == chars.PERIOD) {
|
| + if (style.isSeparator(lastCodeUnit)) {
|
| + childIndex++;
|
| + if (childIndex == child.length) break;
|
| + childCodeUnit = childCodeUnits[childIndex];
|
| +
|
| + if (style.isSeparator(childCodeUnit)) {
|
| + childIndex++;
|
| + continue;
|
| + }
|
| +
|
| + if (childCodeUnit == chars.PERIOD) {
|
| + childIndex++;
|
| + if (childIndex == child.length ||
|
| + style.isSeparator(childCodeUnits[childIndex])) {
|
| + return null;
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
| // If we're here, we've hit two non-matching, non-significant characters.
|
|
|