Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/gimli-0.29.0/src/leb128.rs
Line
Count
Source (jump to first uncovered line)
1
//! Read and write DWARF's "Little Endian Base 128" (LEB128) variable length
2
//! integer encoding.
3
//!
4
//! The implementation is a direct translation of the psuedocode in the DWARF 4
5
//! standard's appendix C.
6
//!
7
//! Read and write signed integers:
8
//!
9
//! ```
10
//! # #[cfg(all(feature = "read", feature = "write"))] {
11
//! use gimli::{EndianSlice, NativeEndian, leb128};
12
//!
13
//! let mut buf = [0; 1024];
14
//!
15
//! // Write to anything that implements `std::io::Write`.
16
//! {
17
//!     let mut writable = &mut buf[..];
18
//!     leb128::write::signed(&mut writable, -12345).expect("Should write number");
19
//! }
20
//!
21
//! // Read from anything that implements `gimli::Reader`.
22
//! let mut readable = EndianSlice::new(&buf[..], NativeEndian);
23
//! let val = leb128::read::signed(&mut readable).expect("Should read number");
24
//! assert_eq!(val, -12345);
25
//! # }
26
//! ```
27
//!
28
//! Or read and write unsigned integers:
29
//!
30
//! ```
31
//! # #[cfg(all(feature = "read", feature = "write"))] {
32
//! use gimli::{EndianSlice, NativeEndian, leb128};
33
//!
34
//! let mut buf = [0; 1024];
35
//!
36
//! {
37
//!     let mut writable = &mut buf[..];
38
//!     leb128::write::unsigned(&mut writable, 98765).expect("Should write number");
39
//! }
40
//!
41
//! let mut readable = EndianSlice::new(&buf[..], NativeEndian);
42
//! let val = leb128::read::unsigned(&mut readable).expect("Should read number");
43
//! assert_eq!(val, 98765);
44
//! # }
45
//! ```
46
47
const CONTINUATION_BIT: u8 = 1 << 7;
48
#[cfg(feature = "read-core")]
49
const SIGN_BIT: u8 = 1 << 6;
50
51
#[inline]
52
0
fn low_bits_of_byte(byte: u8) -> u8 {
53
0
    byte & !CONTINUATION_BIT
54
0
}
Unexecuted instantiation: gimli::leb128::low_bits_of_byte
Unexecuted instantiation: gimli::leb128::low_bits_of_byte
55
56
#[inline]
57
#[allow(dead_code)]
58
0
fn low_bits_of_u64(val: u64) -> u8 {
59
0
    let byte = val & u64::from(core::u8::MAX);
60
0
    low_bits_of_byte(byte as u8)
61
0
}
62
63
/// A module for reading signed and unsigned integers that have been LEB128
64
/// encoded.
65
#[cfg(feature = "read-core")]
66
pub mod read {
67
    use super::{low_bits_of_byte, CONTINUATION_BIT, SIGN_BIT};
68
    use crate::read::{Error, Reader, Result};
69
70
    /// Read bytes until the LEB128 continuation bit is not set.
71
0
    pub fn skip<R: Reader>(r: &mut R) -> Result<()> {
72
        loop {
73
0
            let byte = r.read_u8()?;
74
0
            if byte & CONTINUATION_BIT == 0 {
75
0
                return Ok(());
76
0
            }
77
        }
78
0
    }
Unexecuted instantiation: gimli::leb128::read::skip::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: gimli::leb128::read::skip::<_>
79
80
    /// Read an unsigned LEB128 number from the given `Reader` and
81
    /// return it or an error if reading failed.
82
0
    pub fn unsigned<R: Reader>(r: &mut R) -> Result<u64> {
83
0
        let mut result = 0;
84
0
        let mut shift = 0;
85
86
        loop {
87
0
            let byte = r.read_u8()?;
88
0
            if shift == 63 && byte != 0x00 && byte != 0x01 {
89
0
                return Err(Error::BadUnsignedLeb128);
90
0
            }
91
0
92
0
            let low_bits = u64::from(low_bits_of_byte(byte));
93
0
            result |= low_bits << shift;
94
0
95
0
            if byte & CONTINUATION_BIT == 0 {
96
0
                return Ok(result);
97
0
            }
98
0
99
0
            shift += 7;
100
        }
101
0
    }
Unexecuted instantiation: gimli::leb128::read::unsigned::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: gimli::leb128::read::unsigned::<_>
102
103
    /// Read an LEB128 u16 from the given `Reader` and
104
    /// return it or an error if reading failed.
105
0
    pub fn u16<R: Reader>(r: &mut R) -> Result<u16> {
106
0
        let byte = r.read_u8()?;
107
0
        let mut result = u16::from(low_bits_of_byte(byte));
108
0
        if byte & CONTINUATION_BIT == 0 {
109
0
            return Ok(result);
110
0
        }
111
112
0
        let byte = r.read_u8()?;
113
0
        result |= u16::from(low_bits_of_byte(byte)) << 7;
114
0
        if byte & CONTINUATION_BIT == 0 {
115
0
            return Ok(result);
116
0
        }
117
118
0
        let byte = r.read_u8()?;
119
0
        if byte > 0x03 {
120
0
            return Err(Error::BadUnsignedLeb128);
121
0
        }
122
0
        result += u16::from(byte) << 14;
123
0
        Ok(result)
124
0
    }
Unexecuted instantiation: gimli::leb128::read::u16::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: gimli::leb128::read::u16::<_>
125
126
    /// Read a signed LEB128 number from the given `Reader` and
127
    /// return it or an error if reading failed.
128
0
    pub fn signed<R: Reader>(r: &mut R) -> Result<i64> {
129
0
        let mut result = 0;
130
0
        let mut shift = 0;
131
0
        let size = 64;
132
        let mut byte;
133
134
        loop {
135
0
            byte = r.read_u8()?;
136
0
            if shift == 63 && byte != 0x00 && byte != 0x7f {
137
0
                return Err(Error::BadSignedLeb128);
138
0
            }
139
0
140
0
            let low_bits = i64::from(low_bits_of_byte(byte));
141
0
            result |= low_bits << shift;
142
0
            shift += 7;
143
0
144
0
            if byte & CONTINUATION_BIT == 0 {
145
0
                break;
146
0
            }
147
        }
148
149
0
        if shift < size && (SIGN_BIT & byte) == SIGN_BIT {
150
0
            // Sign extend the result.
151
0
            result |= !0 << shift;
152
0
        }
153
154
0
        Ok(result)
155
0
    }
Unexecuted instantiation: gimli::leb128::read::signed::<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>
Unexecuted instantiation: gimli::leb128::read::signed::<_>
156
}
157
158
/// A module for writing integers encoded as LEB128.
159
#[cfg(feature = "write")]
160
pub mod write {
161
    use super::{low_bits_of_u64, CONTINUATION_BIT};
162
    use std::io;
163
164
    /// Write the given unsigned number using the LEB128 encoding to the given
165
    /// `std::io::Write`able. Returns the number of bytes written to `w`, or an
166
    /// error if writing failed.
167
    pub fn unsigned<W>(w: &mut W, mut val: u64) -> Result<usize, io::Error>
168
    where
169
        W: io::Write,
170
    {
171
        let mut bytes_written = 0;
172
        loop {
173
            let mut byte = low_bits_of_u64(val);
174
            val >>= 7;
175
            if val != 0 {
176
                // More bytes to come, so set the continuation bit.
177
                byte |= CONTINUATION_BIT;
178
            }
179
180
            let buf = [byte];
181
            w.write_all(&buf)?;
182
            bytes_written += 1;
183
184
            if val == 0 {
185
                return Ok(bytes_written);
186
            }
187
        }
188
    }
189
190
    /// Return the size of the LEB128 encoding of the given unsigned number.
191
    pub fn uleb128_size(mut val: u64) -> usize {
192
        let mut size = 0;
193
        loop {
194
            val >>= 7;
195
            size += 1;
196
            if val == 0 {
197
                return size;
198
            }
199
        }
200
    }
201
202
    /// Write the given signed number using the LEB128 encoding to the given
203
    /// `std::io::Write`able. Returns the number of bytes written to `w`, or an
204
    /// error if writing failed.
205
    pub fn signed<W>(w: &mut W, mut val: i64) -> Result<usize, io::Error>
206
    where
207
        W: io::Write,
208
    {
209
        let mut bytes_written = 0;
210
        loop {
211
            let mut byte = val as u8;
212
            // Keep the sign bit for testing
213
            val >>= 6;
214
            let done = val == 0 || val == -1;
215
            if done {
216
                byte &= !CONTINUATION_BIT;
217
            } else {
218
                // Remove the sign bit
219
                val >>= 1;
220
                // More bytes to come, so set the continuation bit.
221
                byte |= CONTINUATION_BIT;
222
            }
223
224
            let buf = [byte];
225
            w.write_all(&buf)?;
226
            bytes_written += 1;
227
228
            if done {
229
                return Ok(bytes_written);
230
            }
231
        }
232
    }
233
234
    /// Return the size of the LEB128 encoding of the given signed number.
235
    pub fn sleb128_size(mut val: i64) -> usize {
236
        let mut size = 0;
237
        loop {
238
            val >>= 6;
239
            let done = val == 0 || val == -1;
240
            val >>= 1;
241
            size += 1;
242
            if done {
243
                return size;
244
            }
245
        }
246
    }
247
}
248
249
#[cfg(test)]
250
#[cfg(all(feature = "read", feature = "write"))]
251
mod tests {
252
    use super::{low_bits_of_byte, low_bits_of_u64, read, write, CONTINUATION_BIT};
253
    use crate::endianity::NativeEndian;
254
    use crate::read::{EndianSlice, Error, ReaderOffsetId};
255
256
    trait ResultExt {
257
        fn map_eof(self, input: &[u8]) -> Self;
258
    }
259
260
    impl<T> ResultExt for Result<T, Error> {
261
        fn map_eof(self, input: &[u8]) -> Self {
262
            match self {
263
                Err(Error::UnexpectedEof(id)) => {
264
                    let id = ReaderOffsetId(id.0 - input.as_ptr() as u64);
265
                    Err(Error::UnexpectedEof(id))
266
                }
267
                r => r,
268
            }
269
        }
270
    }
271
272
    #[test]
273
    fn test_low_bits_of_byte() {
274
        for i in 0..127 {
275
            assert_eq!(i, low_bits_of_byte(i));
276
            assert_eq!(i, low_bits_of_byte(i | CONTINUATION_BIT));
277
        }
278
    }
279
280
    #[test]
281
    fn test_low_bits_of_u64() {
282
        for i in 0u64..127 {
283
            assert_eq!(i as u8, low_bits_of_u64(1 << 16 | i));
284
            assert_eq!(
285
                i as u8,
286
                low_bits_of_u64(i << 16 | i | (u64::from(CONTINUATION_BIT)))
287
            );
288
        }
289
    }
290
291
    // Examples from the DWARF 4 standard, section 7.6, figure 22.
292
    #[test]
293
    fn test_read_unsigned() {
294
        let buf = [2u8];
295
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
296
        assert_eq!(
297
            2,
298
            read::unsigned(&mut readable).expect("Should read number")
299
        );
300
301
        let buf = [127u8];
302
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
303
        assert_eq!(
304
            127,
305
            read::unsigned(&mut readable).expect("Should read number")
306
        );
307
308
        let buf = [CONTINUATION_BIT, 1];
309
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
310
        assert_eq!(
311
            128,
312
            read::unsigned(&mut readable).expect("Should read number")
313
        );
314
315
        let buf = [1u8 | CONTINUATION_BIT, 1];
316
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
317
        assert_eq!(
318
            129,
319
            read::unsigned(&mut readable).expect("Should read number")
320
        );
321
322
        let buf = [2u8 | CONTINUATION_BIT, 1];
323
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
324
        assert_eq!(
325
            130,
326
            read::unsigned(&mut readable).expect("Should read number")
327
        );
328
329
        let buf = [57u8 | CONTINUATION_BIT, 100];
330
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
331
        assert_eq!(
332
            12857,
333
            read::unsigned(&mut readable).expect("Should read number")
334
        );
335
    }
336
337
    // Examples from the DWARF 4 standard, section 7.6, figure 23.
338
    #[test]
339
    fn test_read_signed() {
340
        let buf = [2u8];
341
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
342
        assert_eq!(2, read::signed(&mut readable).expect("Should read number"));
343
344
        let buf = [0x7eu8];
345
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
346
        assert_eq!(-2, read::signed(&mut readable).expect("Should read number"));
347
348
        let buf = [127u8 | CONTINUATION_BIT, 0];
349
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
350
        assert_eq!(
351
            127,
352
            read::signed(&mut readable).expect("Should read number")
353
        );
354
355
        let buf = [1u8 | CONTINUATION_BIT, 0x7f];
356
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
357
        assert_eq!(
358
            -127,
359
            read::signed(&mut readable).expect("Should read number")
360
        );
361
362
        let buf = [CONTINUATION_BIT, 1];
363
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
364
        assert_eq!(
365
            128,
366
            read::signed(&mut readable).expect("Should read number")
367
        );
368
369
        let buf = [CONTINUATION_BIT, 0x7f];
370
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
371
        assert_eq!(
372
            -128,
373
            read::signed(&mut readable).expect("Should read number")
374
        );
375
376
        let buf = [1u8 | CONTINUATION_BIT, 1];
377
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
378
        assert_eq!(
379
            129,
380
            read::signed(&mut readable).expect("Should read number")
381
        );
382
383
        let buf = [0x7fu8 | CONTINUATION_BIT, 0x7e];
384
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
385
        assert_eq!(
386
            -129,
387
            read::signed(&mut readable).expect("Should read number")
388
        );
389
    }
390
391
    #[test]
392
    fn test_read_signed_63_bits() {
393
        let buf = [
394
            CONTINUATION_BIT,
395
            CONTINUATION_BIT,
396
            CONTINUATION_BIT,
397
            CONTINUATION_BIT,
398
            CONTINUATION_BIT,
399
            CONTINUATION_BIT,
400
            CONTINUATION_BIT,
401
            CONTINUATION_BIT,
402
            0x40,
403
        ];
404
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
405
        assert_eq!(
406
            -0x4000_0000_0000_0000,
407
            read::signed(&mut readable).expect("Should read number")
408
        );
409
    }
410
411
    #[test]
412
    fn test_read_unsigned_not_enough_data() {
413
        let buf = [CONTINUATION_BIT];
414
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
415
        assert_eq!(
416
            read::unsigned(&mut readable).map_eof(&buf),
417
            Err(Error::UnexpectedEof(ReaderOffsetId(1)))
418
        );
419
    }
420
421
    #[test]
422
    fn test_read_signed_not_enough_data() {
423
        let buf = [CONTINUATION_BIT];
424
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
425
        assert_eq!(
426
            read::signed(&mut readable).map_eof(&buf),
427
            Err(Error::UnexpectedEof(ReaderOffsetId(1)))
428
        );
429
    }
430
431
    #[test]
432
    fn test_write_unsigned_not_enough_space() {
433
        let mut buf = [0; 1];
434
        let mut writable = &mut buf[..];
435
        match write::unsigned(&mut writable, 128) {
436
            Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero),
437
            otherwise => panic!("Unexpected: {:?}", otherwise),
438
        }
439
    }
