mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-07-19 13:45:58 +02:00
LazUtils: Resolve '/somedir/..' correctly in ResolveDots. Add tests. Issue #40678.
(cherry picked from commit 148b2d23f4
)
This commit is contained in:
parent
7c62769d75
commit
9835b964fb
@ -21,14 +21,13 @@ function ResolveDots(const AFilename: string): string;
|
|||||||
Result:=false;
|
Result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var SrcPos, DestPos, Len, DirStart: integer;
|
var
|
||||||
|
SrcPos, DestPos, Len, DirStart: integer;
|
||||||
c: char;
|
c: char;
|
||||||
MacroPos: LongInt;
|
MacroPos: LongInt;
|
||||||
ResultMustEndWithPathDelim: Boolean;
|
|
||||||
begin
|
begin
|
||||||
Len:=length(AFilename);
|
Len:=length(AFilename);
|
||||||
if Len=0 then exit('');
|
if Len=0 then exit('');
|
||||||
|
|
||||||
Result:=AFilename;
|
Result:=AFilename;
|
||||||
|
|
||||||
{$ifdef windows}
|
{$ifdef windows}
|
||||||
@ -38,13 +37,6 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
//To add some consistency to the outcomes
|
|
||||||
//Depending on the path the algorithm takes it may remove the trailing PathDelim, so we restore it later if needed
|
|
||||||
//Issue #37188
|
|
||||||
//It's a workaround, fee free to implement a better fix
|
|
||||||
ResultMustEndWithPathDelim := ((Len>2) and (AFilename[Len]='.') and (AFilename[Len-1]='.') and (AFilename[Len-2] in AllowDirectorySeparators)) or
|
|
||||||
((Len>1) and (AFilename[Len]='.') and (AFilename[Len-1] in AllowDirectorySeparators));
|
|
||||||
|
|
||||||
SrcPos:=1;
|
SrcPos:=1;
|
||||||
DestPos:=1;
|
DestPos:=1;
|
||||||
|
|
||||||
@ -76,8 +68,7 @@ begin
|
|||||||
if (SrcPos<Len) then begin
|
if (SrcPos<Len) then begin
|
||||||
if (AFilename[SrcPos+1] in AllowDirectorySeparators)
|
if (AFilename[SrcPos+1] in AllowDirectorySeparators)
|
||||||
and IsPathDelim(Result,DestPos-1) then begin
|
and IsPathDelim(Result,DestPos-1) then begin
|
||||||
// special dir ./ or */./
|
// special dir ./ or */./ -> skip
|
||||||
// -> skip
|
|
||||||
inc(SrcPos,2);
|
inc(SrcPos,2);
|
||||||
while (SrcPos<=Len) and (AFilename[SrcPos] in AllowDirectorySeparators) do
|
while (SrcPos<=Len) and (AFilename[SrcPos] in AllowDirectorySeparators) do
|
||||||
inc(SrcPos);
|
inc(SrcPos);
|
||||||
@ -145,12 +136,8 @@ begin
|
|||||||
//writeln('ResolveDots ',DestPos,' SrcPos=',SrcPos,' File="',AFilename,'" Result="',copy(Result,1,DestPos-1),'"');
|
//writeln('ResolveDots ',DestPos,' SrcPos=',SrcPos,' File="',AFilename,'" Result="',copy(Result,1,DestPos-1),'"');
|
||||||
if SrcPos>Len then begin
|
if SrcPos>Len then begin
|
||||||
// '..' at end of filename
|
// '..' at end of filename
|
||||||
if (DestPos>1) and (Result[DestPos-1]=PathDelim) then begin
|
if (DestPos=1) then begin
|
||||||
// foo/dir/.. -> foo
|
Result[1]:='.'; // foo/.. -> .
|
||||||
dec(DestPos);
|
|
||||||
end else if (DestPos=1) then begin
|
|
||||||
// foo/.. -> .
|
|
||||||
Result[1]:='.';
|
|
||||||
DestPos:=2;
|
DestPos:=2;
|
||||||
end;
|
end;
|
||||||
end else if DestPos=1 then begin
|
end else if DestPos=1 then begin
|
||||||
@ -165,20 +152,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
// special dir . at end of filename
|
// special dir . at end of filename
|
||||||
if DestPos=1 then begin
|
if DestPos=1 then
|
||||||
Result:='.';
|
exit('.');
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
if (DestPos>2) and (Result[DestPos-1]=PathDelim)
|
|
||||||
{$ifdef windows}
|
|
||||||
and not IsDriveDelim(Result,DestPos-2)
|
|
||||||
{$endif}
|
|
||||||
then begin
|
|
||||||
// foo/. -> foo
|
|
||||||
// C:foo\. -> C:foo
|
|
||||||
// C:\. -> C:\
|
|
||||||
{dec(DestPos); } //Part of issue #37188
|
|
||||||
end;
|
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -198,12 +173,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
// trim result
|
// trim result
|
||||||
if DestPos<=length(AFilename) then
|
if DestPos<=length(AFilename) then
|
||||||
if (DestPos=1) then
|
if DestPos=1 then
|
||||||
Result:='.'
|
Result:='.'
|
||||||
else
|
else
|
||||||
SetLength(Result,DestPos-1);
|
SetLength(Result,DestPos-1);
|
||||||
if ResultMustEndWithPathDelim and (Result<>'.') and (Result[Length(Result)]<>PathDelim) then
|
|
||||||
Result := Result + PathDelim;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function FilenameIsWinAbsolute(const TheFilename: string): boolean;
|
function FilenameIsWinAbsolute(const TheFilename: string): boolean;
|
||||||
|
@ -63,7 +63,7 @@ begin
|
|||||||
t('..','..');
|
t('..','..');
|
||||||
t('bla/..','.');
|
t('bla/..','.');
|
||||||
t('bla//..','.');
|
t('bla//..','.');
|
||||||
t('foo/bla//..','foo');
|
t('foo/bla//..','foo/');
|
||||||
t('bla/../','.');
|
t('bla/../','.');
|
||||||
t('bla//..//','.');
|
t('bla//..//','.');
|
||||||
t('foo/../bar','bar');
|
t('foo/../bar','bar');
|
||||||
@ -82,6 +82,8 @@ begin
|
|||||||
t('.//.//.','.');
|
t('.//.//.','.');
|
||||||
t('foo/bar/./../too','foo/too');
|
t('foo/bar/./../too','foo/too');
|
||||||
t('foo//bar//.//..//too','foo/too');
|
t('foo//bar//.//..//too','foo/too');
|
||||||
|
t('/bla/..','/');
|
||||||
|
t('/..','/');
|
||||||
{$IFDEF Unix}
|
{$IFDEF Unix}
|
||||||
t('/.','/');
|
t('/.','/');
|
||||||
t('//.','/');
|
t('//.','/');
|
||||||
@ -142,10 +144,12 @@ begin
|
|||||||
DoTest('a/../b','b');
|
DoTest('a/../b','b');
|
||||||
DoTest('a/b/../c','a/c');
|
DoTest('a/b/../c','a/c');
|
||||||
DoTest('a/b/../../c','c');
|
DoTest('a/b/../../c','c');
|
||||||
|
DoTest('a/b/c/../..','a/');
|
||||||
DoTest('a/./b','a/b');
|
DoTest('a/./b','a/b');
|
||||||
DoTest('a/.//b','a/b');
|
DoTest('a/.//b','a/b');
|
||||||
DoTest('a//b','a/b');
|
DoTest('a//b','a/b');
|
||||||
DoTest('a//./b','a/b');
|
DoTest('a//./b','a/b');
|
||||||
|
DoTest('/a/b/../..','/');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestLazFileUtils.TestCreateRelativePath;
|
procedure TTestLazFileUtils.TestCreateRelativePath;
|
||||||
|
@ -178,6 +178,11 @@
|
|||||||
<StackChecks Value="True"/>
|
<StackChecks Value="True"/>
|
||||||
</Checks>
|
</Checks>
|
||||||
</CodeGeneration>
|
</CodeGeneration>
|
||||||
|
<Linking>
|
||||||
|
<Debugging>
|
||||||
|
<DebugInfoType Value="dsDwarf3"/>
|
||||||
|
</Debugging>
|
||||||
|
</Linking>
|
||||||
<Other>
|
<Other>
|
||||||
<CustomOptions Value="-dNoSemiAutomatedTests"/>
|
<CustomOptions Value="-dNoSemiAutomatedTests"/>
|
||||||
</Other>
|
</Other>
|
||||||
|
Loading…
Reference in New Issue
Block a user