Fixed bug "adding a bad _FillValue" bug (NCF-190). Fixed minor bugs

reported by static analysis, including memory leak in ncdump, missing
size_t cast for chunk cache.  Fixed various doc problems, including
byte vs. char issues, missing NC_UBYTE in type list, needed link to
"Building with Windows" page.
This commit is contained in:
Russ Rew 2012-08-16 18:31:48 +00:00
parent 9e8146f873
commit 8d53da4826
12 changed files with 68 additions and 17 deletions

View File

@ -10,6 +10,11 @@ VERSION COMMENTS
Replaced the oc library with oc2.0
Prevented adding an invalid _FillValue attribute to a
variable (with nonmatching type or multiple values),
to avoid later error when any record variable is
extended.
[NCF-190]
4.2.1 Released 2012-07-18

View File

@ -43,7 +43,7 @@ extern "C" {
/* The following are use internally in support of user-defines
* types. They are also the class returned by nc_inq_user_type. */
#define NC_VLEN 13 /**< vlen types */
#define NC_VLEN 13 /**< vlen (variable-length) types */
#define NC_OPAQUE 14 /**< opaque types */
#define NC_ENUM 15 /**< enum types */
#define NC_COMPOUND 16 /**< compound types */

View File

@ -37,7 +37,7 @@ apply.
\param value Pointer to one or more values.
\returns ::NC_NOERR No error.
\returns ::NC_EINVAL Trying to set global _FillValue.
\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue.
\returns ::NC_ENOTVAR Couldn't find varid.
\returns ::NC_EBADTYPE Fill value and var must be same type.
\returns ::NC_ENOMEM Out of memory
@ -85,7 +85,7 @@ apply.
\param value Pointer to one or more values.
\returns ::NC_NOERR No error.
\returns ::NC_EINVAL Trying to set global _FillValue.
\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue.
\returns ::NC_ENOTVAR Couldn't find varid.
\returns ::NC_EBADTYPE Fill value and var must be same type.
\returns ::NC_ENOMEM Out of memory
@ -153,8 +153,11 @@ or if the space required to store the attribute is greater than
before, the netCDF dataset must be in define mode.
With netCDF-4 files, nc_put_att will notice if you are writing a
_Fill_Value_ attribute, and will tell the HDF5 layer to use the
specified fill value for that variable.
_FillValue attribute, and will tell the HDF5 layer to use the
specified fill value for that variable. With either classic or
netCDF-4 files, a _FillValue attribute will be checked for validity,
to make sure it has only one value and that its type matches the type
of the associated variable.
Although it's possible to create attributes of all types, text and
double attributes are adequate for most purposes.
@ -176,7 +179,7 @@ apply.
\param value Pointer to one or more values.
\returns ::NC_NOERR No error.
\returns ::NC_EINVAL Trying to set global _FillValue.
\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue.
\returns ::NC_ENOTVAR Couldn't find varid.
\returns ::NC_EBADTYPE Fill value and var must be same type.
\returns ::NC_ENOMEM Out of memory

View File

@ -322,8 +322,10 @@ nc4_put_att(int ncid, NC_FILE_INFO_T *nc, int varid, const char *name,
NC_TYPE_INFO_T *type_info;
int size;
/* Fill value must be same type. */
/* Fill value must be same type and have exactly one value */
if (att->xtype != var->xtype)
return NC_EBADTYPE;
if (att->len != 1)
return NC_EINVAL;
/* If we already wrote to the dataset, then return an error. */

View File

@ -129,7 +129,7 @@ nc_set_var_chunk_cache_ints(int ncid, int varid, int size, int nelems,
float real_preemption = H5D_CHUNK_CACHE_W0_DEFAULT;
if (size >= 0)
real_size = size * MEGABYTE;
real_size = ((size_t) size) * MEGABYTE;
if (nelems >= 0)
real_nelems = nelems;

View File

@ -2932,8 +2932,8 @@ The length of an attribute is the number of data values assigned to
it. Multiple values are assigned to non-character attributes by
separating the values with commas (','). All values assigned to an
attribute must be of the same type. In the classic data model,
character arrays are used for textual information, so the length of a
character attribute is the number of character values, and an array of
character arrays are used for textual information. The length of a
character attribute is the number of bytes, and an array of
character values can be represented in string notation. In the
enhanced data model of netCDF-4, variable-length strings are available
as a primitive type, and the length of a string attribute is the

View File

@ -2,7 +2,7 @@
Documentation for getting and building netCDF
This document is for getting and building the netCDF C library and
utilities, version 4.2.1. Other libraries that depend on the netCDF C
utilities, version 4.2.1.1. Other libraries that depend on the netCDF C
library, such as the Fortran and C++ libraries, are available as
separate distributions that can be built and installed after the C
library is successfully installed. The netCDF-Java library is also a
@ -47,6 +47,7 @@ full functionality. (See \ref architecture).
- \ref build_classic
- \ref build_hdf4
- \ref build_parallel
- \ref build_windows
- \ref configure_options
\page build_default Building with NetCDF-4 and the Remote Data Client
@ -238,6 +239,12 @@ netCDF-4 libraries:
cc -o myapp myapp.c `nc-config --cflags --libs`
\endverbatim
\page build_windows Building with Windows
See the <a href="http://www.unidata.ucar.edu/netcdf/windows_netcdf/"
>NetCDF for Windows </a> page for Current information about building
netCDF on Windows or downloading prebuilt Windows binaries.
\page configure_options ./configure options
Note: --disable prefix indicates that the option is normally enabled.

View File

@ -1703,7 +1703,7 @@ The atomic external types supported by the netCDF interface are:
@end multitable
* These types are available only for netCDF-4 format files. All the
unsigned ints (except NC_CHAR), the 64-bit ints, and string
unsigned ints, the 64-bit ints, and string
type are for netCDF-4 files only.
These types were chosen to provide a reasonably wide range of

View File

@ -10,7 +10,8 @@ a user-defined data type (see \ref user_defined_types).
The atomic external types supported by the netCDF interface are:
- ::NC_BYTE 8-bit signed integer
- ::NC_CHAR 8-bit unsigned integer
- ::NC_UBYTE 8-bit unsigned integer
- ::NC_CHAR 8-bit character byte
- ::NC_SHORT 16-bit signed integer
- ::NC_USHORT 16-bit unsigned integer *
- ::NC_INT (or ::NC_LONG) 32-bit signed integer
@ -285,4 +286,4 @@ precision value you can write to a double variable is the largest
double-precision number representable on your system that is less than
2 to the 1024th power.
*/
*/

View File

@ -2370,6 +2370,23 @@ main(int argc, char **argv)
if (nc_inq_varnatts(ncid, 0, &natts)) ERR;
if (natts != 2) ERR;
if (nc_copy_att(ncid, NC_GLOBAL, A1_NAME, ncid, 0)) ERR;
/* Also test for fix of another bug, allowing invalid _FillValue
* attribute (not of same type as variable or with 0 values or more
* than 1 value) to be created. */
{
static const int var_FillValue_atts[] = {42, -99} ;
float var_FillValue_att = -99 ;
/* This should return error, because attribute has too many values */
if (nc_put_att_int(ncid, varid, "_FillValue", NC_INT, 2, var_FillValue_atts)
!= NC_EINVAL) ERR;
/* This also should return error, because types don't match */
if (nc_put_att_float(ncid, varid, "_FillValue", NC_FLOAT, 1, &var_FillValue_att)
!= NC_EBADTYPE) ERR;
/* This should succeed, _FillValue is valid */
if (nc_put_att_int(ncid, varid, "_FillValue", NC_INT, 1, var_FillValue_atts)) ERR;
}
if (nc_close(ncid)) ERR;
/* Reopen the file and check it. */

View File

@ -53,7 +53,21 @@ main()
if (nc_inq_var(ncid, 1, NULL, NULL, &ndims, dimids_in, NULL)) ERR;
if (ndims != 3 || dimids_in[0] != 0 || dimids_in[1] != 2 || dimids_in[2] != 1) ERR;
/* Read the record of non-existant data. */
/* Also test for fix of another bug, allowing invalid _FillValue
* attribute (not of same type as variable or with 0 values or more
* than 1 value) to be created. */
{
static const float p_FillValue_atts[] = {NC_FILL_FLOAT, -99} ;
int p_FillValue_att = -99 ;
/* This should returns error, too many attribute vals */
if (nc_put_att_float(ncid, p_id, "_FillValue", NC_FLOAT, 2, p_FillValue_atts) != NC_EINVAL) ERR;
/* This also should return error, wrong type */
if (nc_put_att_int(ncid, p_id, "_FillValue", NC_INT, 1, &p_FillValue_att) != NC_EBADTYPE) ERR;
/* This should succeed, _FillValue is valid */
if (nc_put_att_float(ncid, p_id, "_FillValue", NC_FLOAT, 1, p_FillValue_atts)) ERR;
}
/* Read the record of non-existent data. */
if (nc_get_vara(ncid, 1, cor, edg, P_data)) ERR;
for (i = 0; i < LEN; i++)
if (P_data[i] != NC_FILL_FLOAT) ERR;

View File

@ -1147,6 +1147,7 @@ chars_tostring(
*cp++ = '"';
*cp++ = '\0';
sbuf_cpy(sbuf, sout);
free(sout);
return sbuf_len(sbuf);
}
@ -1885,7 +1886,7 @@ get_type_name(int ncid, nc_type type, char *name)
{
#ifdef USE_NETCDF4
if (is_user_defined_type(type)) {
nc_inq_user_type(ncid, type, name, NULL, NULL, NULL, NULL);
NC_CHECK(nc_inq_user_type(ncid, type, name, NULL, NULL, NULL, NULL));
} else {
strncpy(name, prim_type_name(type), NC_MAX_NAME + 1);
}
@ -1907,7 +1908,7 @@ void
print_type_name(int locid, int typeid) {
char *ename;
#ifdef USE_NETCDF4
char name[NC_MAX_NAME];
char name[NC_MAX_NAME+1];
int type_inherited = 0;
int curlocid; /* group we are searching in */
int parent_groupid = locid;
@ -1921,6 +1922,7 @@ print_type_name(int locid, int typeid) {
if(is_user_defined_type(typeid)) {
/* determine if type is inherited, that is if defined in this
* group or any ancestor group */
name[NC_MAX_NAME] = '\0';
strncpy(name,nctypes[typeid]->name,NC_MAX_NAME);
do {
curlocid = parent_groupid;