Repository: luser/rust-minidump (rust)

Issue:
Integer overflow in stack walker when processing minidump.
Apologies for the very poorly minimised test case, just making a note of this now so I don't forget.

The bug is in the stack walker, but I found this when fuzzing `minidump_processor`.

```
thread 'test_stack_walk_overflow' panicked at 'attempt to add with overflow', /home/jess/src/rust-minidump/minidump-processor/src/stackwalker/x86.rs:165:21
```

<summary>
it's like 300 lines long, i hid it here
<details>

```rust
#[test]
fn test_stack_walk_overflow() {
    let symbols = [
        116, 32, 118, 105, 115, 117, 97, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48,
        45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116,
    ];

    let dump = [
        80, 77, 68, 77, 0, 0, 167, 147, 0, 0, 0, 62, 0, 0, 0, 0, 0, 167, 147, 0, 0, 7, 0, 0, 0, 0,
        1, 22, 249, 1, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 1, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 39,
        0, 80, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 128, 0, 0, 0, 0, 0, 255, 255, 255, 249, 0, 0, 7,
        27, 0, 0, 0, 1, 0, 0, 18, 0, 0, 0, 0, 255, 255, 255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
        0, 80, 3, 186, 74, 74, 74, 74, 74, 74, 74, 74, 74, 4, 255, 255, 0, 0, 0, 0, 0, 255, 0, 33,
        0, 11, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 3, 1, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 255, 255, 255,
        255, 255, 255, 255, 92, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 56, 0, 0, 0, 37, 80, 77, 68, 77, 88,
        120, 255, 238, 39, 0, 251, 0, 162, 162, 162, 0, 0, 109, 109, 109, 0, 0, 0, 0, 0, 0, 0, 1,
        80, 77, 68, 77, 37, 0, 167, 147, 0, 0, 0, 7, 0, 0, 0, 117, 0, 0, 0, 9, 0, 2, 147, 1, 0, 0,
        0, 0, 0, 0, 32, 80, 0, 67, 3, 0, 1, 0, 145, 5, 0, 0, 0, 0, 0, 0, 46, 0, 0, 85, 0, 0, 0, 0,
        7, 1, 0, 0, 255, 251, 0, 1, 101, 0, 0, 0, 0, 7, 32, 32, 32, 32, 32, 32, 54, 45, 57, 32, 77,
        68, 77, 80, 147, 167, 97, 0, 43, 0, 0, 0, 0, 0, 0, 0, 147, 167, 245, 245, 10, 10, 32, 32,
        32, 32, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, 48, 45, 49, 32, 245, 10, 10, 4, 0, 0,
        0, 0, 90, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 80, 77, 68, 77, 0, 0, 167, 147, 0, 0, 0,
        62, 0, 0, 0, 0, 0, 167, 147, 0, 0, 7, 0, 0, 0, 2, 0, 24, 0, 0, 90, 0, 9, 253, 0, 0, 7, 0,
        0, 0, 1, 0, 0, 0, 0, 10, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 0, 187, 1, 80, 77, 68,
        77, 37, 0, 167, 147, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 4, 255, 251, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 137, 0, 0, 0, 76, 68, 77,
        80, 0, 0, 0, 0, 0, 77, 68, 46, 6, 0, 0, 0, 0, 0, 1, 0, 82, 0, 0, 0, 0, 1, 0, 0, 0, 239, 1,
        0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 168, 1, 0, 0, 0, 0, 0, 1, 138, 0, 0, 0, 32, 0, 0, 0,
        255, 80, 77, 68, 77, 0, 0, 167, 147, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 100,
        0, 1, 22, 249, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
        255, 255, 255, 255, 0, 255, 0, 155, 64, 0, 0, 3, 39, 0, 80, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        4, 167, 147, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 137, 0, 0, 9, 0, 0, 0, 103, 71, 0, 0, 0, 0, 77,
        68, 46, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0,
        0, 0, 0, 0, 88, 254, 0, 0, 0, 0, 0, 1, 138, 0, 0, 32, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0,
        0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 37, 80, 77, 68, 77, 88, 120, 255,
        238, 39, 0, 0, 0, 162, 162, 162, 0, 0, 109, 109, 109, 0, 0, 0, 0, 0, 0, 0, 1, 80, 77, 68,
        77, 37, 0, 167, 147, 0, 0, 0, 7, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 147, 0, 3, 0, 0, 0, 0, 7,
        0, 0, 3, 67, 80, 10, 10, 32, 32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10,
        10, 10, 10, 10, 10, 10, 10, 10, 45, 10, 46, 10, 11, 10, 10, 237, 10, 10, 10, 10, 1, 0, 0,
        0, 0, 0, 0, 8, 45, 10, 10, 10, 10, 10, 10, 21, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105,
        108, 101, 115, 92, 109, 105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97,
        245, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77,
        80, 115, 116, 117, 147, 64, 0, 0, 3, 0, 0, 80, 77, 68, 77, 0, 0, 0, 7, 0, 0, 0, 0, 12, 0,
        4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 64, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 208, 0, 0, 9, 45, 49, 32, 0, 0, 0,
        43, 0, 0, 0, 0, 0, 0, 0, 41, 65, 138, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
        49, 45, 49, 32, 49, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 112,
        32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 45, 10, 10, 10,
        10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 49, 32,
        0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 45, 10, 46, 10, 11, 10,
        10, 237, 10, 10, 10, 10, 1, 0, 0, 0, 0, 0, 0, 8, 45, 10, 10, 10, 10, 10, 10, 21, 10, 114,
        111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115, 92, 109, 105, 99, 114, 111, 115, 111,
        102, 116, 32, 118, 105, 115, 117, 97, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
        48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116, 117, 147, 64, 0, 0, 3, 0, 0, 80, 77, 68,
        77, 0, 0, 0, 7, 0, 0, 0, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0,
        0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 208, 0, 0,
        9, 63, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 37, 80, 77, 68, 77, 88,
        120, 255, 238, 39, 0, 0, 0, 100, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        168, 1, 0, 0, 0, 0, 0, 1, 138, 0, 0, 0, 0, 83, 64, 41, 0, 0, 255, 0, 0, 128, 0, 0, 0, 0, 4,
        0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 37, 80, 77, 68, 77, 88, 120, 255, 238, 39, 0, 0, 0,
        162, 162, 162, 0, 0, 109, 109, 109, 0, 0, 0, 0, 0, 0, 0, 1, 80, 77, 68, 77, 37, 0, 167,
        147, 0, 0, 0, 7, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 147, 0, 3, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 3, 246, 255, 253, 115, 111, 10, 0, 32, 118, 105, 115, 117, 97, 108, 32, 115,
        116, 117, 100, 105, 111, 32, 57, 92, 118, 99, 92, 112, 108, 97, 116, 102, 111, 114, 109,
        115, 100, 107, 92, 105, 110, 99, 108, 117, 100, 101, 92, 119, 105, 110, 118, 101, 114, 46,
        104, 13, 10, 70, 73, 76, 69, 32, 49, 57, 32, 99, 58, 92, 32, 32, 32, 32, 32, 32, 32, 32,
        49, 45, 49, 32, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 41, 65, 138, 32, 245, 10, 10, 32, 32, 32,
        32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 49, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32,
        32, 32, 49, 45, 49, 112, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10,
        10, 10, 10, 45, 10, 10, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32,
        32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        10, 45, 10, 46, 10, 11, 10, 10, 237, 10, 10, 10, 10, 1, 0, 0, 0, 0, 0, 0, 8, 45, 10, 10,
        10, 10, 10, 10, 21, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115, 92, 109,
        105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97, 245, 245, 10, 10, 32,
        32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116, 117,
        147, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115, 92, 109, 105, 99, 114,
        111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97, 245, 245, 10, 10, 32, 32, 32, 32, 32,
        32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116, 117, 147, 0, 0, 0, 0, 0,
        0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 10,
        10, 10, 10, 10, 45, 10, 10, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32, 32, 32, 32,
        32, 32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
        241, 241, 241, 241, 241, 241, 241, 241, 241, 142, 241, 241, 241, 241, 241, 241, 241, 241,
        241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
        241, 76, 69, 32, 49, 57, 32, 99, 32, 32, 32, 49, 45, 49, 32, 245, 10, 10, 32, 32, 32, 32,
        32, 32, 32, 32, 32, 48, 45, 49, 32, 49, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32,
        32, 49, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 45,
        10, 46, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32, 32, 32, 0, 91, 7, 35, 0, 0, 0,
        0, 0, 127, 10, 45, 10, 46, 10, 10, 10, 10, 237, 245, 245, 245, 48, 10, 32, 32, 32, 32, 32,
        32, 32, 32, 32, 49, 45, 49, 32, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 41, 65, 138, 32, 245, 10,
        10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 8, 0, 134, 134, 242, 168, 134, 166,
        134, 134, 185, 126, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 105, 0, 0, 0, 1, 138, 0, 0, 0, 0, 83,
        64, 41, 0, 0, 255, 0, 0, 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 37,
        80, 77, 68, 77, 88, 120, 255, 238, 39, 0, 0, 0, 162, 162, 162, 0, 0, 109, 109, 109, 0, 0,
        0, 0, 0, 0, 0, 1, 80, 77, 68, 77, 37, 0, 167, 147, 0, 0, 0, 7, 0, 0, 0, 117, 0, 0, 0, 0, 0,
        0, 147, 0, 3, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 246, 255, 253, 115, 111, 10, 0,
        32, 118, 105, 115, 117, 97, 108, 32, 115, 116, 117, 100, 105, 111, 32, 57, 92, 118, 99, 92,
        112, 108, 97, 116, 102, 111, 114, 109, 115, 100, 107, 92, 105, 110, 99, 108, 117, 100, 101,
        92, 119, 105, 110, 118, 101, 114, 46, 104, 13, 10, 70, 73, 32, 99, 58, 92, 32, 32, 32, 32,
        32, 32, 32, 32, 49, 45, 49, 32, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 41, 65, 138, 32, 245, 10,
        10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 49, 32, 245, 10, 10, 32, 32, 32,
        32, 32, 32, 32, 32, 32, 49, 45, 49, 112, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        10, 0, 10, 10, 10, 10, 10, 45, 10, 10, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32,
        32, 32, 32, 32, 32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        10, 10, 10, 10, 10, 45, 10, 46, 10, 11, 10, 10, 237, 10, 10, 10, 10, 1, 0, 0, 0, 0, 0, 0,
        8, 45, 10, 10, 10, 10, 10, 10, 21, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108, 101,
        115, 92, 109, 105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97, 245, 245,
        10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115,
        116, 117, 147, 64, 0, 0, 3, 0, 0, 80, 77, 68, 77, 0, 0, 0, 7, 0, 0, 0, 0, 12, 0, 4, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 208, 0, 0, 9, 63, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3,
        0, 0, 0, 52, 0, 0, 0, 37, 80, 77, 68, 77, 88, 120, 255, 238, 39, 0, 0, 0, 100, 162, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 1, 0, 0, 0, 0, 0, 1, 138, 0, 0, 0, 0, 83,
        64, 41, 0, 0, 255, 0, 0, 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 37,
        80, 77, 68, 77, 88, 120, 255, 238, 39, 0, 0, 0, 162, 162, 162, 0, 0, 109, 109, 109, 0, 0,
        0, 0, 0, 0, 0, 1, 80, 77, 68, 77, 37, 0, 167, 147, 0, 0, 0, 7, 0, 0, 0, 117, 0, 0, 0, 0, 0,
        0, 147, 0, 3, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 246, 255, 253, 115, 111, 10, 0,
        32, 118, 105, 115, 117, 97, 108, 32, 115, 116, 117, 100, 105, 111, 32, 57, 92, 118, 99, 92,
        112, 108, 97, 116, 102, 111, 114, 109, 115, 100, 107, 92, 105, 110, 99, 108, 117, 100, 101,
        92, 119, 105, 110, 118, 101, 114, 46, 104, 13, 10, 70, 73, 76, 69, 32, 49, 57, 32, 99, 58,
        92, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 41,
        65, 138, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 49, 32, 245,
        10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 112, 32, 0, 0, 0, 10, 10, 10, 10,
        10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 45, 10, 10, 10, 10, 10, 10, 237, 245, 245,
        245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10,
        10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 45, 10, 46, 10, 11, 10, 10, 237, 10, 10, 10, 10, 1,
        0, 0, 0, 0, 0, 0, 8, 45, 10, 10, 10, 10, 10, 10, 21, 10, 114, 111, 103, 124, 97, 1, 11,
        102, 105, 108, 101, 115, 92, 109, 105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115,
        117, 97, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108,
        32, 77, 80, 115, 116, 117, 147, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115,
        92, 109, 105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97, 245, 245, 10,
        10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116,
        117, 147, 107, 92, 105, 110, 99, 108, 117, 100, 101, 92, 119, 105, 110, 118, 101, 114, 46,
        104, 13, 10, 70, 73, 76, 69, 32, 49, 57, 32, 99, 58, 92, 32, 32, 32, 32, 32, 32, 32, 32,
        49, 45, 49, 32, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 41, 65, 138, 32, 245, 10, 10, 32, 32, 32,
        32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 49, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32,
        32, 32, 49, 45, 49, 112, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10,
        10, 10, 10, 45, 10, 10, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32,
        32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        10, 45, 10, 46, 10, 11, 10, 10, 237, 10, 10, 10, 10, 1, 0, 0, 0, 0, 0, 0, 8, 45, 10, 10,
        10, 10, 10, 10, 21, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115, 92, 109,
        105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97, 245, 245, 10, 10, 32,
        32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116, 117,
        147, 64, 0, 0, 3, 0, 0, 80, 77, 68, 77, 0, 0, 0, 7, 0, 0, 0, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 6, 0, 0, 0, 208, 0, 0, 9, 63, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 52,
        0, 0, 0, 37, 80, 77, 68, 77, 88, 120, 255, 238, 39, 0, 0, 0, 100, 162, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 1, 0, 0, 0, 0, 0, 1, 138, 0, 0, 0, 0, 83, 64, 41, 0, 0,
        255, 0, 0, 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 37, 80, 77, 68, 77,
        88, 120, 255, 238, 39, 0, 0, 0, 162, 162, 162, 0, 0, 109, 109, 109, 0, 0, 0, 0, 0, 0, 0, 1,
        80, 77, 68, 77, 37, 0, 167, 147, 0, 0, 0, 7, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 147, 0, 3, 0,
        0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 246, 255, 253, 115, 111, 10, 0, 32, 118, 105,
        115, 117, 97, 108, 32, 115, 116, 117, 100, 105, 111, 32, 57, 92, 118, 99, 92, 112, 108, 97,
        116, 102, 111, 114, 109, 115, 100, 107, 92, 105, 110, 99, 108, 117, 100, 101, 92, 119, 105,
        110, 118, 101, 114, 46, 104, 13, 10, 70, 73, 76, 69, 32, 49, 57, 32, 99, 58, 92, 32, 32,
        32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 41, 65, 138, 32,
        245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 49, 32, 245, 10, 10, 32,
        32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 112, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10,
        10, 10, 10, 0, 10, 10, 10, 10, 10, 45, 10, 10, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10,
        32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10,
        10, 10, 10, 10, 10, 10, 10, 45, 10, 46, 10, 11, 10, 10, 237, 10, 10, 10, 10, 1, 0, 0, 0, 0,
        0, 0, 8, 45, 10, 10, 10, 10, 10, 10, 21, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108,
        101, 115, 92, 109, 105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97, 245,
        245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77, 80,
        115, 116, 117, 147, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115, 92, 109,
        105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97, 245, 245, 10, 10, 32,
        32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116, 117,
        147, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
        32, 32, 32, 0, 10, 10, 10, 10, 10, 45, 10, 10, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10,
        32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10,
        10, 10, 10, 10, 10, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
        241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 142, 241, 241, 241, 241,
        241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
        241, 241, 241, 241, 241, 76, 69, 32, 49, 57, 32, 99, 32, 32, 32, 49, 45, 49, 32, 245, 10,
        10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 49, 32, 49, 32, 245, 10, 10, 32, 32, 32,
        32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        10, 10, 10, 10, 45, 10, 46, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32, 32, 32, 0,
        91, 7, 35, 0, 0, 0, 0, 0, 127, 10, 45, 10, 46, 10, 10, 10, 10, 237, 245, 245, 245, 48, 10,
        32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 41,
        65, 138, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 8, 0, 134,
        134, 242, 168, 134, 166, 134, 134, 185, 126, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 105, 0, 0, 0,
        1, 138, 0, 0, 0, 0, 83, 64, 41, 0, 0, 255, 0, 0, 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0,
        0, 0, 52, 0, 0, 0, 37, 80, 77, 68, 77, 88, 120, 255, 238, 39, 0, 0, 0, 162, 162, 162, 0, 0,
        109, 109, 109, 0, 0, 0, 0, 0, 0, 0, 1, 80, 77, 68, 77, 37, 0, 167, 147, 0, 0, 0, 7, 0, 0,
        0, 117, 0, 0, 0, 0, 0, 0, 147, 0, 3, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 246, 255,
        253, 115, 111, 10, 0, 32, 118, 105, 115, 117, 97, 108, 32, 115, 116, 117, 100, 105, 111,
        32, 57, 92, 118, 99, 92, 112, 108, 97, 116, 102, 111, 114, 109, 115, 100, 107, 92, 105,
        110, 99, 108, 117, 100, 101, 92, 119, 105, 110, 118, 101, 114, 46, 104, 13, 10, 70, 73, 76,
        69, 32, 49, 57, 32, 99, 58, 92, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 0, 0, 0,
        43, 0, 0, 0, 0, 0, 0, 0, 41, 65, 138, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
        49, 45, 49, 32, 49, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 45, 49, 112,
        32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 45, 10, 10, 10,
        10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 49, 32,
        0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 45, 10, 46, 10, 11, 10,
        10, 237, 10, 10, 10, 10, 1, 0, 0, 0, 0, 0, 0, 8, 45, 10, 10, 10, 10, 10, 10, 21, 10, 114,
        111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115, 92, 109, 105, 99, 114, 111, 115, 111,
        102, 116, 32, 118, 105, 115, 117, 97, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
        48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116, 117, 147, 64, 0, 0, 3, 0, 0, 80, 77, 68,
        77, 0, 0, 0, 7, 0, 0, 0, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0,
        0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 208, 0, 0,
        9, 63, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 37, 80, 77, 68, 77, 88,
        120, 255, 238, 39, 0, 0, 0, 100, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        168, 1, 0, 0, 0, 0, 0, 1, 138, 0, 0, 0, 0, 83, 64, 41, 0, 0, 255, 0, 0, 128, 0, 0, 0, 0, 4,
        0, 0, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 37, 80, 77, 68, 77, 88, 120, 255, 238, 39, 0, 0, 0,
        162, 162, 162, 0, 0, 109, 109, 109, 0, 0, 0, 0, 0, 0, 0, 1, 80, 77, 68, 77, 37, 0, 167,
        147, 0, 0, 0, 7, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 147, 0, 3, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 3, 246, 255, 253, 115, 111, 10, 0, 32, 118, 105, 115, 117, 97, 108, 32, 115,
        116, 117, 100, 105, 111, 32, 57, 92, 118, 99, 92, 112, 108, 97, 116, 102, 111, 114, 109,
        115, 100, 107, 92, 105, 110, 99, 108, 117, 100, 101, 92, 119, 105, 110, 118, 101, 114, 46,
        104, 13, 10, 70, 73, 76, 69, 32, 49, 57, 32, 99, 58, 92, 32, 32, 32, 32, 32, 32, 32, 32,
        49, 45, 49, 32, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 41, 65, 138, 32, 245, 10, 10, 32, 32, 32,
        32, 32, 32, 32, 32, 32, 49, 45, 49, 32, 49, 32, 245, 10, 10, 32, 32, 32, 32, 32, 32, 32,
        32, 32, 49, 45, 49, 112, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10,
        10, 10, 10, 45, 10, 10, 10, 10, 10, 10, 237, 245, 245, 245, 10, 10, 32, 32, 32, 32, 32, 32,
        32, 32, 32, 48, 45, 49, 32, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        10, 45, 10, 46, 10, 11, 10, 10, 237, 10, 10, 10, 10, 1, 0, 0, 0, 0, 0, 0, 8, 45, 10, 10,
        10, 10, 10, 10, 21, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115, 92, 109,
        105, 99, 114, 111, 115, 111, 102, 116, 32, 118, 105, 115, 117, 97, 245, 245, 10, 10, 32,
        32, 32, 32, 32, 32, 32, 32, 32, 48, 45, 57, 32, 77, 68, 108, 32, 77, 80, 115, 116, 117,
        147, 10, 114, 111, 103, 124, 97, 1, 11, 102, 105, 108, 101, 115, 92, 109, 105, 99, 114,
        111, 115, 111, 102,
    ];

    struct StaticSymbolSupplier {
        file: Vec<u8>,
    }

    impl minidump_processor::SymbolSupplier for StaticSymbolSupplier {
        fn locate_symbols(
            &self,
            _module: &dyn minidump::Module,
        ) -> Result<minidump_processor::SymbolFile, minidump_processor::SymbolError> {
            minidump_processor::SymbolFile::from_bytes(&self.file)
        }
    }

    let dump = minidump::Minidump::read(&dump[..]).unwrap();
    let supplier = StaticSymbolSupplier {
        file: symbols.to_vec(),
    };
    let provider = minidump_processor::Symbolizer::new(supplier);
    let _ = minidump_processor::process_minidump(&dump, &provider);
}
```
</details>
</summary>

