Skip to content

Commit 5b18a35

Browse files
authored
Fix decoding of infinities and NaNs according to specs (#62)
1 parent 55edcd2 commit 5b18a35

2 files changed

Lines changed: 62 additions & 2 deletions

File tree

pytests/test_dag_cbor.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,51 @@ def test_dab_cbor_encode_map_int_key() -> None:
179179
libipld.encode_dag_cbor(obj)
180180

181181
assert 'Map keys must be strings' in str(exc_info.value)
182+
183+
184+
def test_dag_cbor_decode_nan_f64_error() -> None:
185+
# fb7ff8000000000000 - IEEE 754 double precision NaN
186+
with pytest.raises(ValueError) as exc_info:
187+
libipld.decode_dag_cbor(bytes.fromhex('fb7ff8000000000000'))
188+
189+
assert 'number out of range for f64' in str(exc_info.value).lower()
190+
191+
192+
def test_dag_cbor_decode_positive_infinity_f64_error() -> None:
193+
# fb7ff0000000000000 - IEEE 754 double precision positive infinity
194+
with pytest.raises(ValueError) as exc_info:
195+
libipld.decode_dag_cbor(bytes.fromhex('fb7ff0000000000000'))
196+
197+
assert 'number out of range for f64' in str(exc_info.value).lower()
198+
199+
200+
def test_dag_cbor_decode_negative_infinity_f64_error() -> None:
201+
# fbfff0000000000000 - IEEE 754 double precision negative infinity
202+
with pytest.raises(ValueError) as exc_info:
203+
libipld.decode_dag_cbor(bytes.fromhex('fbfff0000000000000'))
204+
205+
assert 'number out of range for f64' in str(exc_info.value).lower()
206+
207+
208+
def test_dag_cbor_decode_nan_f32_error() -> None:
209+
# fa7fc00000 - IEEE 754 single precision NaN
210+
with pytest.raises(ValueError) as exc_info:
211+
libipld.decode_dag_cbor(bytes.fromhex('fa7fc00000'))
212+
213+
assert 'number out of range for f32' in str(exc_info.value).lower()
214+
215+
216+
def test_dag_cbor_decode_positive_infinity_f32_error() -> None:
217+
# fa7f800000 - IEEE 754 single precision positive infinity
218+
with pytest.raises(ValueError) as exc_info:
219+
libipld.decode_dag_cbor(bytes.fromhex('fa7f800000'))
220+
221+
assert 'number out of range for f32' in str(exc_info.value).lower()
222+
223+
224+
def test_dag_cbor_decode_negative_infinity_f32_error() -> None:
225+
# faff800000 - IEEE 754 single precision negative infinity
226+
with pytest.raises(ValueError) as exc_info:
227+
libipld.decode_dag_cbor(bytes.fromhex('faff800000'))
228+
229+
assert 'number out of range for f32' in str(exc_info.value).lower()

src/lib.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,20 @@ fn decode_dag_cbor_to_pyobject<R: Read + Seek>(
199199
cbor::FALSE => false.into_pyobject(py)?.into_any().unbind(),
200200
cbor::TRUE => true.into_pyobject(py)?.into_any().unbind(),
201201
cbor::NULL => py.None(),
202-
cbor::F32 => decode::read_f32(r)?.into_pyobject(py)?.into(),
203-
cbor::F64 => decode::read_f64(r)?.into_pyobject(py)?.into(),
202+
cbor::F32 => {
203+
let value = decode::read_f32(r)?;
204+
if !value.is_finite() {
205+
return Err(anyhow!("Number out of range for f32 (NaNs are forbidden)".to_string()));
206+
}
207+
value.into_pyobject(py)?.into()
208+
},
209+
cbor::F64 => {
210+
let value = decode::read_f64(r)?;
211+
if !value.is_finite() {
212+
return Err(anyhow!("Number out of range for f64 (NaNs are forbidden)".to_string()));
213+
}
214+
value.into_pyobject(py)?.into()
215+
},
204216
_ => return Err(anyhow!("Unsupported major type".to_string())),
205217
},
206218
})

0 commit comments

Comments
 (0)