/* * Given a valid ncp, return NC_EVARSIZE if any variable has a bad len * (product of non-rec dim sizes too large), else return NC_NOERR. */ static int NC_check_vlens(NC *ncp) { NC_var **vpp; /* maximum permitted variable size (or size of one record's worth of a record variable) in bytes. This is different for format 1 and format 2. */ size_t vlen_max; size_t ii; size_t large_vars_count; size_t rec_vars_count; int last = 0; if(ncp->vars.nelems == 0) return NC_NOERR; if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) { /* CDF2 format and LFS */ vlen_max = X_UINT_MAX - 3; /* "- 3" handles rounded-up size */ } else { /* CDF1 format */ vlen_max = X_INT_MAX - 3; } /* Loop through vars, first pass is for non-record variables. */ large_vars_count = 0; rec_vars_count = 0; vpp = ncp->vars.value; for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) { if( !IS_RECVAR(*vpp) ) { last = 0; if( NC_check_vlen(*vpp, vlen_max) == 0 ) { large_vars_count++; last = 1; } } else { rec_vars_count++; } } /* OK if last non-record variable size too large, since not used to compute an offset */ if( large_vars_count > 1) { /* only one "too-large" variable allowed */ return NC_EVARSIZE; } /* and it has to be the last one */ if( large_vars_count == 1 && last == 0) { return NC_EVARSIZE; } if( rec_vars_count > 0 ) { /* and if it's the last one, there can't be any record variables */ if( large_vars_count == 1 && last == 1) { return NC_EVARSIZE; } /* Loop through vars, second pass is for record variables. */ large_vars_count = 0; vpp = ncp->vars.value; for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) { if( IS_RECVAR(*vpp) ) { last = 0; if( NC_check_vlen(*vpp, vlen_max) == 0 ) { large_vars_count++; last = 1; } } } /* OK if last record variable size too large, since not used to compute an offset */ if( large_vars_count > 1) { /* only one "too-large" variable allowed */ return NC_EVARSIZE; } /* and it has to be the last one */ if( large_vars_count == 1 && last == 0) { return NC_EVARSIZE; } } return NC_NOERR; }
/* * 'compile' the shape and len of a variable * Formerly NC_var_shape(var, dims) */ int NC_var_shape(NC_var *varp, const NC_dimarray *dims) { size_t *shp, *op; off_t *dsp; int *ip = NULL; const NC_dim *dimp; off_t product = 1; varp->xsz = ncx_szof(varp->type); if(varp->ndims == 0 || varp->dimids == NULL) { goto out; } /* * use the user supplied dimension indices * to determine the shape */ for(ip = varp->dimids, op = varp->shape ; ip < &varp->dimids[varp->ndims]; ip++, op++) { if(*ip < 0 || (size_t) (*ip) >= ((dims != NULL) ? dims->nelems : 1) ) return NC_EBADDIM; dimp = elem_NC_dimarray(dims, (size_t)*ip); *op = dimp->size; if(*op == NC_UNLIMITED && ip != varp->dimids) return NC_EUNLIMPOS; } /* * Compute the dsizes */ /* ndims is > 0 here */ for(shp = varp->shape + varp->ndims -1, dsp = varp->dsizes + varp->ndims -1; shp >= varp->shape; shp--, dsp--) { /*if(!(shp == varp->shape && IS_RECVAR(varp)))*/ if( shp != NULL && (shp != varp->shape || !IS_RECVAR(varp))) { if( ((off_t)(*shp)) <= OFF_T_MAX / product ) { product *= (*shp > 0 ? *shp : 1); } else { product = OFF_T_MAX ; } } *dsp = product; } out : /* No variable size can be > X_INT64_MAX - 3 */ if (0 == NC_check_vlen(varp, X_INT64_MAX-3)) return NC_EVARSIZE; /* * For CDF-1 and CDF-2 formats, the total number of array elements * cannot exceed 2^32, unless this variable is the last fixed-size * variable, there is no record variable, and the file starting * offset of this variable is less than 2GiB. * This will be checked in NC_check_vlens() during NC_endef() */ varp->len = product * varp->xsz; if (varp->len % 4 > 0) varp->len += 4 - varp->len % 4; /* round up */ #if 0 arrayp("\tshape", varp->ndims, varp->shape); arrayp("\tdsizes", varp->ndims, varp->dsizes); #endif return NC_NOERR; }