440
441
    #[test]
442
    fn test_write_signed_not_enough_space() {
443
        let mut buf = [0; 1];
444
        let mut writable = &mut buf[..];
445
        match write::signed(&mut writable, 128) {
446
            Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero),
447
            otherwise => panic!("Unexpected: {:?}", otherwise),
448
        }
449
    }
450
451
    #[test]
452
    fn dogfood_signed() {
453
        fn inner(i: i64) {
454
            let mut buf = [0u8; 1024];
455
456
            {
457
                let mut writable = &mut buf[..];
458
                write::signed(&mut writable, i).expect("Should write signed number");
459
            }
460
461
            let mut readable = EndianSlice::new(&buf[..], NativeEndian);
462
            let result = read::signed(&mut readable).expect("Should be able to read it back again");
463
            assert_eq!(i, result);
464
        }
465
        for i in -513..513 {
466
            inner(i);
467
        }
468
        inner(core::i64::MIN);
469
    }
470
471
    #[test]
472
    fn dogfood_unsigned() {
473
        for i in 0..1025 {
474
            let mut buf = [0u8; 1024];
475
476
            {
477
                let mut writable = &mut buf[..];
478
                write::unsigned(&mut writable, i).expect("Should write signed number");
479
            }
480
481
            let mut readable = EndianSlice::new(&buf[..], NativeEndian);
482
            let result =
483
                read::unsigned(&mut readable).expect("Should be able to read it back again");
484
            assert_eq!(i, result);
485
        }
486
    }
