|
@@ -47,7 +47,8 @@ function PathStrScan(const S: PChar; const C: Char): PChar;
|
|
function RemoveBackslash(const S: String): String;
|
|
function RemoveBackslash(const S: String): String;
|
|
function RemoveBackslashUnlessRoot(const S: String): String;
|
|
function RemoveBackslashUnlessRoot(const S: String): String;
|
|
function ValidateAndCombinePath(const ADestDir, AFilename: String;
|
|
function ValidateAndCombinePath(const ADestDir, AFilename: String;
|
|
- out AResultingPath: String): Boolean;
|
|
|
|
|
|
+ out AResultingPath: String): Boolean; overload;
|
|
|
|
+function ValidateAndCombinePath(const ADestDir, AFilename: String): Boolean; overload;
|
|
|
|
|
|
implementation
|
|
implementation
|
|
|
|
|
|
@@ -611,7 +612,8 @@ function ValidateAndCombinePath(const ADestDir, AFilename: String;
|
|
Returns True if all security checks pass, with the combination of ADestDir
|
|
Returns True if all security checks pass, with the combination of ADestDir
|
|
and AFilename in AResultingPath.
|
|
and AFilename in AResultingPath.
|
|
ADestDir is assumed to be normalized already and have a trailing backslash.
|
|
ADestDir is assumed to be normalized already and have a trailing backslash.
|
|
- AFilename may be a file or directory name. }
|
|
|
|
|
|
+ AFilename may be a file or directory name.
|
|
|
|
+ If ADestDir is empty then only AFilename is checked. }
|
|
begin
|
|
begin
|
|
{ - Don't allow empty names
|
|
{ - Don't allow empty names
|
|
- Don't allow forward slashes or repeated slashes
|
|
- Don't allow forward slashes or repeated slashes
|
|
@@ -624,21 +626,30 @@ begin
|
|
not PathIsRooted(AFilename) and
|
|
not PathIsRooted(AFilename) and
|
|
not PathCharIsSlash(AFilename[High(AFilename)]) and
|
|
not PathCharIsSlash(AFilename[High(AFilename)]) and
|
|
not PathHasInvalidCharacters(AFilename, False) then begin
|
|
not PathHasInvalidCharacters(AFilename, False) then begin
|
|
- { Our validity checks passed. Now pass the combined path to PathExpand
|
|
|
|
- (GetFullPathName) to see if it thinks the path needs normalization.
|
|
|
|
- If the returned path isn't exactly what was passed in, then consider
|
|
|
|
- the name invalid.
|
|
|
|
- One way that can happen is if the path ends in an MS-DOS device name:
|
|
|
|
- PathExpand('c:\path\NUL') returns '\\.\NUL'. Obviously we don't want
|
|
|
|
- devices being opened, so that must be rejected. }
|
|
|
|
- var CombinedPath := ADestDir + AFilename;
|
|
|
|
- var TestExpandedPath: String;
|
|
|
|
- if PathExpand(CombinedPath, TestExpandedPath) and
|
|
|
|
- (CombinedPath = TestExpandedPath) then begin
|
|
|
|
- AResultingPath := CombinedPath;
|
|
|
|
|
|
+ if ADestDir <> '' then begin
|
|
|
|
+ { Our validity checks passed. Now pass the combined path to PathExpand
|
|
|
|
+ (GetFullPathName) to see if it thinks the path needs normalization.
|
|
|
|
+ If the returned path isn't exactly what was passed in, then consider
|
|
|
|
+ the name invalid.
|
|
|
|
+ One way that can happen is if the path ends in an MS-DOS device name:
|
|
|
|
+ PathExpand('c:\path\NUL') returns '\\.\NUL'. Obviously we don't want
|
|
|
|
+ devices being opened, so that must be rejected. }
|
|
|
|
+ var CombinedPath := ADestDir + AFilename;
|
|
|
|
+ var TestExpandedPath: String;
|
|
|
|
+ if PathExpand(CombinedPath, TestExpandedPath) and
|
|
|
|
+ (CombinedPath = TestExpandedPath) then begin
|
|
|
|
+ AResultingPath := CombinedPath;
|
|
|
|
+ Result := True;
|
|
|
|
+ end;
|
|
|
|
+ end else
|
|
Result := True;
|
|
Result := True;
|
|
- end;
|
|
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function ValidateAndCombinePath(const ADestDir, AFilename: String): Boolean;
|
|
|
|
+begin
|
|
|
|
+ var ResultingPath: String;
|
|
|
|
+ Result := ValidateAndCombinePath(ADestDir, AFilename, ResultingPath);
|
|
|
|
+end;
|
|
|
|
+
|
|
end.
|
|
end.
|