[GRASS-dev] Re: [GRASS GIS] #50: g.copy segfaults (debian.gfoss.it
package) [and latest SVN]
GRASS GIS
trac at osgeo.org
Sat Apr 12 21:10:19 EDT 2008
#50: g.copy segfaults (debian.gfoss.it package) [and latest SVN]
----------------------+-----------------------------------------------------
Reporter: steko | Owner: grass-dev at lists.osgeo.org
Type: defect | Status: new
Priority: major | Milestone: 6.4.0
Component: default | Version: 6.3.0 RCs
Resolution: | Keywords: g.copy
----------------------+-----------------------------------------------------
Comment (by glynn):
Replying to [comment:8 marisn]:
> Changing G_lstat() with lstat() in general/manage/lib/do_copy.c fixes
problem;(1)[[BR]]
Okay, I've installed gcc 4.1.2, can reproduce the segfault, and have
identified the problem: LFS.
When --enable-largefile is used, libgis is built with
-D_FILE_OFFSET_BITS=64. This causes the "struct stat" used by e.g.
G_lstat() in lib/gis/paths.c to be the 64-bit version (which is 96 bytes),
and lstat() to be an alias for lstat64(). But general/manage (and, in
fact, most of GRASS) is built without that flag, so "struct stat" is the
32-bit version (which is only 88 bytes).
The end result is that "sb" in recursive_copy is only 88 bytes, but
G_lstat() writes 96 bytes, overflowing the buffer by 8 bytes. This trashes
the saved copy of the %esi register, which holds the "dirp" variable. When
recursive_copy() returns, the trashed value is restored to %esi, meaning
that "dirp" has been trashed, resulting in the segfault.
In practice, exactly what gets trashed depends upon what is above "sb" on
the stack, which depends upon the compiler version and compilation
switches. Right now, the only files which use G_stat() or G_lstat() are:
{{{
grass=> select * from obj_imp where symbol in ('G_stat', 'G_lstat') ;
object | symbol
----------------------------------------------------+---------
general/manage/lib/OBJ.i686-pc-linux-gnu/do_copy.o | G_lstat
lib/gis/OBJ.i686-pc-linux-gnu/mapset_msc.o | G_stat
lib/gis/OBJ.i686-pc-linux-gnu/remove.o | G_lstat
lib/gis/OBJ.i686-pc-linux-gnu/unix_socks.o | G_lstat
lib/gis/OBJ.i686-pc-linux-gnu/user_config.o | G_lstat
}}}
Four of them are part of libgis, so they will use the correct "struct
stat" size. The other is do_copy.c, which loses.
As for possible solutions: one option is to change G_[l]stat() to allocate
the "struct stat" with e.g. G_malloc(). Another is to move
recursive_copy() into libgis.
The problem with the latter option is that, so long as G_[l]stat() exist
in their current form, any code which uses them but which has a different
off_t size to libgis will likely get bitten by the same issue (and by the
time that it actually gets discovered, we will probably have forgotten
about all of this).
--
Ticket URL: <http://trac.osgeo.org/grass/ticket/50#comment:11>
GRASS GIS <http://grass.osgeo.org>
GRASS Geographic Information System (GRASS GIS) - http://grass.osgeo.org/
More information about the grass-dev
mailing list