cole14/rust-elf

Parsing note entry failed when the namesz == (align * x + 1) in v0.7.*

baka233 opened this issue · 2 comments

Hello,

I found that parsing the note entry as follows would corrupt the parsing result.

/*     name, type, desc */
ELFNOTE32("Test", 0, "1234")

The namesz of this note is 5, and namesz will be decremented by one in Note::parse_at(), so the offset becomes (offset + 4) instead of (offset + 8) after alignment.

        let name_start = *offset;
        let name_size: usize = nhdr.n_namesz.saturating_sub(1).try_into()?;
        let name_end = name_start
            .checked_add(name_size)
            .ok_or(ParseError::IntegerOverflow)?;
        let name_buf = data.get_bytes(name_start..name_end)?;
        let name = from_utf8(name_buf)?;
        *offset = name_end;

        // skip over padding if needed to get back to 4-byte alignment
        if *offset % align > 0 {
            *offset = (*offset)
                .checked_add(align - *offset % align)
                .ok_or(ParseError::IntegerOverflow)?;
        }

As far as i know, this issue has been fixed by this commit, but it has not been picked up into v0.7 branch, I don't know if it is because that commit changed the API. If possible, could you fix this issue with the following patch in v0.7? Or i need to wait for the v0.8 to be released

        let name_start = *offset;
        let name_size: usize = nhdr.n_namesz.saturating_sub(1).try_into()?;
        let name_end = name_start
            .checked_add(name_size)
            .ok_or(ParseError::IntegerOverflow)?;
        let name_buf = data.get_bytes(name_start..name_end)?;
        let name = from_utf8(name_buf)?;
-        *offset = name_end;
+        *offset = name_start
+            .checked_add(nhdr.n_namesz.try_into()?)
+            .ok_or(ParseError::IntegerOverflow)?;


        // skip over padding if needed to get back to 4-byte alignment
        if *offset % align > 0 {
            *offset = (*offset)
                .checked_add(align - *offset % align)
                .ok_or(ParseError::IntegerOverflow)?;
        }

I committed a fix for this to the v0.7 branch and released it as v0.7.4. How does that look, does it solve your issue?

Yes, it solve my issue.

Fix note parsing for notes with n_namesz == (align * x + 1)