487
488
    #[test]
489
    fn test_read_unsigned_overflow() {
490
        let buf = [
491
            2u8 | CONTINUATION_BIT,
492
            2 | CONTINUATION_BIT,
493
            2 | CONTINUATION_BIT,
494
            2 | CONTINUATION_BIT,
495
            2 | CONTINUATION_BIT,
496
            2 | CONTINUATION_BIT,
497
            2 | CONTINUATION_BIT,
498
            2 | CONTINUATION_BIT,
499
            2 | CONTINUATION_BIT,
500
            2 | CONTINUATION_BIT,
501
            2 | CONTINUATION_BIT,
502
            2 | CONTINUATION_BIT,
503
            2 | CONTINUATION_BIT,
504
            2 | CONTINUATION_BIT,
505
            2 | CONTINUATION_BIT,
506
            2 | CONTINUATION_BIT,
507
            2 | CONTINUATION_BIT,
508
            2 | CONTINUATION_BIT,
509
            2 | CONTINUATION_BIT,
510
            2 | CONTINUATION_BIT,
511
            2 | CONTINUATION_BIT,
512
            2 | CONTINUATION_BIT,
513
            2 | CONTINUATION_BIT,
514
            2 | CONTINUATION_BIT,
515
            2 | CONTINUATION_BIT,
516
            2 | CONTINUATION_BIT,
517
            2 | CONTINUATION_BIT,
518
            2 | CONTINUATION_BIT,
519
            2 | CONTINUATION_BIT,
520
            2 | CONTINUATION_BIT,
521
            1,
522
        ];
523
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
524
        assert!(read::unsigned(&mut readable).is_err());
525
    }
