Paths where '..' is not right between separators are normalized.

R=brianwilkerson@google.com
BUG=

Review URL: https://codereview.chromium.org/1512363002 .
This commit is contained in:
Konstantin Shcheglov 2015-12-10 10:39:53 -08:00
parent 2956d5d69b
commit eb6da55838
2 changed files with 15 additions and 16 deletions

View file

@ -7,7 +7,6 @@ library analyzer.src.util.absolute_path;
/// The class for manipulating absolute, normalized paths.
class AbsolutePathContext {
static const int _COLON = 0x3A;
static const int _PERIOD = 0x2e;
static const int _LOWER_A = 0x61;
static const int _LOWER_Z = 0x7A;
static const int _UPPER_A = 0x41;
@ -16,10 +15,18 @@ class AbsolutePathContext {
final bool _isWindows;
String separator;
int _separatorChar;
String _singlePeriodComponent;
String _doublePeriodComponent;
String _singlePeriodEnding;
String _doublePeriodEnding;
AbsolutePathContext(this._isWindows) {
separator = _isWindows ? r'\' : '/';
_separatorChar = separator.codeUnitAt(0);
_singlePeriodComponent = separator + '.' + separator;
_doublePeriodComponent = separator + '..' + separator;
_singlePeriodEnding = separator + '.';
_doublePeriodEnding = separator + '..';
}
/// Append the given relative [suffix] to the given absolute [parent].
@ -125,29 +132,19 @@ class AbsolutePathContext {
}
}
/// Return `true` if the given absolute [path] is normalized.
///
/// _isNormalized('/foo/bar'); // -> true
/// _isNormalized('/foo/..bar'); // -> true
/// _isNormalized('/foo/bar..'); // -> true
/// _isNormalized('/'); // -> true
/// _isNormalized('/foo/bar/../baz'); // -> false
/// _isNormalized('/foo/bar/..'); // -> false
bool _isNormalized(String path) {
int periodCount = 0;
for (int c in path.codeUnits) {
if (c == _PERIOD) {
periodCount++;
continue;
}
if (c == _separatorChar) {
if (periodCount == 1 || periodCount == 2) {
return false;
}
}
periodCount = 0;
}
return periodCount != 1 && periodCount != 2;
return !path.contains(_singlePeriodComponent) &&
!path.contains(_doublePeriodComponent) &&
!path.endsWith(_singlePeriodEnding) &&
!path.endsWith(_doublePeriodEnding);
}
/// Returns whether [char] is the code for an ASCII letter (uppercase or

View file

@ -51,6 +51,7 @@ class AbsolutePathContextPosixTest {
expect(context.isValid(r'/foo/..bar'), isTrue);
expect(context.isValid(r'/foo/.bar/baz'), isTrue);
expect(context.isValid(r'/foo/...'), isTrue);
expect(context.isValid(r'/foo/bar..'), isTrue);
expect(context.isValid(r'/foo/.../bar'), isTrue);
expect(context.isValid(r'/foo/.bar/.'), isFalse);
expect(context.isValid(r'/foo/bar/../baz'), isFalse);
@ -113,6 +114,7 @@ class AbsolutePathContextWindowsTest {
expect(context.isValid(r'C:\foo\..bar'), isTrue);
expect(context.isValid(r'C:\foo\.bar\baz'), isTrue);
expect(context.isValid(r'C:\foo\...'), isTrue);
expect(context.isValid(r'C:\foo\bar..'), isTrue);
expect(context.isValid(r'C:\foo\...\bar'), isTrue);
expect(context.isValid(r'C:\foo\.bar\.'), isFalse);
expect(context.isValid(r'C:\foo\bar\..\baz'), isFalse);