Skip to content

Commit

Permalink
Merge pull request #2289 from davidhewitt/fix-get-tzinfo
Browse files Browse the repository at this point in the history
ffi: fix segfault in _GET_TZINFO methods
  • Loading branch information
davidhewitt committed Apr 10, 2022
2 parents 2a54641 + 1d9d60a commit e6901e3
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Default to "m" ABI tag when choosing `libpython` link name for CPython 3.7 on Unix. [#2288](https://github.com/PyO3/pyo3/pull/2288)

### Fixed

- Fix segfault when calling FFI methods `PyDateTime_DATE_GET_TZINFO` or `PyDateTime_TIME_GET_TZINFO` on `datetime` or `time` without a tzinfo. [#2289](https://github.com/PyO3/pyo3/pull/2289)

## [0.16.3] - 2022-04-05

### Packaging
Expand Down
6 changes: 5 additions & 1 deletion pyo3-ffi/src/datetime.rs
Expand Up @@ -155,7 +155,11 @@ macro_rules! _PyDateTime_GET_FOLD {
#[cfg(not(PyPy))]
macro_rules! _PyDateTime_GET_TZINFO {
($o: expr) => {
(*$o).tzinfo
if (*$o).hastzinfo != 0 {
(*$o).tzinfo
} else {
$crate::Py_None()
}
};
}

Expand Down
41 changes: 41 additions & 0 deletions src/ffi/tests.rs
Expand Up @@ -180,3 +180,44 @@ fn ucs4() {
}
})
}

#[test]
#[cfg(not(PyPy))]
fn test_get_tzinfo() {
crate::Python::with_gil(|py| {
use crate::types::{PyDateTime, PyTime};
use crate::{AsPyPointer, PyAny, ToPyObject};

let datetime = py.import("datetime").map_err(|e| e.print(py)).unwrap();
let timezone = datetime.getattr("timezone").unwrap();
let utc = timezone.getattr("utc").unwrap().to_object(py);

let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap();

assert!(
unsafe { py.from_borrowed_ptr::<PyAny>(PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) }
.is(&utc)
);

let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap();

assert!(
unsafe { py.from_borrowed_ptr::<PyAny>(PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) }
.is_none()
);

let t = PyTime::new(py, 0, 0, 0, 0, Some(&utc)).unwrap();

assert!(
unsafe { py.from_borrowed_ptr::<PyAny>(PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }
.is(&utc)
);

let t = PyTime::new(py, 0, 0, 0, 0, None).unwrap();

assert!(
unsafe { py.from_borrowed_ptr::<PyAny>(PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }
.is_none()
);
})
}

0 comments on commit e6901e3

Please sign in to comment.