526
527
    #[test]
528
    fn test_read_signed_overflow() {
529
        let buf = [
530
            2u8 | CONTINUATION_BIT,
531
            2 | CONTINUATION_BIT,
532
            2 | CONTINUATION_BIT,
533
            2 | CONTINUATION_BIT,
534
            2 | CONTINUATION_BIT,
535
            2 | CONTINUATION_BIT,
536
            2 | CONTINUATION_BIT,
537
            2 | CONTINUATION_BIT,
538
            2 | CONTINUATION_BIT,
539
            2 | CONTINUATION_BIT,
540
            2 | CONTINUATION_BIT,
541
            2 | CONTINUATION_BIT,
542
            2 | CONTINUATION_BIT,
543
            2 | CONTINUATION_BIT,
544
            2 | CONTINUATION_BIT,
545
            2 | CONTINUATION_BIT,
546
            2 | CONTINUATION_BIT,
547
            2 | CONTINUATION_BIT,
548
            2 | CONTINUATION_BIT,
549
            2 | CONTINUATION_BIT,
550
            2 | CONTINUATION_BIT,
551
            2 | CONTINUATION_BIT,
552
            2 | CONTINUATION_BIT,
553
            2 | CONTINUATION_BIT,
554
            2 | CONTINUATION_BIT,
555
            2 | CONTINUATION_BIT,
556
            2 | CONTINUATION_BIT,
557
            2 | CONTINUATION_BIT,
558
            2 | CONTINUATION_BIT,
559
            2 | CONTINUATION_BIT,
560
            1,
561
        ];
562
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
563
        assert!(read::signed(&mut readable).is_err());
564
    }
