Unidata / netcdf-c

Official GitHub repository for netCDF-C libraries and utilities.
BSD 3-Clause "New" or "Revised" License
521 stars 262 forks source link

`nc_inq_dimlen` reports wrong dimension length on a 32-bit platform #1481

Open vassilyl opened 5 years ago

vassilyl commented 5 years ago

NetCDF 4.7.0 on Windows 10 using Microsoft (R) C/C++ Optimizing Compiler Version 19.22.27905.

It appears it is totally possible to create a NetCDF4 file with the length of dimension > 2**32. On systems with 32-bit size_t, e.q. 32-bit Windows, the NetCDF API reports wrong values. Does the API has functions capable of reporting 64-bit sizes on 32-bit platforms? I would, at least, expect that the limitation is clearly documented and the function to report an error.

Steps to reproduce:

Create a .nc file using this simple code:

#include "stdio.h"
#include "netcdf.h"

int main(int argc, char** argv)
{
    int ncid;
    int result = nc_create("a.nc", NC_NETCDF4, &ncid);
    printf("nc_create result=%d ncid=%d\n", result, ncid);
    int dimid[1];
    result = nc_def_dim(ncid, "a", NC_UNLIMITED, dimid);
    printf("nc_def_dim result=%d dimid=%d\n", result, dimid[0]);
    int varid;
    result = nc_def_var(ncid, "v", NC_INT, 1, dimid, &varid);
    printf("nc_def_var result=%d varid=%d\n", result, varid);
    size_t start[] = {4294967295};
    size_t count[] = {2};
    int data[] = {19, 22};
    result = nc_put_vara_int(ncid, varid, start, count, dimid);
    printf("nc_put_vars result=%d\n", result);
    result = nc_close(ncid);
    printf("nc_close result=%d\n", result);
}

... and then open the file with the following:

#include "stdio.h"
#include "netcdf.h"

int main()
{
    printf("size of size_t is %d\n", sizeof(size_t));
    int ncid;
    int result = nc_open("a.nc", NC_NOWRITE, &ncid);
    int ndims;
    int dimid[1];
    result = nc_inq_dimids(ncid, &ndims, dimid, 0);
    printf("nc_inq_dimids result=%d ndims=%d dimid=%d\n", result, ndims, dimid[0]);
    size_t dimlen;
    result = nc_inq_dimlen(ncid, dimid[0], &dimlen);
    long long longdimlen = dimlen;
    printf("nc_inq_dimlen result=%d dimlen=%lld\n", result, longdimlen);
    result = nc_close(ncid);
    printf("nc_close result=%d\n", result);
}

F

or a 64-bit program the output is

size of size_t is 8
nc_inq_dimids result=0 ndims=1 dimid=0
nc_inq_dimlen result=0 dimlen=4294967297
nc_close result=0

while for a 32-bit code it is

size of size_t is 4
nc_inq_dimids result=0 ndims=1 dimid=0
nc_inq_dimlen result=0 dimlen=1
nc_close result=0

The .nc file: a.zip

edhartnett commented 5 years ago

Well certainly this can be better documented.

Can this be detected? That is, is there some code that runs on the 32-bit machine that will identify when this condition has occurred?

barracuda156 commented 8 months ago

@edhartnett I guess this was never fixed ever since? I just got an apparently related error in an R package which relies on NetCDF: https://github.com/pvanlaake/CFtime/issues/5

Maybe it can be addressed?

barracuda156 commented 2 months ago

Any update on this one?

edwardhartnett commented 2 months ago

I don't know what should be done.

We do not want to limit the dimension size. So what should we do here?

barracuda156 commented 2 months ago

I don't know what should be done.

We do not want to limit the dimension size. So what should we do here?

There must be a way to have it working on 32-bit? Any needed changes can be done conditionally, so nothing is adversely affected on 64-bit platforms.

edwardhartnett commented 2 months ago

Well what should it do if there is a dimension that is too big for a 32-bit int? Error out?

Does windows really not have a 64-bit int? That sounds wrong...

barracuda156 commented 2 months ago

Well what should it do if there is a dimension that is too big for a 32-bit int? Error out?

Does windows really not have a 64-bit int? That sounds wrong...

I have no idea about Windows, but normally on a 32-bit platform int is, of course, 32-bit, so long long should be used.