Fix File.cp_r/3 infinite loop when copying into subdirectory of source#15148
Fix File.cp_r/3 infinite loop when copying into subdirectory of source#15148josevalim merged 1 commit intoelixir-lang:mainfrom
File.cp_r/3 infinite loop when copying into subdirectory of source#15148Conversation
| expanded_destination = Path.expand(destination) | ||
|
|
||
| if String.starts_with?(expanded_destination, expanded_source <> "/") do | ||
| {:error, :einval, destination} |
There was a problem hiding this comment.
Looks that :einval is the most appropriate here, any better suggestion?
| expanded_source = Path.expand(source) | ||
| expanded_destination = Path.expand(destination) | ||
|
|
||
| if String.starts_with?(expanded_destination, expanded_source <> "/") do |
There was a problem hiding this comment.
A Path.parent? would be useful here.
|
Giveni the symlinks behaviour, I am not sure if it is something we should try to solve codewise or if we should just warn users of the problematic behaviour. In any case, if we do want to check for parent/child relationship, the best is to split call Path.split and then List.start_with? |
85a1014 to
06791f8
Compare
|
Pushed the fix with |
|
Tests are failing :) |
When destination is a subdirectory of source, `cp_r` would enter an
infinite loop because the newly created destination directory would
be included in the file listing during recursion. This can **cause disk
exhaustion** if large files are present under source.
This adds a validation check that returns `{:error, :einval, destination}`
when copying on a subdir of the source path.
Also document typical error reasons including the new `:einval` case.
06791f8 to
b6b4d94
Compare
|
Fixed, there was a test for copying src to src, that was failing with the |
|
💚 💙 💜 💛 ❤️ |
When destination is a subdirectory of source,
cp_rwould enter an infinite loop because the newly created destination directory would be included in the file listing during recursion. This can cause disk exhaustion if large files are present under source.This adds a validation check that returns
{:error, :einval, destination}when the expanded destination path starts with the expanded source path followed by a path separator.Also document typical error reasons including the new
:einvalcase.Simple reproduction:
Symlinks
Notice symlinks are not resolved by
Path.expand, so the issue is still there if you are using a symlinked subdir:realpath?