Pull request:
Harden 32-bit unwinders against mixed-width calculations.
Fixes #422

This issue is kinda nonsense, but in a 'hey good job fuzzer for finding this wild input' kinda way?
Basically rust-minidump likes doing things in 64-bit to reuse code and keep things uniform, but this
creates a fun situation where you can define *impossible* memory ranges for a 32-bit system and have
calculated pointers successfully access that memory because the operations are happening in 64-bit.

In-and-of-itself this is not a problem, but it does mean that things can go Bad when you have some
of the operations happening in the platform's native width, causing some operations to succeed and
others to overflow. In particular, this would allow you to load some memory that is beyond u32::MAX
(which normally would be a strong proof that the entire memory range is a valid pointer) and then
update the 32-bit frame pointer to that address, causing an overflow.

The fix is to simply do the overflow check that *already existed for exactly this code* in 32-bit
instead of 64-bit. I'm not sure if an actual minidump would have been able to trigger this bug,
since it's possible some earlier code would have freaked out at the memory range definitions.
But hey, the guards were wrong either way.

Patch:
diff --git a/minidump-processor/src/stackwalker/arm.rs b/minidump-processor/src/stackwalker/arm.rs
index dcfc1d1..a34aa71 100644
--- a/minidump-processor/src/stackwalker/arm.rs
+++ b/minidump-processor/src/stackwalker/arm.rs
@@ -127,7 +127,7 @@ where
     // Unlike ARM64, we don't bother trying really hard to restore lr
     let last_lr = ctx.get_register(LINK_REGISTER, valid)?;
 
-    if last_fp as u64 >= u64::MAX - POINTER_WIDTH as u64 * 2 {
+    if last_fp as u32 >= u32::MAX - POINTER_WIDTH as u32 * 2 {
         // Although this code generally works fine if the pointer math overflows,
         // debug builds will still panic, and this guard protects against it without
         // drowning the rest of the code in checked_add.
diff --git a/minidump-processor/src/stackwalker/x86.rs b/minidump-processor/src/stackwalker/x86.rs
index 0514c27..11db053 100644
--- a/minidump-processor/src/stackwalker/x86.rs
+++ b/minidump-processor/src/stackwalker/x86.rs
@@ -154,7 +154,7 @@ where
     // %bp_new = *(%bp_old)
     // %sp_new = %bp_old + ptr*2
 
-    if last_bp as u64 >= u64::MAX - POINTER_WIDTH as u64 * 2 {
+    if last_bp as u32 >= u32::MAX - POINTER_WIDTH as u32 * 2 {
         // Although this code generally works fine if the pointer math overflows,
         // debug builds will still panic, and this guard protects against it without
         // drowning the rest of the code in checked_add.


Test patch:
diff --git a/minidump-processor/src/stackwalker/amd64_unittest.rs b/minidump-processor/src/stackwalker/amd64_unittest.rs
index bd38410..1b672b5 100644
--- a/minidump-processor/src/stackwalker/amd64_unittest.rs
+++ b/minidump-processor/src/stackwalker/amd64_unittest.rs
@@ -562,29 +562,103 @@ fn test_cfi_at_4006() {
 }
 
 #[test]
-fn test_overflow() {
+fn test_frame_pointer_overflow() {
     // Make sure we don't explode when trying frame pointer analysis on a value
     // that will overflow.
 
-    // Functions typically push their %rbp upon entry and set %rbp pointing
-    // there.  If stackwalking finds a plausible address for the next frame's
-    // %rbp directly below the return address, assume that it is indeed the
-    // next frame's %rbp.
+    type Pointer = u64;
+    let stack_max: Pointer = Pointer::MAX;
+    let stack_size: Pointer = 1000;
+    let bad_frame_ptr: Pointer = stack_max;
+
     let mut f = TestFixture::new();
     let mut stack = Section::new();
-    let stack_start = 0x8000000080000000;
-    stack.start().set_const(stack_start);
+    let stack_start: Pointer = stack_max - stack_size;
+    stack.start().set_const(stack_start as u64);
 
     stack = stack
         // frame 0
-        .append_repeated(0, 1000); // junk, not important to the test
+        .append_repeated(0, stack_size as usize); // junk, not important to the test
 
     f.raw.rip = 0x00007400c0000200;
-    f.raw.rbp = u64::MAX;
-    f.raw.rsp = stack.start().value().unwrap();
+    f.raw.rbp = bad_frame_ptr;
+    f.raw.rsp = stack.start().value().unwrap() as Pointer;
 
     let s = f.walk_stack(stack);
     assert_eq!(s.frames.len(), 1);
 
     // As long as we don't panic, we're good!
 }
+
+#[test]
+fn test_frame_pointer_barely_no_overflow() {
+    // This is test_caller_pushed_rbp but with the all the values pushed
+    // as close to the upper memory boundary as possible, to confirm that
+    // our code doesn't randomly overflow *AND* isn't overzealous in
+    // its overflow guards.
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+
+    type Pointer = u64;
+    let stack_max: Pointer = Pointer::MAX;
+    let pointer_size: Pointer = std::mem::size_of::<Pointer>() as Pointer;
+    let stack_size: Pointer = pointer_size * 3;
+
+    let stack_start: Pointer = stack_max - stack_size;
+    let return_address: Pointer = 0x00007500b0000110;
+    stack.start().set_const(stack_start as u64);
+
+    let frame0_fp = Label::new();
+    let frame1_sp = Label::new();
+    let frame1_fp = Label::new();
+
+    stack = stack
+        // frame 0
+        .mark(&frame0_fp)
+        .D64(&frame1_fp) // caller-pushed %rbp
+        .D64(return_address) // actual return address
+        // frame 1
+        .mark(&frame1_sp)
+        .mark(&frame1_fp) // end of stack
+        .D64(0);
+
+    f.raw.rip = 0x00007400c0000200;
+    f.raw.rbp = frame0_fp.value().unwrap() as Pointer;
+    f.raw.rsp = stack.start().value().unwrap();
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 2);
+
+    {
+        // To avoid reusing locals by mistake
+        let f0 = &s.frames[0];
+        assert_eq!(f0.trust, FrameTrust::Context);
+        assert_eq!(f0.context.valid, MinidumpContextValidity::All);
+        if let MinidumpRawContext::Amd64(ctx) = &f0.context.raw {
+            assert_eq!(ctx.rbp, frame0_fp.value().unwrap() as Pointer);
+        } else {
+            unreachable!();
+        }
+    }
+
+    {
+        // To avoid reusing locals by mistake
+        let f1 = &s.frames[1];
+        assert_eq!(f1.trust, FrameTrust::FramePointer);
+        if let MinidumpContextValidity::Some(ref which) = f1.context.valid {
+            assert!(which.contains("rip"));
+            assert!(which.contains("rsp"));
+            assert!(which.contains("rbp"));
+        } else {
+            unreachable!();
+        }
+        if let MinidumpRawContext::Amd64(ctx) = &f1.context.raw {
+            assert_eq!(ctx.rip, return_address);
+            assert_eq!(ctx.rsp, frame1_sp.value().unwrap() as Pointer);
+            assert_eq!(ctx.rbp, frame1_fp.value().unwrap() as Pointer);
+        } else {
+            unreachable!();
+        }
+    }
+}
diff --git a/minidump-processor/src/stackwalker/arm64_unittest.rs b/minidump-processor/src/stackwalker/arm64_unittest.rs
index 4b8735c..4d11c2d 100644
--- a/minidump-processor/src/stackwalker/arm64_unittest.rs
+++ b/minidump-processor/src/stackwalker/arm64_unittest.rs
@@ -850,3 +850,122 @@ fn test_cfi_reject_bad_exprs() {
     let s = f.walk_stack(stack);
     assert_eq!(s.frames.len(), 1);
 }
+
+#[test]
+fn test_frame_pointer_overflow() {
+    // Make sure we don't explode when trying frame pointer analysis on a value
+    // that will overflow.
+
+    type Pointer = u64;
+    let stack_max: Pointer = Pointer::MAX;
+    let stack_size: Pointer = 1000;
+    let bad_frame_ptr: Pointer = stack_max;
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+    let stack_start: Pointer = stack_max - stack_size;
+    stack.start().set_const(stack_start as u64);
+
+    stack = stack
+        // frame 0
+        .append_repeated(0, stack_size as usize); // junk, not important to the test
+
+    f.raw.set_register("pc", 0x00007400c0000200);
+    f.raw.set_register("fp", bad_frame_ptr);
+    f.raw
+        .set_register("sp", stack.start().value().unwrap() as Pointer);
+    f.raw.set_register("lr", 0x00007500b0000110);
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 1);
+
+    // As long as we don't panic, we're good!
+}
+
+#[test]
+fn test_frame_pointer_barely_no_overflow() {
+    // This is a simple frame pointer test but with the all the values pushed
+    // as close to the upper memory boundary as possible, to confirm that
+    // our code doesn't randomly overflow *AND* isn't overzealous in
+    // its overflow guards.
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+
+    type Pointer = u64;
+    let stack_max: Pointer = Pointer::MAX;
+    let pointer_size: Pointer = std::mem::size_of::<Pointer>() as Pointer;
+    let stack_size: Pointer = pointer_size * 3;
+
+    let stack_start: Pointer = stack_max - stack_size;
+    let return_address: Pointer = 0x00007500b0000110;
+    stack.start().set_const(stack_start as u64);
+
+    let frame0_fp = Label::new();
+    let frame1_sp = Label::new();
+    let frame1_fp = Label::new();
+
+    stack = stack
+        // frame 0
+        .mark(&frame0_fp)
+        .D64(&frame1_fp) // caller-pushed %rbp
+        .D64(return_address) // actual return address
+        // frame 1
+        .mark(&frame1_sp)
+        .mark(&frame1_fp) // end of stack
+        .D64(0);
+
+    f.raw.set_register("pc", 0x00007400c0000200);
+    f.raw
+        .set_register("fp", frame0_fp.value().unwrap() as Pointer);
+    f.raw
+        .set_register("sp", stack.start().value().unwrap() as Pointer);
+    f.raw.set_register("lr", return_address);
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 2);
+
+    {
+        // Frame 0
+        let frame = &s.frames[0];
+        let valid = &frame.context.valid;
+        assert_eq!(frame.trust, FrameTrust::Context);
+        assert_eq!(frame.context.valid, MinidumpContextValidity::All);
+
+        if let MinidumpRawContext::Arm64(ctx) = &frame.context.raw {
+            assert_eq!(
+                ctx.get_register("fp", valid).unwrap(),
+                frame0_fp.value().unwrap() as Pointer
+            );
+        } else {
+            unreachable!();
+        }
+    }
+
+    {
+        // Frame 1
+        let frame = &s.frames[1];
+        let valid = &frame.context.valid;
+        assert_eq!(frame.trust, FrameTrust::FramePointer);
+        if let MinidumpContextValidity::Some(ref which) = valid {
+            assert_eq!(which.len(), 4);
+        } else {
+            unreachable!();
+        }
+
+        if let MinidumpRawContext::Arm64(ctx) = &frame.context.raw {
+            assert_eq!(ctx.get_register("pc", valid).unwrap(), return_address);
+            assert_eq!(
+                ctx.get_register("sp", valid).unwrap(),
+                frame1_sp.value().unwrap() as Pointer
+            );
+            assert_eq!(
+                ctx.get_register("fp", valid).unwrap(),
+                frame1_fp.value().unwrap() as Pointer
+            );
+            assert_eq!(ctx.get_register("lr", valid).unwrap(), return_address);
+        } else {
+            unreachable!();
+        }
+    }
+}
diff --git a/minidump-processor/src/stackwalker/arm_unittest.rs b/minidump-processor/src/stackwalker/arm_unittest.rs
index 48f5958..8ab9f79 100644
--- a/minidump-processor/src/stackwalker/arm_unittest.rs
+++ b/minidump-processor/src/stackwalker/arm_unittest.rs
@@ -739,3 +739,158 @@ fn test_cfi_reject_bad_exprs() {
     let s = f.walk_stack(stack);
     assert_eq!(s.frames.len(), 1);
 }
+
+#[test]
+fn test_frame_pointer_overflow() {
+    // Make sure we don't explode when trying frame pointer analysis on a value
+    // that will overflow.
+
+    type Pointer = u32;
+    let stack_max: Pointer = Pointer::MAX;
+    let stack_size: Pointer = 1000;
+    let bad_frame_ptr: Pointer = stack_max;
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+    let stack_start: Pointer = stack_max - stack_size;
+    stack.start().set_const(stack_start as u64);
+
+    stack = stack
+        // frame 0
+        .append_repeated(0, stack_size as usize); // junk, not important to the test
+
+    f.raw.set_register("pc", 0x7a100000);
+    f.raw.set_register("fp", bad_frame_ptr);
+    f.raw
+        .set_register("sp", stack.start().value().unwrap() as Pointer);
+    f.raw.set_register("lr", 0x7b302000);
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 1);
+
+    // As long as we don't panic, we're good!
+}
+
+#[test]
+fn test_frame_pointer_overflow_nonsense_32bit_stack() {
+    // same as test_frame_pointer_overflow, but we're going to abuse the fact
+    // that rust-minidump prefers representing things in 64-bit to create
+    // impossible stack addresses that overflow 32-bit integers but appear
+    // valid in 64-bit. By doing this memory reads will "succeed" but
+    // pointer math done in the native pointer width will overflow and
+    // everything will be sad.
+
+    type Pointer = u32;
+    let pointer_size: u64 = std::mem::size_of::<Pointer>() as u64;
+    let stack_max: u64 = Pointer::MAX as u64 + pointer_size * 2;
+    let stack_size: u64 = 1000;
+    let bad_frame_ptr: u64 = Pointer::MAX as u64 - pointer_size;
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+    let stack_start: u64 = stack_max - stack_size;
+    stack.start().set_const(stack_start as u64);
+
+    stack = stack
+        // frame 0
+        .append_repeated(0, 1000); // junk, not important to the test
+
+    f.raw.set_register("pc", 0x7a100000);
+    f.raw.set_register("fp", bad_frame_ptr as u32);
+    f.raw
+        .set_register("sp", stack.start().value().unwrap() as Pointer);
+    f.raw.set_register("lr", 0x7b302000);
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 1);
+
+    // As long as we don't panic, we're good!
+}
+
+#[test]
+fn test_frame_pointer_barely_no_overflow() {
+    // This is a simple frame pointer test but with the all the values pushed
+    // as close to the upper memory boundary as possible, to confirm that
+    // our code doesn't randomly overflow *AND* isn't overzealous in
+    // its overflow guards.
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+
+    type Pointer = u32;
+    let stack_max: Pointer = Pointer::MAX;
+    let pointer_size: Pointer = std::mem::size_of::<Pointer>() as Pointer;
+    let stack_size: Pointer = pointer_size * 3;
+
+    let stack_start: Pointer = stack_max - stack_size;
+    let return_address: Pointer = 0x7b302000;
+    stack.start().set_const(stack_start as u64);
+
+    let frame0_fp = Label::new();
+    let frame1_sp = Label::new();
+    let frame1_fp = Label::new();
+
+    stack = stack
+        // frame 0
+        .mark(&frame0_fp)
+        .D32(&frame1_fp) // caller-pushed %rbp
+        .D32(return_address) // actual return address
+        // frame 1
+        .mark(&frame1_sp)
+        .mark(&frame1_fp) // end of stack
+        .D32(0);
+
+    f.raw.set_register("pc", 0x7a100000);
+    f.raw
+        .set_register("fp", frame0_fp.value().unwrap() as Pointer);
+    f.raw
+        .set_register("sp", stack.start().value().unwrap() as Pointer);
+    f.raw.set_register("lr", return_address);
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 2);
+
+    {
+        // Frame 0
+        let frame = &s.frames[0];
+        let valid = &frame.context.valid;
+        assert_eq!(frame.trust, FrameTrust::Context);
+        assert_eq!(frame.context.valid, MinidumpContextValidity::All);
+
+        if let MinidumpRawContext::Arm(ctx) = &frame.context.raw {
+            assert_eq!(
+                ctx.get_register("fp", valid).unwrap(),
+                frame0_fp.value().unwrap() as Pointer
+            );
+        } else {
+            unreachable!();
+        }
+    }
+
+    {
+        // Frame 1
+        let frame = &s.frames[1];
+        let valid = &frame.context.valid;
+        assert_eq!(frame.trust, FrameTrust::FramePointer);
+        if let MinidumpContextValidity::Some(ref which) = valid {
+            assert_eq!(which.len(), 4);
+        } else {
+            unreachable!();
+        }
+
+        if let MinidumpRawContext::Arm(ctx) = &frame.context.raw {
+            assert_eq!(ctx.get_register("pc", valid).unwrap(), return_address);
+            assert_eq!(
+                ctx.get_register("sp", valid).unwrap(),
+                frame1_sp.value().unwrap() as Pointer
+            );
+            assert_eq!(
+                ctx.get_register("fp", valid).unwrap(),
+                frame1_fp.value().unwrap() as Pointer
+            );
+            assert_eq!(ctx.get_register("lr", valid).unwrap(), return_address);
+        } else {
+            unreachable!();
+        }
+    }
+}
diff --git a/minidump-processor/src/stackwalker/x86_unittest.rs b/minidump-processor/src/stackwalker/x86_unittest.rs
index b12dacf..e9051d8 100644
--- a/minidump-processor/src/stackwalker/x86_unittest.rs
+++ b/minidump-processor/src/stackwalker/x86_unittest.rs
@@ -818,3 +818,139 @@ fn test_stack_win_frame_data_parameter_size() {
         }
     }
 }
