classfile_parser/attribute_info/
parser.rs

1use nom::{
2    bytes::complete::take,
3    combinator::{map, success},
4    error::{Error, ErrorKind},
5    multi::count,
6    number::complete::{be_u16, be_u32, be_u8},
7    Err as BaseErr,
8};
9
10use attribute_info::types::StackMapFrame::*;
11use attribute_info::*;
12
13// Using a type alias here evades a Clippy warning about complex types.
14type Err<E> = BaseErr<Error<E>>;
15
16pub fn attribute_parser(input: &[u8]) -> Result<(&[u8], AttributeInfo), Err<&[u8]>> {
17    let (input, attribute_name_index) = be_u16(input)?;
18    let (input, attribute_length) = be_u32(input)?;
19    let (input, info) = take(attribute_length)(input)?;
20    Ok((
21        input,
22        AttributeInfo {
23            attribute_name_index,
24            attribute_length,
25            info: info.to_owned(),
26        },
27    ))
28}
29
30pub fn exception_entry_parser(input: &[u8]) -> Result<(&[u8], ExceptionEntry), Err<&[u8]>> {
31    let (input, start_pc) = be_u16(input)?;
32    let (input, end_pc) = be_u16(input)?;
33    let (input, handler_pc) = be_u16(input)?;
34    let (input, catch_type) = be_u16(input)?;
35    Ok((
36        input,
37        ExceptionEntry {
38            start_pc,
39            end_pc,
40            handler_pc,
41            catch_type,
42        },
43    ))
44}
45
46pub fn code_attribute_parser(input: &[u8]) -> Result<(&[u8], CodeAttribute), Err<&[u8]>> {
47    let (input, max_stack) = be_u16(input)?;
48    let (input, max_locals) = be_u16(input)?;
49    let (input, code_length) = be_u32(input)?;
50    let (input, code) = take(code_length)(input)?;
51    let (input, exception_table_length) = be_u16(input)?;
52    let (input, exception_table) =
53        count(exception_entry_parser, exception_table_length as usize)(input)?;
54    let (input, attributes_count) = be_u16(input)?;
55    let (input, attributes) = count(attribute_parser, attributes_count as usize)(input)?;
56    Ok((
57        input,
58        CodeAttribute {
59            max_stack,
60            max_locals,
61            code_length,
62            code: code.to_owned(),
63            exception_table_length,
64            exception_table,
65            attributes_count,
66            attributes,
67        },
68    ))
69}
70
71pub fn method_parameters_attribute_parser(
72    input: &[u8],
73) -> Result<(&[u8], MethodParametersAttribute), Err<&[u8]>> {
74    let (input, parameters_count) = be_u8(input)?;
75    let (input, parameters) = count(parameters_parser, parameters_count as usize)(input)?;
76    Ok((
77        input,
78        MethodParametersAttribute {
79            parameters_count,
80            parameters,
81        },
82    ))
83}
84
85pub fn parameters_parser(input: &[u8]) -> Result<(&[u8], ParameterAttribute), Err<&[u8]>> {
86    let (input, name_index) = be_u16(input)?;
87    let (input, access_flags) = be_u16(input)?;
88    Ok((
89        input,
90        ParameterAttribute {
91            name_index,
92            access_flags,
93        },
94    ))
95}
96
97fn same_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
98    success(SameFrame { frame_type })(input)
99}
100
101fn verification_type_parser(input: &[u8]) -> Result<(&[u8], VerificationTypeInfo), Err<&[u8]>> {
102    use self::VerificationTypeInfo::*;
103    let v = input[0];
104    let new_input = &input[1..];
105    match v {
106        0 => Ok((new_input, Top)),
107        1 => Ok((new_input, Integer)),
108        2 => Ok((new_input, Float)),
109        3 => Ok((new_input, Double)),
110        4 => Ok((new_input, Long)),
111        5 => Ok((new_input, Null)),
112        6 => Ok((new_input, UninitializedThis)),
113        7 => map(be_u16, |class| Object { class })(new_input),
114        8 => map(be_u16, |offset| Uninitialized { offset })(new_input),
115        _ => Result::Err(Err::Error(error_position!(input, ErrorKind::NoneOf))),
116    }
117}
118
119fn same_locals_1_stack_item_frame_parser(
120    input: &[u8],
121    frame_type: u8,
122) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
123    let (input, stack) = verification_type_parser(input)?;
124    Ok((input, SameLocals1StackItemFrame { frame_type, stack }))
125}
126
127fn same_locals_1_stack_item_frame_extended_parser(
128    input: &[u8],
129    frame_type: u8,
130) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
131    let (input, offset_delta) = be_u16(input)?;
132    let (input, stack) = verification_type_parser(input)?;
133    Ok((
134        input,
135        SameLocals1StackItemFrameExtended {
136            frame_type,
137            offset_delta,
138            stack,
139        },
140    ))
141}
142
143fn chop_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
144    let (input, offset_delta) = be_u16(input)?;
145    Ok((
146        input,
147        ChopFrame {
148            frame_type,
149            offset_delta,
150        },
151    ))
152}
153
154fn same_frame_extended_parser(
155    input: &[u8],
156    frame_type: u8,
157) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
158    let (input, offset_delta) = be_u16(input)?;
159    Ok((
160        input,
161        SameFrameExtended {
162            frame_type,
163            offset_delta,
164        },
165    ))
166}
167
168fn append_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
169    let (input, offset_delta) = be_u16(input)?;
170    let (input, locals) = count(verification_type_parser, (frame_type - 251) as usize)(input)?;
171    Ok((
172        input,
173        AppendFrame {
174            frame_type,
175            offset_delta,
176            locals,
177        },
178    ))
179}
180
181fn full_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
182    let (input, offset_delta) = be_u16(input)?;
183    let (input, number_of_locals) = be_u16(input)?;
184    let (input, locals) = count(verification_type_parser, number_of_locals as usize)(input)?;
185    let (input, number_of_stack_items) = be_u16(input)?;
186    let (input, stack) = count(verification_type_parser, number_of_stack_items as usize)(input)?;
187    Ok((
188        input,
189        FullFrame {
190            frame_type,
191            offset_delta,
192            number_of_locals,
193            locals,
194            number_of_stack_items,
195            stack,
196        },
197    ))
198}
199
200fn stack_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
201    match frame_type {
202        0..=63 => same_frame_parser(input, frame_type),
203        64..=127 => same_locals_1_stack_item_frame_parser(input, frame_type),
204        247 => same_locals_1_stack_item_frame_extended_parser(input, frame_type),
205        248..=250 => chop_frame_parser(input, frame_type),
206        251 => same_frame_extended_parser(input, frame_type),
207        252..=254 => append_frame_parser(input, frame_type),
208        255 => full_frame_parser(input, frame_type),
209        _ => Result::Err(Err::Error(error_position!(input, ErrorKind::NoneOf))),
210    }
211}
212
213fn stack_map_frame_entry_parser(input: &[u8]) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
214    let (input, frame_type) = be_u8(input)?;
215    let (input, stack_frame) = stack_frame_parser(input, frame_type)?;
216    Ok((input, stack_frame))
217}
218
219pub fn stack_map_table_attribute_parser(
220    input: &[u8],
221) -> Result<(&[u8], StackMapTableAttribute), Err<&[u8]>> {
222    let (input, number_of_entries) = be_u16(input)?;
223    let (input, entries) = count(stack_map_frame_entry_parser, number_of_entries as usize)(input)?;
224    Ok((
225        input,
226        StackMapTableAttribute {
227            number_of_entries,
228            entries,
229        },
230    ))
231}
232
233pub fn exceptions_attribute_parser(
234    input: &[u8],
235) -> Result<(&[u8], ExceptionsAttribute), Err<&[u8]>> {
236    let (input, exception_table_length) = be_u16(input)?;
237    let (input, exception_table) = count(be_u16, exception_table_length as usize)(input)?;
238    Ok((
239        input,
240        ExceptionsAttribute {
241            exception_table_length,
242            exception_table,
243        },
244    ))
245}
246
247pub fn constant_value_attribute_parser(
248    input: &[u8],
249) -> Result<(&[u8], ConstantValueAttribute), Err<&[u8]>> {
250    let (input, constant_value_index) = be_u16(input)?;
251    Ok((
252        input,
253        ConstantValueAttribute {
254            constant_value_index,
255        },
256    ))
257}
258
259fn bootstrap_method_parser(input: &[u8]) -> Result<(&[u8], BootstrapMethod), Err<&[u8]>> {
260    let (input, bootstrap_method_ref) = be_u16(input)?;
261    let (input, num_bootstrap_arguments) = be_u16(input)?;
262    let (input, bootstrap_arguments) = count(be_u16, num_bootstrap_arguments as usize)(input)?;
263    Ok((
264        input,
265        BootstrapMethod {
266            bootstrap_method_ref,
267            num_bootstrap_arguments,
268            bootstrap_arguments,
269        },
270    ))
271}
272
273pub fn bootstrap_methods_attribute_parser(
274    input: &[u8],
275) -> Result<(&[u8], BootstrapMethodsAttribute), Err<&[u8]>> {
276    let (input, num_bootstrap_methods) = be_u16(input)?;
277    let (input, bootstrap_methods) =
278        count(bootstrap_method_parser, num_bootstrap_methods as usize)(input)?;
279    Ok((
280        input,
281        BootstrapMethodsAttribute {
282            num_bootstrap_methods,
283            bootstrap_methods,
284        },
285    ))
286}
287
288pub fn sourcefile_attribute_parser(
289    input: &[u8],
290) -> Result<(&[u8], SourceFileAttribute), Err<&[u8]>> {
291    let (input, attribute_name_index) = be_u16(input)?;
292    let (input, attribute_length) = be_u32(input)?;
293    let (input, sourcefile_index) = be_u16(input)?;
294    Ok((
295        input,
296        SourceFileAttribute {
297            attribute_name_index,
298            attribute_length,
299            sourcefile_index,
300        },
301    ))
302}