elf/
compression.rs

1//! Parsing [CompressionHeader] from compressed ELF sections
2//!
3//! Note: This library does not provide any decompression functionality, but
4//! does expose parsed ELF compression headers alongside the raw compressed data.
5//!
6//! It is up to users of the library to choose the decompression library of
7//! their choice when dealing with compressed section contents.
8use crate::endian::EndianParse;
9use crate::file::Class;
10use crate::parse::{ParseAt, ParseError};
11
12/// C-style 32-bit ELF Compression Header definition
13///
14/// These C-style definitions are for users who want to implement their own ELF manipulation logic.
15#[derive(Debug)]
16#[repr(C)]
17pub struct Elf32_Chdr {
18    pub ch_type: u32,
19    pub ch_size: u32,
20    pub ch_addralign: u32,
21}
22
23/// C-style 64-bit ELF Compression Header definition
24///
25/// These C-style definitions are for users who want to implement their own ELF manipulation logic.
26#[derive(Debug)]
27#[repr(C)]
28pub struct Elf64_Chdr {
29    pub ch_type: u32,
30    pub ch_reserved: u32,
31    pub ch_size: u64,
32    pub ch_addralign: u64,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
36pub struct CompressionHeader {
37    pub ch_type: u32,
38    pub ch_size: u64,
39    pub ch_addralign: u64,
40}
41
42impl ParseAt for CompressionHeader {
43    fn parse_at<E: EndianParse>(
44        endian: E,
45        class: Class,
46        offset: &mut usize,
47        data: &[u8],
48    ) -> Result<Self, ParseError> {
49        match class {
50            Class::ELF32 => Ok(CompressionHeader {
51                ch_type: endian.parse_u32_at(offset, data)?,
52                ch_size: endian.parse_u32_at(offset, data)? as u64,
53                ch_addralign: endian.parse_u32_at(offset, data)? as u64,
54            }),
55            Class::ELF64 => {
56                let ch_type = endian.parse_u32_at(offset, data)?;
57                let _ch_reserved = endian.parse_u32_at(offset, data)?;
58                Ok(CompressionHeader {
59                    ch_type,
60                    ch_size: endian.parse_u64_at(offset, data)?,
61                    ch_addralign: endian.parse_u64_at(offset, data)?,
62                })
63            }
64        }
65    }
66
67    #[inline]
68    fn size_for(class: Class) -> usize {
69        match class {
70            Class::ELF32 => 12,
71            Class::ELF64 => 24,
72        }
73    }
74}
75
76#[cfg(test)]
77mod parse_tests {
78    use super::*;
79    use crate::endian::{BigEndian, LittleEndian};
80    use crate::parse::{test_parse_for, test_parse_fuzz_too_short};
81
82    #[test]
83    fn parse_chdr32_lsb() {
84        test_parse_for(
85            LittleEndian,
86            Class::ELF32,
87            CompressionHeader {
88                ch_type: 0x03020100,
89                ch_size: 0x07060504,
90                ch_addralign: 0x0B0A0908,
91            },
92        );
93    }
94
95    #[test]
96    fn parse_chdr32_msb() {
97        test_parse_for(
98            BigEndian,
99            Class::ELF32,
100            CompressionHeader {
101                ch_type: 0x00010203,
102                ch_size: 0x04050607,
103                ch_addralign: 0x08090A0B,
104            },
105        );
106    }
107
108    #[test]
109    fn parse_chdr64_lsb() {
110        test_parse_for(
111            LittleEndian,
112            Class::ELF64,
113            CompressionHeader {
114                ch_type: 0x03020100,
115                ch_size: 0x0F0E0D0C0B0A0908,
116                ch_addralign: 0x1716151413121110,
117            },
118        );
119    }
120
121    #[test]
122    fn parse_chdr64_msb() {
123        test_parse_for(
124            BigEndian,
125            Class::ELF64,
126            CompressionHeader {
127                ch_type: 0x00010203,
128                ch_size: 0x08090A0B0C0D0E0F,
129                ch_addralign: 0x1011121314151617,
130            },
131        );
132    }
133
134    #[test]
135    fn parse_chdr32_lsb_fuzz_too_short() {
136        test_parse_fuzz_too_short::<_, CompressionHeader>(LittleEndian, Class::ELF32);
137    }
138
139    #[test]
140    fn parse_chdr32_msb_fuzz_too_short() {
141        test_parse_fuzz_too_short::<_, CompressionHeader>(BigEndian, Class::ELF32);
142    }
143
144    #[test]
145    fn parse_chdr64_lsb_fuzz_too_short() {
146        test_parse_fuzz_too_short::<_, CompressionHeader>(LittleEndian, Class::ELF64);
147    }
148
149    #[test]
150    fn parse_chdr64_msb_fuzz_too_short() {
151        test_parse_fuzz_too_short::<_, CompressionHeader>(BigEndian, Class::ELF64);
152    }
153}