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

Failing to round-trip deserialize with Bincoded formula #18

Open
vlovich opened this issue Oct 24, 2023 · 5 comments
Open

Failing to round-trip deserialize with Bincoded formula #18

vlovich opened this issue Oct 24, 2023 · 5 comments

Comments

@vlovich
Copy link

vlovich commented Oct 24, 2023

It looks like if I have a member that contains Bincoded, either deserialization fails or I'm doing something wrong. For some reason the byte array ends up pointing to the whole input buffer being deserialized instead of correctly round-tripping.

  left: `[4, 4, 5, 6, 7, 1, 2, 3, 4]`,
 right: `[1, 2, 3, 4]`: Full serialized [4, 4, 5, 6, 7, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0]', src/main.rs:55:5

Left is the buffer we actually retrieved from deserialized, right is the expected deserialized buffer and "full serialized" is the input buffer provided to alkahest::deserialize. It's interesting that the buffer returned ends at the right spot & just has the wrong starting point.

Here's the example code snippet: https://gist.github.com/vlovich/9e2645ed83e546777422766e825cb463

Cargo.toml:

[package]
name = "alkahest-repro"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
alkahest = { path = "../../alkahest", default-features = false, features = [
    "bincoded",
    "fixed64",
    "derive"
]}
bincode = { version = "2.0.0-rc", features = ["derive"] }
serde = "1.0.189"

Everything seems OK if I avoid Bincoded (https://gist.github.com/vlovich/2b352bcfe26ad5d40958561f166d0aa7).

@vlovich
Copy link
Author

vlovich commented Oct 25, 2023

Also it seems adding a dummy field to the end of the formula works around the issue.

@zakarumych
Copy link
Owner

Thank you for the report. I will investigate it next week

@zakarumych
Copy link
Owner

zakarumych commented Nov 8, 2023

Sorry for late reply.
You use deserialize which won't work here because it has following requirements:

  • The value must occupy the whole input slice.
  • The value must be either sized or heap-less.

Code ensures to satisfy first one by truncating the buffer.
But the value is not heapless since it uses Bincoded and not sized since it has unsized field Bytes.
In this case you have to use deserialize_with_size to provide stack size of the serialized buffer.
It is the second value returned from serialize

@zakarumych
Copy link
Owner

zakarumych commented Nov 8, 2023

For more straightforward usage consider using packet module which will encode stack size into the buffer, so it won't be necessary to carry it around.
It also allows to unpack from buffer with any other bytes after actual packet.
This way you can read values from data stream and unpack them from first to last, or read only next packet length and skip it.

@zakarumych
Copy link
Owner

I'm adding assert to the deserialize. Its requirement can and must be checked by looking at associated constants.

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

No branches or pull requests

2 participants