netcdf4-python
netcdf4-python copied to clipboard
Segmentation fault while reading a string array from non-netcdf4 hdf5
This behavior only happens with netCDF4-1.6.0 installed via pip. I cannot reproduce it with git install from v1.6.0rel. The following code:
from netCDF4 import Dataset
import h5py
import numpy as np
import operator
filename = "foobar.h5"
with h5py.File(filename, "w") as fp:
fp["test"] = np.array(["foo", "bar", "baz"], dtype="|S3")
rootgrp = Dataset("foobar.h5", "r", format="NETCDF4")
# This works, but note that result is wrong 'foobarbaz', '', ''
print(rootgrp["/test"][slice(None)])
# 2nd call will cause segfault
print(rootgrp["/test"][slice(None)])
yields:
$ python3 -Wd -X faulthandler bug2.py
['foobarbaz' '' '']
Fatal Python error: Segmentation fault
Current thread 0x00007f49f8c59740 (most recent call first):
File "/home/xarth/codes/xarthisius/yt/bug2.py", line 14 in <module>
Segmentation fault (core dumped)
Environment:
commit: None
python: 3.9.5 (default, Nov 23 2021, 15:27:38)
[GCC 9.3.0]
python-bits: 64
OS: Linux (Ubuntu 20.04.4 LTS)
OS-release: 5.4.0-121-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: en_US.utf8
LANG: en_US.utf8
LOCALE: ('en_US', 'UTF-8')
libhdf5: 1.12.2
libnetcdf: 4.9.0
xarray: 2022.3.1.dev60+g5f01c115
pandas: 1.4.3
numpy: 1.23.0
scipy: 1.9.0rc1
netCDF4: 1.6.0
pydap: None
h5netcdf: None
h5py: 3.7.0
Initially reported to xarray as https://github.com/pydata/xarray/issues/6728
Can the test h5 file be gzipped and attached to this issue? When you pip install netcdf4-python v1.6.0 you are getting 4.9.0 of the netcdf-c library. It's not totally clear from the above whether the situation where it works with an install from git is also using netcdf-c 4.9.0. Can you confirm that it is?
Test hdf5 : foobar.h5.gz
I totally missed the fact that pip package is linked to a different version of netcdf. The one I have (and the one that's being picked up during local pip install -e) is:
# apt list libnetcdf-dev
Listing... Done
libnetcdf-dev/focal,now 1:4.7.3-1 amd64 [installed]
so that means the segfault occurs with 4.9.0, but not with 4.7.3?
Yes, I just checked by installing netcdf-4.9.0 locally. Both v1.5.8rel and v1.6.0rel can trigger segfault now on my machine. It doesn't happen as reliably (i.e. not every time) but when I loop a slightly modified test case:
from netCDF4 import Dataset
import operator
rootgrp = Dataset("foobar.h5", "r", format="NETCDF4")
for i in range(10):
operator.getitem(rootgrp["/test"], slice(None, None, None))
it happens at least once:
$ for i in {1..10} ; do python3 -Wd -X faulthandler bug2.py ; done
Traceback (most recent call last):
File "/home/xarth/codes/xarthisius/yt/bug2.py", line 6, in <module>
operator.getitem(rootgrp["/test"], slice(None, None, None))
File "src/netCDF4/_netCDF4.pyx", line 4406, in netCDF4._netCDF4.Variable.__getitem__
File "src/netCDF4/_netCDF4.pyx", line 5382, in netCDF4._netCDF4.Variable._get
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 9: invalid continuation byte
Traceback (most recent call last):
File "/home/xarth/codes/xarthisius/yt/bug2.py", line 6, in <module>
operator.getitem(rootgrp["/test"], slice(None, None, None))
File "src/netCDF4/_netCDF4.pyx", line 4406, in netCDF4._netCDF4.Variable.__getitem__
File "src/netCDF4/_netCDF4.pyx", line 5382, in netCDF4._netCDF4.Variable._get
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe0 in position 9: invalid continuation byte
Traceback (most recent call last):
File "/home/xarth/codes/xarthisius/yt/bug2.py", line 6, in <module>
operator.getitem(rootgrp["/test"], slice(None, None, None))
File "src/netCDF4/_netCDF4.pyx", line 4406, in netCDF4._netCDF4.Variable.__getitem__
File "src/netCDF4/_netCDF4.pyx", line 5382, in netCDF4._netCDF4.Variable._get
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x90 in position 9: invalid start byte
Fatal Python error: Segmentation fault
Current thread 0x00007ff0c5617740 (most recent call first):
File "/home/xarth/codes/xarthisius/yt/bug2.py", line 6 in <module>
Segmentation fault (core dumped)
...
No, I was wrong. It can happen with 4.7.3 too. For some reason it's just more likely to happen with 4.9.0, but I can reproduce with earlier version too. It's just a matter of looping the example.
ncdump crashes on this file too - so it's definitely a C library issue. Care to open a netcdf-c issue?
ncdump crashes on this file too - so it's definitely a C library issue. Care to open a netcdf-c issue?
Looks like it might be https://github.com/Unidata/netcdf-c/issues/2159
Since netcdf cannot handle arrays of fixed length strings, I don't think you'll ever be able to read this file using xarray or netcdf4-python. It shouldn't crash the interpreter though.
Since netcdf cannot handle arrays of fixed length strings, I don't think you'll ever be able to read this file using xarray or netcdf4-python. It shouldn't crash the interpreter though.
That's all I'm really after: an error rather than a segmentation fault. We hit that in a code that tries to "detect" what kind of file format we're looking at.
@Xarthisius Is there any chance you might be able to attach a small foobar.nc file for me to test a fix against? Agreed that it should not crash at the underlying C library level if at all possible, although adding support for arrays of fixed length strings is not something we currently have the bandwidth for. Hopefully there will be a way at the libnetcdf level to catch this and return an error code; alternatively, a check could be put in before the call to libnetcdf so that the interpreter doesn't pass this through?
It's here: https://github.com/Unidata/netcdf4-python/issues/1172#issuecomment-1168116065
Oh excellent, thank you.