geos icon indicating copy to clipboard operation
geos copied to clipboard

CoordinateSequence::getAt relies on undefined behavior

Open ergpudb opened this issue 2 years ago • 4 comments

The line:

const T* orig = reinterpret_cast<const T*>(&m_vect[i*stride()]);

violates the strict aliasing rule (it's using reinterpret_cast to create a coordinate object on top of memory that isn't) and has undefined behavior.

Of course there's a good chance it will work the vast majority (if not all) of the time, but compilers are free to do things that would make it not work since it isn't following the rule.

ergpudb avatar Oct 18 '23 13:10 ergpudb

Seems hard to fix... https://en.cppreference.com/w/cpp/utility/launder ?

pramsey avatar Feb 12 '24 20:02 pramsey

It isn't possible (within the bounds of defined behavior) to use a std::vector<double> as storage for this purpose. It would be possible to allocate a memory buffer of the correct size and alignment and then use placement new to construct an array of the correct coordinate type into it (you'd have to know the type at the point you did this and use the correct form of new... and of course manually implement all of the vector-type operations like reserve, resize, etc.)

You would probably need std::launder to access the coordinates in the buffer (since presumably you wouldn't have saved the result of placement new, since each coordinate type would use a different form of new), and it would still be undefined behavior to access the contents of the buffer using a different coordinate type than the one it was initialized with (but presumably the creator of the sequence would know what type they wanted and be consistent about it).

ergpudb avatar Feb 13 '24 00:02 ergpudb

@pramsey The PostGIS POINTARRAY has been doing this for roughly a decade...any issues there?

https://github.com/postgis/postgis/blob/master/liblwgeom/lwinline.h#L90-L100

dbaston avatar Feb 13 '24 02:02 dbaston

De nada.

pramsey avatar Feb 13 '24 16:02 pramsey