Security Advisories (2)
CVE-2026-60074 (2026-07-30)

Date::Manip versions through 6.99 for Perl return corrupted dates via non-ASCII decimal digits that pass the numeric range tests in check. The parse regexes capture year, month and day with the `\d` shorthand, which on a character string matches the whole Unicode decimal digit property `\p{Nd}` and not just `[0-9]`. Date::Manip::Base::check then validates the captured fields with numeric comparisons alone (`$y<1 || $y>9999`, `$m<1 || $m>12`, `$d<1 || $d>$days`), and _parse_check stores the numified fields (`$y+0`). Perl truncates a string at the first character that is not an ASCII digit, so a field whose leading characters are ASCII digits numifies to an in-range prefix and satisfies every test: a year field of three ASCII digits followed by U+0664 ARABIC-INDIC DIGIT FOUR numifies to 202, giving the year 0202, and one non-ASCII digit in the month or day field shifts those fields the same way. The hour, minute and second fields match explicit ASCII character classes (`0?[0-9]`, `[0-5][0-9]`) and do not shift, though a non-ASCII digit in a fractional hour or minute field truncates the fraction. Any caller that passes an untrusted character string to ParseDate() or Date::Manip::Date->parse() can get back a date that differs from the string it parsed, with no parse error. Where the parsed date gates logic such as an expiry check or a retention window, the shift goes unnoticed.

CVE-2026-60075 (2026-07-30)

Date::Manip versions through 6.99 for Perl allow CPU exhaustion via quadratic backtracking in the unanchored time substitution in _parse_time. _parse_time removes a time from anywhere in the string with the unanchored substitution `s/$timerx/ /`, where $timerx is an auto-generated alternation of time patterns reached through a leading `(?:$atrx|^|\s+)`. The engine therefore retries the match at every position of an interior whitespace run: at each start position the leading `\s+` consumes the rest of the run greedily, the time alternation fails because the run holds no digits, and the engine backtracks a space at a time across the run before advancing the start position, which is quadratic in the length of the run. No time need be present in the string for this to happen, only a long run of whitespace, and the parse time rises about fourfold for each doubling of the run: a few kilobytes of whitespace costs seconds of CPU per parse and tens of kilobytes costs minutes. Any caller that passes an untrusted string of unbounded length to ParseDate(), Date::Manip::Date->parse() or ->parse_time() can be made to spend unbounded CPU in a single parse, a denial of service.

NAME

Date::Manip::TZdata -- Internal module for working with the tzdata files

SYNOPSIS

use Date::Manip::TZdata;

$tzd  = new Date::Manip::TZdata($dir);

DESCRIPTION

This module is not intended for public use. It is used internally by the scripts used to analyze the time zone database and generate the modules for each time zone. The module is included in the distribution solely for the sake of completeness. Currently, no support is offered for this module, and it can (and may) change without notice.

This module consists of routines for working with the tzdata files. These files are updated several times a year and are the basis for time zone descriptions for most computer systems.

ROUTINES

new
use Date::Manip::TZdata;

$tzd  = new Date::Manip::TZdata($dir);

This finds and reads in all the tzdata. If $dir is passed in, it is the directory where a tzdata directory is located. It defaults to the current directory.

KNOWN LIMITATIONS

Some assumptions and limitations are assumed in the logic of this module.

When a time change occurs, the time may change backwards or forwards. Time changes rules are listed on a per-year basis. It is assumed that time changes will not occur so close to the end or start of the year as to cross the year boundary (in other words, the year will not change as a result of the time change). This is not accounted for, and it is hoped that this situation will never occur.

Also, because this module is strictly limited to 4 digit positive years (regardless of whether it is wall clock or universal time), and because various parts of the module switch back and forth, valid times for this module are from Jan 2, 0001 to Dec 30, 9999. This ensures that conversions from wall clock to universal or vice versa will never make dates occur in the year 0000 or 10000.

KNOWN BUGS

None known.

BUGS AND QUESTIONS

Please refer to the Date::Manip man page for information on submitting bug reports or questions to the author.

AUTHOR

Sullivan Beck (sbeck@cpan.org)