+
+#[test]
+fn test_frame_pointer_overflow() {
+    // Make sure we don't explode when trying frame pointer analysis on a value
+    // that will overflow.
+
+    type Pointer = u32;
+    let stack_max: Pointer = Pointer::MAX;
+    let stack_size: Pointer = 1000;
+    let bad_frame_ptr: Pointer = stack_max;
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+    let stack_start: Pointer = stack_max - stack_size;
+    stack.start().set_const(stack_start as u64);
+
+    stack = stack
+        // frame 0
+        .append_repeated(0, stack_size as usize); // junk, not important to the test
+
+    f.raw.eip = 0x7a100000;
+    f.raw.ebp = bad_frame_ptr;
+    f.raw.esp = stack.start().value().unwrap() as Pointer;
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 1);
+
+    // As long as we don't panic, we're good!
+}
+
+#[test]
+fn test_frame_pointer_overflow_nonsense_32bit_stack() {
+    // same as test_frame_pointer_overflow, but we're going to abuse the fact
+    // that rust-minidump prefers representing things in 64-bit to create
+    // impossible stack addresses that overflow 32-bit integers but appear
+    // valid in 64-bit. By doing this memory reads will "succeed" but
+    // pointer math done in the native pointer width will overflow and
+    // everything will be sad.
+
+    type Pointer = u32;
+    let pointer_size: u64 = std::mem::size_of::<Pointer>() as u64;
+    let stack_max: u64 = Pointer::MAX as u64 + pointer_size * 2;
+    let stack_size: u64 = 1000;
+    let bad_frame_ptr: u64 = Pointer::MAX as u64 - pointer_size;
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+    let stack_start: u64 = stack_max - stack_size;
+    stack.start().set_const(stack_start as u64);
+
+    stack = stack
+        // frame 0
+        .append_repeated(0, 1000); // junk, not important to the test
+
+    f.raw.eip = 0x7a100000;
+    f.raw.ebp = bad_frame_ptr as u32;
+    f.raw.esp = stack.start().value().unwrap() as Pointer;
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 1);
+
+    // As long as we don't panic, we're good!
+}
+
+#[test]
+fn test_frame_pointer_barely_no_overflow() {
+    // This is test_tradition but with the all the values pushed
+    // as close to the upper memory boundary as possible, to confirm that
+    // our code doesn't randomly overflow *AND* isn't overzealous in
+    // its overflow guards.
+
+    let mut f = TestFixture::new();
+    let mut stack = Section::new();
+
+    type Pointer = u32;
+    let pointer_size: Pointer = std::mem::size_of::<Pointer>() as Pointer;
+    let stack_max: Pointer = Pointer::MAX;
+    let stack_size: Pointer = pointer_size * 3;
+
+    let stack_start: Pointer = stack_max - stack_size;
+    let return_address: Pointer = 0x7b302000;
+    stack.start().set_const(stack_start as u64);
+
+    let frame0_fp = Label::new();
+    let frame1_sp = Label::new();
+    let frame1_fp = Label::new();
+
+    stack = stack
+        // frame 0
+        .mark(&frame0_fp)
+        .D32(&frame1_fp) // caller-pushed %rbp
+        .D32(return_address) // actual return address
+        // frame 1
+        .mark(&frame1_sp)
+        .mark(&frame1_fp) // end of stack
+        .D32(0);
+
+    f.raw.eip = 0x7a100000;
+    f.raw.ebp = frame0_fp.value().unwrap() as Pointer;
+    f.raw.esp = stack.start().value().unwrap() as Pointer;
+
+    let s = f.walk_stack(stack);
+    assert_eq!(s.frames.len(), 2);
+
+    {
+        // To avoid reusing locals by mistake
+        let f0 = &s.frames[0];
+        assert_eq!(f0.trust, FrameTrust::Context);
+        assert_eq!(f0.context.valid, MinidumpContextValidity::All);
+        if let MinidumpRawContext::X86(ctx) = &f0.context.raw {
+            assert_eq!(ctx.ebp, frame0_fp.value().unwrap() as Pointer);
+        } else {
+            unreachable!();
+        }
+    }
+
+    {
+        // To avoid reusing locals by mistake
+        let f1 = &s.frames[1];
+        assert_eq!(f1.trust, FrameTrust::FramePointer);
+        if let MinidumpContextValidity::Some(ref which) = f1.context.valid {
+            assert!(which.contains("eip"));
+            assert!(which.contains("esp"));
+            assert!(which.contains("ebp"));
+        } else {
+            unreachable!();
+        }
+        if let MinidumpRawContext::X86(ctx) = &f1.context.raw {
+            assert_eq!(ctx.eip, return_address);
+            assert_eq!(ctx.esp, frame1_sp.value().unwrap() as Pointer);
+            assert_eq!(ctx.ebp, frame1_fp.value().unwrap() as Pointer);
+        } else {
+            unreachable!();
+        }
+    }
+}