-
Notifications
You must be signed in to change notification settings - Fork 95
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
Stack overflow when decoding large boxed arrays #419
Comments
This manual implementation works as a workaround, but it is slow: #![feature(new_uninit)]
use parity_scale_codec::{Decode, Encode, Input};
use std::mem::ManuallyDrop;
#[derive(Encode)]
struct S(Box<[u8; 100 * 1024 * 1024]>);
impl Decode for S {
fn decode<I: Input>(input: &mut I) -> Result<Self, parity_scale_codec::Error> {
let piece = parity_scale_codec::decode_vec_with_len::<u8, _>(input, 100 * 1024 * 1024)
.map_err(|error| error.chain("Could not decode `S.0`"))?;
let mut piece = ManuallyDrop::new(piece);
// SAFETY: Original memory is not dropped and guaranteed to be allocated
let piece = unsafe { Box::from_raw(piece.as_mut_ptr() as *mut [u8; 100 * 1024 * 1024]) };
Ok(S(piece))
}
}
impl Default for S {
fn default() -> Self {
Self(unsafe { Box::new_zeroed().assume_init() })
}
}
fn main() {
let s = S::default();
let encoded = s.encode();
println!("Encoded successfully");
S::decode(&mut encoded.as_slice()).unwrap();
} |
Minimized example on stable rust (in case anyone doubts the use parity_scale_codec::Decode;
fn main() {
let data = &[];
let _ = Box::<[u8; 100 * 1024 * 1024]>::decode(&mut data.as_slice());
} |
Hmm.... this seems a little tricky to fix as-is; this is the problem code: impl<T, X> Decode for X where
T: Decode + Into<X>,
X: WrapperTypeDecode<Wrapped=T>,
{
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
input.descend_ref()?;
let result = Ok(T::decode(input)?.into());
input.ascend_ref();
result
}
}
impl<T> WrapperTypeDecode for Box<T> {
type Wrapped = T;
} So it calls We'll probably have to refactor |
I don't think the issue is fixed fully. I have upgraded to 3.6.1 and it my app still crashes with stack overflow. Here is example that is a tiny bit more advanced than before (this is what I actually use in the app), it uses new type:
|
I dont think this^ can be fixed, or @koute ? |
The biggest problem is that it compiled, but crashes in runtime. If it didn't compile it would have been easier to work with. |
Hm not sure what could be done about this. We could add some Or we swap to lazy allocations when the estimated size is above some customizable limit? All just ideas, no idea what is best or achivable. |
I think we can fix it. If we have a new type wrapper like type (one unnamed/named field) and it has the |
And BTW, it doesn't fail with a stack overflow for me. I get a segmentation fault, because the inputs to |
It seems to on Linux:
|
I'm also on Linux, but I get:
Looking into it with gdb, I get the following:
That |
Yeah, this is kinda expected, as the #[repr(transparent)]
struct NewType([u8; 100 * 1024 * 1024]);
struct S(Box<NewType>);
#[allow(deprecated)]
const _: () = {
#[automatically_derived]
impl ::parity_scale_codec::Decode for NewType {
fn decode<__CodecInputEdqy: ::parity_scale_codec::Input>(
__codec_input_edqy: &mut __CodecInputEdqy,
) -> ::core::result::Result<Self, ::parity_scale_codec::Error> {
::core::result::Result::Ok(
NewType({
let __codec_res_edqy = <[u8; 100 * 1024
* 1024] as ::parity_scale_codec::Decode>::decode(
__codec_input_edqy,
);
match __codec_res_edqy {
::core::result::Result::Err(e) => {
return ::core::result::Result::Err(
e.chain("Could not decode `NewType.0`"),
);
}
::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,
}
}),
)
}
}
};
#[allow(deprecated)]
const _: () = {
#[automatically_derived]
impl ::parity_scale_codec::Decode for S {
fn decode<__CodecInputEdqy: ::parity_scale_codec::Input>(
__codec_input_edqy: &mut __CodecInputEdqy,
) -> ::core::result::Result<Self, ::parity_scale_codec::Error> {
::core::result::Result::Ok(
S({
let __codec_res_edqy = <Box<
NewType,
> as ::parity_scale_codec::Decode>::decode(__codec_input_edqy);
match __codec_res_edqy {
::core::result::Result::Err(e) => {
return ::core::result::Result::Err(
e.chain("Could not decode `S.0`"),
);
}
::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,
}
}),
)
}
}
}; As you can see the For this not to crash we need to also generate a I'll fix this. |
That's probably due to corrupted stack. (See the other argument where you're getting |
PR with a fix to also handle newtypes: #462 |
Example:
Output:
Likely due to rust-lang/rust#53827
The text was updated successfully, but these errors were encountered: