[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