aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src/filename.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-02-16 15:55:34 +0100
committerBjörn Gustavsson <[email protected]>2017-02-21 09:45:00 +0100
commit8c7a68f3808a8d52f5cfc297a249ca4ef2480238 (patch)
tree716f1fb9157b6e46a1d86f78ec646067742475a3 /lib/stdlib/src/filename.erl
parent381f97b30092624b238a68909855692929d6f8bf (diff)
downloadotp-8c7a68f3808a8d52f5cfc297a249ca4ef2480238.tar.gz
otp-8c7a68f3808a8d52f5cfc297a249ca4ef2480238.tar.bz2
otp-8c7a68f3808a8d52f5cfc297a249ca4ef2480238.zip
filename: Add safe_relative_path/1
Add safe_relative_path/1 to guard against directory traversal attacks. It either returns a shorter path without any ".." or "." components, or 'unsafe' if an ".." component would climb up above the root of the relative path. Here are a few examples: safe_relative_path("a/b/..") => "a" safe_relative_path("a/..") => "" safe_relative_path("a/../..") => unsafe safe_relative_path("/absolute/path") => unsafe The returned path can be used directly or combined with an absolute path using filename:join/2.
Diffstat (limited to 'lib/stdlib/src/filename.erl')
-rw-r--r--lib/stdlib/src/filename.erl36
1 files changed, 35 insertions, 1 deletions
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index c4586171ca..5d60b3837e 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -34,7 +34,8 @@
-export([absname/1, absname/2, absname_join/2,
basename/1, basename/2, dirname/1,
extension/1, join/1, join/2, pathtype/1,
- rootname/1, rootname/2, split/1, nativename/1]).
+ rootname/1, rootname/2, split/1, nativename/1,
+ safe_relative_path/1]).
-export([find_src/1, find_src/2, flatten/1]).
-export([basedir/2, basedir/3]).
@@ -750,6 +751,39 @@ separators() ->
_ -> {false, false}
end.
+-spec safe_relative_path(Filename) -> 'unsafe' | SafeFilename when
+ Filename :: file:name_all(),
+ SafeFilename :: file:name_all().
+
+safe_relative_path(Path) ->
+ case pathtype(Path) of
+ relative ->
+ Cs0 = split(Path),
+ safe_relative_path_1(Cs0, []);
+ _ ->
+ unsafe
+ end.
+
+safe_relative_path_1(["."|T], Acc) ->
+ safe_relative_path_1(T, Acc);
+safe_relative_path_1([<<".">>|T], Acc) ->
+ safe_relative_path_1(T, Acc);
+safe_relative_path_1([".."|T], Acc) ->
+ climb(T, Acc);
+safe_relative_path_1([<<"..">>|T], Acc) ->
+ climb(T, Acc);
+safe_relative_path_1([H|T], Acc) ->
+ safe_relative_path_1(T, [H|Acc]);
+safe_relative_path_1([], []) ->
+ [];
+safe_relative_path_1([], Acc) ->
+ join(lists:reverse(Acc)).
+
+climb(_, []) ->
+ unsafe;
+climb(T, [_|Acc]) ->
+ safe_relative_path_1(T, Acc).
+
%% find_src(Module) --