Skip to content
This repository has been archived by the owner on Feb 14, 2023. It is now read-only.

Calling form.prepare()?.boundary() twice panics #122

Open
konstin opened this issue Aug 21, 2019 · 2 comments
Open

Calling form.prepare()?.boundary() twice panics #122

konstin opened this issue Aug 21, 2019 · 2 comments

Comments

@konstin
Copy link

konstin commented Aug 21, 2019

Creating a form outside of a loop and then calling let prepared_fields = form.prepare()?; and let boundary = prepared_fields.boundary(); in a loop panics on the second time.

Function the crash occurs in:

/// Get the boundary that was used to serialize the request.
pub fn boundary(&self) -> &str {
let boundary = self.end_boundary.get_ref();
// Get just the bare boundary string
&boundary[4 .. boundary.len() - 2]
}
}

Backtrace:

thread 'main' panicked at 'attempt to subtract with overflow', /home/konsti/.cargo/registry/src/github.com-1ecc6299db9ec823/multipart-0.16.1/src/client/lazy.rs:303:24
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:47
   3: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:36
   4: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:200
   5: std::panicking::default_hook
             at src/libstd/panicking.rs:214
   6: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:477
   7: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:384
   8: rust_begin_unwind
             at src/libstd/panicking.rs:311
   9: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  10: core::panicking::panic
             at src/libcore/panicking.rs:49
  11: multipart::client::lazy::PreparedFields::boundary
             at /home/konsti/.cargo/registry/src/github.com-1ecc6299db9ec823/multipart-0.16.1/src/client/lazy.rs:303
  12: pyo3_pack::upload::upload
             at src/upload.rs:93
  13: pyo3_pack::upload_ui::{{closure}}
             at src/main.rs:326
  14: <core::iter::adapters::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold::{{closure}}
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/iter/adapters/mod.rs:615
  15: <core::slice::Iter<T> as core::iter::traits::iterator::Iterator>::try_fold
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/slice/mod.rs:3187
  16: <core::iter::adapters::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/iter/adapters/mod.rs:615
  17: <core::iter::adapters::ResultShunt<I,E> as core::iter::traits::iterator::Iterator>::try_fold
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/iter/adapters/mod.rs:2234
  18: core::iter::traits::iterator::Iterator::fold
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/iter/traits/iterator.rs:1783
  19: core::iter::traits::iterator::Iterator::for_each
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/iter/traits/iterator.rs:602
  20: core::unit::<impl core::iter::traits::collect::FromIterator<()> for ()>::from_iter
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/unit.rs:19
  21: core::iter::traits::iterator::Iterator::collect
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/iter/traits/iterator.rs:1464
  22: <core::result::Result<V,E> as core::iter::traits::collect::FromIterator<core::result::Result<A,E>>>::from_iter::{{closure}}
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/result.rs:1346
  23: core::iter::adapters::process_results
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/iter/adapters/mod.rs:2206
  24: <core::result::Result<V,E> as core::iter::traits::collect::FromIterator<core::result::Result<A,E>>>::from_iter
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/result.rs:1346
  25: core::iter::traits::iterator::Iterator::collect
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/iter/traits/iterator.rs:1464
  26: pyo3_pack::upload_ui
             at src/main.rs:323
  27: pyo3_pack::run
             at src/main.rs:410
  28: pyo3_pack::main
             at src/main.rs:485
  29: std::rt::lang_start::{{closure}}
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libstd/rt.rs:64
  30: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:49
  31: std::panicking::try::do_call
             at src/libstd/panicking.rs:296
  32: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:80
  33: std::panicking::try
             at src/libstd/panicking.rs:275
  34: std::panic::catch_unwind
             at src/libstd/panic.rs:394
  35: std::rt::lang_start_internal
             at src/libstd/rt.rs:48
  36: std::rt::lang_start
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libstd/rt.rs:64
  37: main
  38: __libc_start_main
  39: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
@abonander
Copy link
Owner

abonander commented Aug 21, 2019

@konstin leaving this open cause I'm not sure how to address it but .prepare() is not meant to be called more than once in a row; the fields you set in the form were moved the first time you called it.

This panic is occurring because boundary is empty; if there are no fields in the request then a boundary doesn't need to be created. A simple fix would be to not perform the slicing operation if the boundary is empty.

I don't really have a good reason for why .prepare() doesn't take the Multipart by-value except that I thought people might want to reuse the internal allocation to build another request. Oh, also because the other methods take &mut self and return &mut Self so this can all fit into one call chain.

@konstin
Copy link
Author

konstin commented Aug 22, 2019

I think .prepare() consuming Mutlitpart would be a good idea as it's already consuming the contents. boundary() not slicing or at least explicitly panicing with an error message would also be helpful.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants