P3KI / bendy

A rust library for encoding and decoding bencode with enforced cannonicalization rules.
BSD 3-Clause "New" or "Revised" License
74 stars 14 forks source link

`StructureError(UnsortedKeys)` on decoding? #61

Closed avdb13 closed 1 year ago

avdb13 commented 1 year ago

I have the following FromBencode implementation which very surprisingly fails with an error that should be only relevant to encoding.

impl FromBencode for ScrapeResponse {
    const EXPECTED_RECURSION_DEPTH: usize = 5;
    fn decode_bencode_object(
        object: bendy::decoding::Object,
    ) -> Result<Self, bendy::decoding::Error>
    where
        Self: Sized,
    {
        // &bytes = b"d5:filesd20:\x1b\x84\xcb\xd2TZf\x8a\xd85\x04!\xd4\x1b\x88\x0f?d\xcc\xf4d8:completei17e10:incompletei2e10:downloadedi1539eeee"

        let mut dict = object.try_into_dictionary()?;
        let mut result = Vec::new();

        while let Some(files) = dict.next_pair()? {
            let mut files = files.1.try_into_dictionary()?;

            while let Some(file) = files.next_pair()? {
                let mut decoder = file.1.try_into_dictionary()?;
                let mut status: Status = Default::default();

                while let Some(pair) = decoder.next_pair()? {
                    match pair {
                        (b"complete", _) => {
                            status.seeders = u32::decode_bencode_object(pair.1)?;
                        }
                        (b"incomplete", _) => {
                            status.leechers = u32::decode_bencode_object(pair.1)?;
                        }
                        (b"downloaded", _) => {
                            let err = u32::decode_bencode_object(pair.1);
                            dbg!(err.unwrap());
                        }
                        _ => {}
                    }
                }
                result.push((file.0.to_vec(), status));
            }
        }
        Ok(Self { files: result })
    }
}
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { context: None, error: StructureError(UnsortedKeys) }
thequux commented 1 year ago

That is invalid bencode; the keys of a dictionary must be stored in sorted order, and bendy validates this while parsing. Thus, arguably the bug is in whatever generated the invalid bencode data.

We have plans to make it possible to disable that check (see #6), but it hasn't been a priority for us until now. We'll see if we can fix this in the coming few weeks, but I can't make any guarantees as we have a deadline approaching on another project.

On Thu, Dec 29, 2022, 21:50 avdb @.***> wrote:

I have the following FromBencode implementation which very surprisingly fails with an error that should be only relevant to encoding.

impl FromBencode for ScrapeResponse { const EXPECTED_RECURSION_DEPTH: usize = 5; fn decode_bencode_object( object: bendy::decoding::Object, ) -> Result<Self, bendy::decoding::Error> where Self: Sized, { // &bytes = b"d5:filesd20:\x1b\x84\xcb\xd2TZf\x8a\xd85\x04!\xd4\x1b\x88\x0f?d\xcc\xf4d8:completei17e10:incompletei2e10:downloadedi1539eeee"

    let mut dict = object.try_into_dictionary()?;
    let mut result = Vec::new();

    while let Some(files) = dict.next_pair()? {
        let mut files = files.1.try_into_dictionary()?;

        while let Some(file) = files.next_pair()? {
            let mut decoder = file.1.try_into_dictionary()?;
            let mut status: Status = Default::default();

            while let Some(pair) = decoder.next_pair()? {
                match pair {
                    (b"complete", _) => {
                        status.seeders = u32::decode_bencode_object(pair.1)?;
                    }
                    (b"incomplete", _) => {
                        status.leechers = u32::decode_bencode_object(pair.1)?;
                    }
                    (b"downloaded", _) => {
                        let err = u32::decode_bencode_object(pair.1);
                        dbg!(err.unwrap());
                    }
                    _ => {}
                }
            }
            result.push((file.0.to_vec(), status));
        }
    }
    Ok(Self { files: result })
}}

— Reply to this email directly, view it on GitHub https://github.com/P3KI/bendy/issues/61, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAABJEFMOCKQZFGLFGHCIELWPX2RPANCNFSM6AAAAAATMMHVFI . You are receiving this because you are subscribed to this thread.Message ID: @.***>