Skip to content

Infinite loop when creating buffer #37

@michel-kraemer

Description

@michel-kraemer

Summary

First of all, thank you so much for this great library. It's very fast and typically extremely reliable. Keep up the good work!

I'm using iOverlay through the geo crate. When I execute the minimal reproducer below, iOverlay will end up in an infinite loop and will quickly use up gigabytes of main memory (be careful if you want to execute it on your machine!).

It appears there is a problem with large floating-point values. As soon as I remove a few digits after the decimal point or even the digits "589" from the beginning of the y-coordinates, everything works fine. However, geospatial coordinates are often quite large and we can't control the input data from users. So I'm wondering if I should trim the coordinates (which I'd prefer not to do as it loses precision) or if this is a bug that can be fixed.

Steps to reproduce

Create a new project with cargo and add the geo crate as dependency (the latest version should be v0.32.0). It uses iOverlay v4.0.6. Then add the following main.rs file:

use std::f64::consts::PI;

use geo::{
    Buffer, Coord, LineString, Polygon,
    buffer::{BufferStyle, LineCap, LineJoin},
};

fn main() {
    let coords = vec![
        [2681.39599938213, 5892784.488998892],
        [5419.06964821636, 5891947.742386343],
        [5419.1446127397, 5891949.316633703],
        [5422.8669123155, 5892027.484991552],
        [5034.8682417375, 5892817.151239874],
        [4804.8188261491, 5892876.799252035],
        [4804.81882805645, 5892876.799253942],
        [4551.3436274034, 5892942.5211854],
        [2681.39599938213, 5892784.488998892],
    ];

    let coords = coords
        .into_iter()
        .map(|c| Coord::from((c[0], c[1])))
        .collect::<Vec<_>>();
    let ls = LineString::new(coords);
    let polygon = Polygon::new(ls, Vec::new());

    let angle = 10.0 / (PI / 2.0);
    let _buffer = polygon.buffer_with_style(
        BufferStyle::new(150.0)
            .line_cap(LineCap::Round(angle))
            .line_join(LineJoin::Round(angle)),
    );
}

Expected behavior

The program creates a buffer with a distance of 150m.

Actual behavior

The program ends up in an infinite loop and allocates gigabytes of memory until it crashes.

Environment

  • iOverlay version: v4.0.6
  • Rust version: 1.92.0
  • OS: macOS Tahoe

Additional context

Let me know if you need anything else or if I should try to create an even smaller reproducer without the geo dependency.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions