multipart icon indicating copy to clipboard operation
multipart copied to clipboard

Calling `form.prepare()?.boundary()` twice panics

Open konstin opened this issue 6 years ago • 2 comments

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:

https://github.com/abonander/multipart/blob/4a4104d2c5241dd9702359d4e2e91114408afbb0/src/client/lazy.rs#L298-L305

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.

konstin avatar Aug 21 '19 16:08 konstin

@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.

abonander avatar Aug 21 '19 19:08 abonander

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.

konstin avatar Aug 22 '19 11:08 konstin