565
566
    #[test]
567
    fn test_read_multiple() {
568
        let buf = [2u8 | CONTINUATION_BIT, 1u8, 1u8];
569
570
        let mut readable = EndianSlice::new(&buf[..], NativeEndian);
571
        assert_eq!(
572
            read::unsigned(&mut readable).expect("Should read first number"),
573
            130u64
574
        );
575
        assert_eq!(
576
            read::unsigned(&mut readable).expect("Should read first number"),
577
            1u64
578
        );
579
    }
580
581
    #[test]
582
    fn test_read_u16() {
583
        for (buf, val) in [
584
            (&[2][..], 2),
585
            (&[0x7f][..], 0x7f),
586
            (&[0x80, 1][..], 0x80),
587
            (&[0x81, 1][..], 0x81),
588
            (&[0x82, 1][..], 0x82),
589
            (&[0xff, 0x7f][..], 0x3fff),
590
            (&[0x80, 0x80, 1][..], 0x4000),
591
            (&[0xff, 0xff, 1][..], 0x7fff),
592
            (&[0xff, 0xff, 3][..], 0xffff),
593
        ]
594
        .iter()
595
        {
596
            let mut readable = EndianSlice::new(buf, NativeEndian);
597
            assert_eq!(*val, read::u16(&mut readable).expect("Should read number"));
598
        }
599
600
        for buf in [
601
            &[0x80][..],
602
            &[0x80, 0x80][..],
603
            &[0x80, 0x80, 4][..],
604
            &[0x80, 0x80, 0x80, 3][..],
605
        ]
606
        .iter()
607
        {
608
            let mut readable = EndianSlice::new(buf, NativeEndian);
609
            assert!(read::u16(&mut readable).is_err(), "{:?}", buf);
610
        }
611
    }
612
}