-
Notifications
You must be signed in to change notification settings - Fork 74
Avoid panics in NgxListIterator, rename to_str to as_str where appropriate #183
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
base: main
Are you sure you want to change the base?
Conversation
The ngx_str_items in the header name and value are often untrusted input, and may not have utf-8 contents. The use of ngx_str_t::to_str in this iterator will panic when the contents are not utf-8. So, instead of yielding a pair of strs here, yield a pair of byte slices.
In Rust, the convention is that `to_` methods take ownership of self (e.g. fn to_string(self) -> Self) whereas `as_` methods borrow self (e.g. fn as_str(&self) -> &str). In general, we should avoid exposing methods that panic when its reasonable to return a Result instead. This particular method was used, likely without considering that it may panic or validating that the contents are utf-8, in ngx::http::NgxListIterator's Iterator impl, which made it very easy to panic based on untrusted input.
In Rust, the convention is that `to_` methods take ownership of self (e.g. fn to_string(self) -> Self) whereas `as_` methods borrow self (e.g. fn as_str(&self) -> &str).
67c967a
to
479f08c
Compare
The NgxListIterator bug was discovered by @xeioex so I'll tag him for review |
@@ -478,7 +478,7 @@ impl<'a> Iterator for NgxListIterator<'a> { | |||
} | |||
let header = &part.arr[self.i]; | |||
self.i += 1; | |||
Some((header.key.to_str(), header.value.to_str())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather return a pair of NgxStr
here, as these now provide Display, PartialEq and necessary conversions.
I believe we need more time to think for this Header iterator interface as there are a lot of things to consider.
Also looking at RFC9110
Treating the headers as bytes simplifies things for us in ngx-rust, but I am not sure it is very convenient for users. |
if let Ok(value) = std::str::from_utf8(value) { | ||
headers.insert(http::header::HOST, value.parse().unwrap()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let Ok(value) = std::str::from_utf8(value) { | |
headers.insert(http::header::HOST, value.parse().unwrap()); | |
if let Ok(value) = http::HeaderValue::from_bytes(value) { | |
headers.insert(http::header::HOST, value); |
@@ -282,7 +282,7 @@ http_request_handler!(awssigv4_header_handler, |request: &mut Request| { | |||
} | |||
|
|||
let datetime = chrono::Utc::now(); | |||
let uri = match request.unparsed_uri().to_str() { | |||
let uri = match request.unparsed_uri().as_str() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ToStr trait seems pretty standard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at std
, it seems to provide as_str
for infallible conversions with guaranteed UTF-8 and to_str
for maybe-not-utf types.
Proposed changes
ngx::http::NgxListIterator: ngx_str_t items may not be str:
The ngx_str_items in the header name and value are often untrusted
input, and may not have utf-8 contents. The use of ngx_str_t::to_str
in this iterator will panic when the contents are not utf-8. So, instead
of yielding a pair of strs here, yield a pair of byte slices.
ngx_str_t::to_str should not unwrap, and should be called as_str
In Rust, the convention is that
to_
methods take ownership of self(e.g. fn to_string(self) -> Self) whereas
as_
methods borrow self(e.g. fn as_str(&self) -> &str).
In general, we should avoid exposing methods that panic when its
reasonable to return a Result instead. This particular method was used,
likely without considering that it may panic or validating that the
contents are utf-8, in ngx::http::NgxListIterator's Iterator impl,
which made it very easy to panic based on untrusted input.
NgxStr::to_str renamed as_str
Same reasoning as above. This method already had the Result<&str, Utf8Error>
return type that I changed ngx_str_t::to_str to have.
Checklist
Before creating a PR, run through this checklist and mark each as complete.