Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix downloading URLs with invalid characters #5921

Merged
merged 2 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions master_changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ users)
## Lint

## Repository
* Fix download URLs containing invalid characters on Windows (e.g. the ? character in `?full_index=1`) [#5921 @dra27]

## Lock

Expand Down
9 changes: 9 additions & 0 deletions src/core/opamStd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,15 @@ module OpamSys = struct
if !called then invalid_arg "Just what do you think you're doing, Dave?";
called := true;
console := printer

let is_valid_basename_char =
if Sys.win32 then
function
| '\000'..'\031'
| '<' | '>' | ':' | '"' | '/' | '\\' | '|' | '?' | '*' -> false
| _ -> true
else
fun c -> c <> '\000' && c <> '/'
end


Expand Down
3 changes: 3 additions & 0 deletions src/core/opamStd.mli
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,9 @@ module Sys : sig
OS) *)
val path_sep: char

(** [true] if a character may be used in a filename. *)
val is_valid_basename_char: char -> bool

(** Splits a PATH-like variable separated with [path_sep]. More involved than
it seems, because there may be quoting on Windows. By default, it returns
the path cleaned (remove trailing, leading, contiguous delimiters).
Expand Down
12 changes: 11 additions & 1 deletion src/repository/opamDownload.ml
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,18 @@ let download_as ?quiet ?validate ~overwrite ?compress ?checksum url dst =
()

let download ?quiet ?validate ~overwrite ?compress ?checksum url dstdir =
let base =
let base = OpamUrl.basename url in
if Sys.win32 then
let f c =
if OpamStd.Sys.is_valid_basename_char c then c else '_'
in
String.map f base
else
base
in
let dst =
OpamFilename.(create dstdir (Base.of_string (OpamUrl.basename url)))
OpamFilename.(create dstdir (Base.of_string base))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should have that check/change in OpamFilename.Base directly, like that we are sure that every file created is valid. But can we have that change (forbidden char -> _) for all files?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can ever automatically change it, but we may want to do things to cause better error messages. For example, if an opam file actually specifies extra-source "zstd-detection?full_index=1.patch" { then I don't think opam should ever do anything to make this work, but it perhaps fail with a better error message if this is encountered.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(the key point here is that this filename is internal to opam)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In opam code, there is no collision with _ change (as you pointed), but I'm wondering if we could have collision for library users.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly - on the plus-side, the fallout is limited to Windows, where the code would have been failing before!

in
download_as ?quiet ?validate ~overwrite ?compress ?checksum url dst @@|
fun () -> dst
Expand Down
Loading