[GRASS-dev] d.legend uses a static buffer for `map='
Ivan Shmakov
ivan at theory.asu.ru
Tue Jan 8 01:20:28 EST 2008
>>>>> Glynn Clements <glynn at gclements.plus.com> writes:
[...]
>>>> PS. I've seen a number of other uses of static buffers scattered
>>>> across the code, leading to both potential limits and crashes,
>>>> which I'm on the way to investigate.
>>> There isn't necessarily a problem with using fixed-size buffers for
>>> map names, but the size should be GNAME_MAX.
>> Well, yes. It's actually strcpy () use which bothers me the most,
>> and not the static buffer per se. Obviously, `d.legend' may
>> accidentally get called with a `map' value larger than any
>> predefined static buffer size, leading to hardly predicable
>> behaviour.
> If you're worried about buffer overflows, there are probably
> somewhere between a few hundred and a few thousand others to worry
> about.
Perhaps.
> To date, the general policy has been to use buffers which are
> sufficently large for "normal" use and rely upon the user not doing
> anything abnormal (like using 1000-character map names).
> If you're writing a "web application" (CGI script) on top of GRASS,
> validating any user-supplied data is essential.
I'm not considering web applications as yet. Besides, there may
be other sources of ``potentially dangerous'' data.
My primary concern is that the software shouldn't surprise the
user by breaking gratuitously. In particular, I was quite
surprised when `d.legend' has failed for a particularly long
raster name. I had to make a copy for each of the rasters to
make it work, and it was a hassle.
>> In my opinion, strncpy () should generally be preferred over strcpy
>> ().
> Using strncpy() isn't much of an improvement, as the copy won't be
> NUL-terminated if it's truncated. And simplyy NUL-terminating the
> string risks reading/writing the wrong file. The only safe solutions
> are to either dynamically allocate all buffers, or signal a fatal
> error if the source is too long.
Or, if a library function is considered, it may return a kind of
error to the caller.
For example, I'd suggest changing D_get_cell_name () as follows:
diff --git a/lib/display/list.c b/lib/display/list.c
index 48180cf..2353092 100644
--- a/lib/display/list.c
+++ b/lib/display/list.c
@@ -99,6 +99,9 @@ int D_get_cell_name(char *name )
if ((stat = R_pad_get_item ("cell", &list, &count)))
return(-1) ;
+ if (strlen (list[0]) >= GNAME_MAX)
+ return -1;
+
strcpy(name, list[0]) ;
R_pad_freelist (list,count) ;
(Add a warning to your taste.)
Along with changing all its users to use static buffers of size
GNAME_MAX. (I'd try to find them all and propose a patch soon.)
[...]
>> $ nl -ba display/d.colors/main.c
>> ...
>> 25 int
>> 26 main (int argc, char **argv)
>> 27 {
>> 28 char name[128] = "";
> Right. We encourage developers to replace these with the defined
> constants as they encounter them.
ACK.
[...]
>>> As this never enlarges the string, it's okay to re-use the original
>>> buffer.
>> I see, Martin has turned G_find_cell () into G_find_cell2 ()
>> instead.
... Though `const' was stripped off the `map_name' declaration
as well?
> G_find_cell2() is preferable, but you need to ensure that there isn't
> any code which relies upon the @mapset having been stripped off (e.g.
> code which generates additional map names by appending a suffix).
ACK.
> A while back, I changed all of the libgis functions which I could
> find to accept qualified, so leaving the name qualified shouldn't be
> a problem so far as libgis is concerned, but there may still be
> problems with other libraries and with the module itself.
The only uses of `map_name' in d.legend are:
G_read_colors (map_name, mapset, ...)
G_raster_map_is_fp (map_name, mapset)
G_read_cats (map_name, mapset, ...)
G_read_range (map_name, mapset, ...)
G_read_fp_range (map_name, mapset, ...)
I guess, they're safe?
PS. Shouldn't G__open () use GPATH_MAX as well?
More information about the grass-dev
mailing list