Opened 11 years ago
Closed 11 years ago
#5230 closed defect (fixed)
[PATCH] GML TopoSurface concatenation results in invalid geometries due to point duplication
Reported by: | esseffe | Owned by: | warmerdam |
---|---|---|---|
Priority: | normal | Milestone: | 1.10.2 |
Component: | OGR_SF | Version: | unspecified |
Severity: | normal | Keywords: | GML Topology |
Cc: |
Description
looks very similar to ticket #4451.
while parsing GML-Topology many TopoSurfaces re-aggregated from their corresponding Edges will be invalid due to point duplication.
this bug only occurs when specifying GML_FACE_HOLE_NEGATIVE YES and affects both modes GML_SKIP_RESOLVE_ELEMS NONE|HUGE indifferently.
you could eventually replicate this issue by processing the attached GML-Topo sample (you'll find duplicated points into the "suolo" table):
ogr2ogr -f "SQLite" dupli.sqlite topogml_sample.xml -dsco SPATIALITE=yes --config GML_SKIP_RESOLVE_ELEMS HUGE --config GML_FACE_HOLE_NEGATIVE YES the attached patch (closely derived from the one already adopted for ticket #4451) seems to effectively resolve this issue.
bye Sandro
Attachments (3)
Change History (8)
by , 11 years ago
Attachment: | topogml_sample.xml.gz added |
---|
by , 11 years ago
Attachment: | patch_topo_surface.gz added |
---|
comment:1 by , 11 years ago
Summary: | GML TopoSurface concatenation results in invalid geometries due to point duplication → [PATCH] GML TopoSurface concatenation results in invalid geometries due to point duplication |
---|
comment:2 by , 11 years ago
Feedback from Sandro:
I've cloned yet again the current GDAL sources from the SVN, then I've downloaded my own patch an testcase from Trac, so to be absolutely sure to replicate your local configuration as close as possible. First surprise: on my Debian Wheezy anything works in the cleanest way; I'm completely unable to see any error or warning, and for sure I get no crash at all. This seems to be fully consistent with my previous test performed immediately before committing my patch. Anyway it strongly contrasts with your own findings. So I've patiently set up a full Valgrind session, in order to identify any possible memory corruption. And here comes the second surprise: ==24147== Invalid read of size 4 ==24147== at 0x4EFA318: ??? (in /usr/local/lib/libspatialite.so.5.1.0) ==24147== by 0x5CE47C0: ??? (in /usr/lib/i386-linux-gnu/libsqlite3.so.0.8.6) ==24147== by 0x5CC837D: sqlite3_step (in /usr/lib/i386-linux-gnu/libsqlite3.so.0.8.6) ==24147== by 0x5CCE7DE: sqlite3_exec (in /usr/lib/i386-linux-gnu/libsqlite3.so.0.8.6) ==24147== by 0x8057CA8: SetupTargetLayer(OGRDataSource*, OGRLayer*, OGRDataSource*, char**, char const*, OGRSpatialReference*, int, char**, int, int, int, int, int, int, char**, int, int, char const*, char**, char const*) (ogr2ogr.cpp:2681) ==24147== by 0x8056E26: main (ogr2ogr.cpp:2202) ==24147== Address 0x740b5bc is 4 bytes inside a block of size 6 alloc'd ==24147== at 0x4028308: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==24147== by 0x4EFA09C: ??? (in /usr/local/lib/libspatialite.so.5.1.0) ==24147== by 0x5CE47C0: ??? (in /usr/lib/i386-linux-gnu/libsqlite3.so.0.8.6) ==24147== by 0x5CC837D: sqlite3_step (in /usr/lib/i386-linux-gnu/libsqlite3.so.0.8.6) ==24147== by 0x5CCE7DE: sqlite3_exec (in /usr/lib/i386-linux-gnu/libsqlite3.so.0.8.6) ==24147== by 0x8057CA8: SetupTargetLayer(OGRDataSource*, OGRLayer*, OGRDataSource*, char**, char const*, OGRSpatialReference*, int, char**, int, int, int, int, int, int, char**, int, int, char const*, char**, char const*) (ogr2ogr.cpp:2681) ==24147== by 0x8056E26: main (ogr2ogr.cpp:2202) ==24147== after all there is some memory corruption, and this could easily explain all errors and the final crash you detected; and anything points my suspects into the direction of some nasty mismatch affecting sqlite/spatialite (sqlite3_exec). after further debugging I was finally able to identify the exact point where this "invalid read" happens: ogrsqlitedatasource.cpp (near line 2036) rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg ); if( rc != SQLITE_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to add %s table to geometry_columns:\n%s", pszLayerName, pszErrMsg ); sqlite3_free( pszErrMsg ); return FALSE; } the memory issue materializes while executing these SQL statements: SELECT AddGeometryColumn('lineeelementari', 'GEOMETRY', 0, 'MULTILINESTRING', 2) SELECT AddGeometryColumn('suolo', 'GEOMETRY', 0, 'POLYGON', 2) the first invocation passes absolutely clean; but the second one certainly encounters some heavily corrupted memory block, as clearly reported by Valgrind. the specific component causing this memory corruption seems to be exactly libspatialite itself. GDAL seems to be absolutely extraneous to all this, and the same is for my proposed patch affecting GML Topo Surface. once I've reached this first preliminary conclusion then I've soon updated yet again libspatialite by cloning the most recent shapshot available from the Fossil repo (I use a different Fedora platform for any SpatiaLite development, so the Debian Wheezy I was using to test GDAL was a little bit out of sync) and here comes the third surprise: ANYTHING WORKS NICELY Valgrind doesn't raises any longer any complaint, ever the slightest one. MY FINAL CONCLUSIONS: --------------------- 1) the proposed patch is crystal clear 2) as is the attached testcase 3) the specific version of libspatialite 4.1.2-devel available few weeks ago contained some undetected internal memory issue (*); I'm pretty sure about this, because I've corrected and fixed a couple of related issues affecting the internal connection cache in the afterwhile. 4) such memory issues caused memory corruption in critical areas accessed by sqlite/spatialite (sqlite3_exec). for some odd reason this passed practically unnoticed on my Debian/Fedora, but caused many troubles and a final crash on your system (I suppose we are using different versions of libsqlite3 and may be of the C runtime, and this could probably be the real cause explaining any observed difference; dirty memory blocks are rather extravagant in their practical consequences) 5) the current snapshot of libspatialite 4.1.2-devel seems to be finally immune from any memory related issue; and under these conditions both the proposed patch and testcase work exactly as expected.
(*) just a short technical note now the more recent spatialite's versions support two different initializing APIs: - void spatialite_init ( int verbose ); - void spatialite_init_ex ( sqlite3 *db_handle, void *p_cache, int verbose ); the first form is now obsolete and just preserved for long term back compatibility. the second form was introduced so to allow a more specific handling of each single connection (much better suited for effective multi-threading, because each connection now have its own externally allocated cache) both spatialite CLI and GUI now uniquely use the second form; unhappily GDAL/OGR still continued to use the legacy form, who was actually plagued by several memory issues fixed only last week (badly allocated default connection cache). and this really is the end of this long and cumbersome story :-D
comment:3 by , 11 years ago
Sandro,
your above problems are related to spatialite, but my test does not involve spatialite at all. It is just ogrinfo on the GML file, so it just requires sqlite3 support.
Did you really test with the sample file attached to the ticket ? By replacing sqlite3_prepare by sqlite3_prepare_v2, I got a more precise error message and when looking at the file, I can indeed see that "Edge_32_34096" is defined twice in the file (line 197 and 224), which causes a duplicated primary key issue. And there are other problems too with edges Edge_32_34129, Edge_32_34096 and Edge_32_34203.
by , 11 years ago
Attachment: | topogml_sample_ok.xml.gz added |
---|
comment:4 by , 11 years ago
Hi Even,
you are absolutely right; I had two different versions of the GML testcase on two different directories, and I stupidly attached the first preliminary version instead of the final right one. Few days ago I was pretty sure to had used for my latest tests exactly the sample downloaded from GDAL Trac, but it's now rather obviously that I finished yet again by testing my local copy.
please see the attached "good" testcase
sorry for any inconvenience, Sandro
comment:5 by , 11 years ago
Component: | default → OGR_SF |
---|---|
Milestone: | → 1.10.2 |
Resolution: | → fixed |
Status: | new → closed |
trunk r26559 and branches/1.10 r26560 "GML TopoSurface: fix duplicated points in GML_FACE_HOLE_NEGATIVE=YES mode (patch by Sandro Furieri, #5230)"
trunk r26557 "GML huge file resolver: initialize members of huge_tag structure, use sqlite3_prepare_v2 instead of sqlite3_prepare, and add more precise error message in gmlHugeFileSQLiteInsert()"
trunk r26558 "GML huge file resolver: fix crash and mem leak"
Hum, before applying the patch for the issue you're trying to fix, I encounter quite a few preliminary issues :
I've tried the following patch :
which fixes the segfault, but there's still the sqlite3_step() failure that occurs at line 853 of hugefileresolver.cpp, due to a constraint violation (probably a duplicated primary key)