[GRASSLIST:8036] Re: error reading large rasters in 5.4/6.0
Glynn Clements
glynn at gclements.plus.com
Tue Aug 23 17:25:05 EDT 2005
Andrew Danner wrote:
> After looking into the problem of reading very large rasters, I believe
> I have isolated the bug. The problem only happens when reading row 0 and
> triggers the following block in flate.c:186
>
> else if (b[0] != G_ZLIB_COMPRESSED_YES)
> {
> /* We're not at the start of a row */
> G_free (b);
> return -1;
> }
>
> I think the problem is a bug in writing rasters, not reading them. When
> creating a new raster, it writes a vector of row offsets to the fcell
> file in the function G__write_row_ptrs. It attempts to guess the size of
> the file offsets.
>
> int nbytes = sizeof(off_t);
> ...
> if (nbytes > 4 && fcb->row_ptr[nrows] <= 0xffffffff)
> nbytes = 4;
> ...
> len = (nrows + 1) * nbytes + 1;
> b = buf = G_malloc(len);
>
> The problem is that when a new raster is created fcb->row_ptr[nrows]=0,
> so nbytes is always 4. Later when writing the rows and actually
> computing the offsets, if fcb->row_ptr[nrows] > 0xffffffff, it bumps
> nbytes upto 8, but row 0 was written to the file assuming an offset of 4
> and row 0 becomes corrupted if the raster is larger than 4GB.
Right. I'd overlooked the fact that G_write_row_ptrs() gets called
twice.
> Commenting out the "if" block seems to fix the problem.
The reader will handle 8-byte offsets even if off_t is only 4 bytes so
long as the offsets themselves don't exceed the 32-bit range.
There isn't any practical way to determine in advance whether the
offsets will fit into 4 bytes, so removing the "if" block is the right
fix.
> Should I submit a bug report?
No need; I've comitted the fix to CVS.
One other bug which I've just noticed: the reader checks whether an
offset exceeds the range of an off_t, but only in the sense that it
checks whether it occupies too many bytes.
This check is wrong for files between 2GiB and 4GiB, where the offset
fits into 4 bytes, but exceeds the 31-bit (signed) range of an off_t.
There needs to be an "if (offset < 0)" check in there somewhere.
--
Glynn Clements <glynn at gclements.plus.com>
More information about the grass-user
mailing list