Skip to content

_zoneinfo: get_local_timestamp() misinterprets valid -1 results from PyLong_AsLong() #154892

Description

@BHUVANSH855

Bug report

Bug description:

Modules/_zoneinfo.c:get_local_timestamp() incorrectly treats the valid integer value -1 returned by PyLong_AsLong() as an error for the hour, minute, and second fields.

PyLong_AsLong() returns -1 both on conversion failure and for the legitimate Python integer -1. The C API requires checking PyErr_Occurred() to distinguish these cases.

The function already does this correctly for toordinal():

ord = PyLong_AsLong(num);
if (ord == -1 && PyErr_Occurred()) {
    return -1;
}

However, the checks for hour, minute, and second only test == -1:

hour = PyLong_AsLong(num);
if (hour == -1) {
    return -1;
}

minute = PyLong_AsLong(num);
if (minute == -1) {
    return -1;
}

second = PyLong_AsLong(num);
if (second == -1) {
    return -1;
}

As a result, valid values of -1 are incorrectly treated as conversion failures, causing the function to return an error without an exception being set.

Reproducer

from datetime import datetime
from zoneinfo import ZoneInfo

class BadDateTime(datetime):
    @property
    def hour(self):
        return -1

dt = BadDateTime(2024, 1, 1, tzinfo=ZoneInfo("UTC"))
dt.utcoffset()

Current behavior:

SystemError: <method 'utcoffset' of 'zoneinfo.ZoneInfo' objects> returned NULL without setting an exception

The same issue also affects:

  • ZoneInfo.dst()
  • ZoneInfo.tzname()
  • ZoneInfo.fromutc()

The issue reproduces on the current main branch on Linux.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions