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::Migration5to6 - how to upgrade from 5.xx to 6.00

SYNOPSIS

When upgrading from Date::Manip 5.xx to 6.00, a few changes may be necessary to your scripts.

The Date::Manip::Changes5to6 document lists in more detail the ways in which Date::Manip changed, but very few of these actually entail changes to your script.

It should be noted that once the changes are made to your script, it will no longer run correctly in 5.xx.

NECESSARY AND SUGGESTED CHANGES

The following changes are necessary, or strongly suggested:

Reading config files with Date_Init

If you use Date_Init to read any config files (if you do business mode calculations, you probably do), you should remove all of the following config variables from your call to Date_Init:

GlobalCnf=FILE
PersonalCnf=FILE
PathSep=*
IgnoreGlobalCnf=*
PersonalCnfPath=*

and replace them with:

ConfigFile=FILE

where FILE is now the full path to a config file. Also, the ConfigFile argument should be the first argument in Date_Init.

Date_ConvTZ

The Date_ConvTZ function has changed. It should now take 3 arguments:

$date = Date_ConvTZ($date,$from,$to);

If $from is not given, it defaults to the local time zone. If $to is not given, it defaults to the local time zone.

The date is converted from the $from time zone into the $to time zone. Both should be any time zone (or alias) supported by Date::Manip.

The old $errlevel argument is no longer handled.

ConvTZ and TZ config variables

If you use either the ConvTZ or TZ config variables, you should replace them with either SetDate or ForceDate. See the Date::Manip::Config document for information.

The TZ variable will continue to work until Dec 2015 at which point it will be removed.

Other deprecated config variables

The following config variables have been deprecated, but will continue to function (though they will be removed at a future date):

TZ           (removed Mar 2016)

The following variables have been removed. If you use any of them, you may need to modify your scripts:

IntCharSet
GlobalCnf
PersonalCnf
PathSep
IgnoreGlobalCnf
PersonalCnfPath
ConvTZ
Internal
TodayIsMidnight
DeltaSigns
UpdateCurrTZ
ResetWorkdDay
today, yesterday, tomorrow

If you parse the strings "today", "yesterday", or "tomorrow" in order to get the time now, or 24 hours in the past/future, this will no longer work. These strings now refer strictly to the date (so "today" is the current day at midnight, "yesterday" is the previous day at midnight, etc.).

To get the time now, 24 hours ago, or 24 hours in the future, you would need to parse the strings "now", "-24:00:00", or "+24:00:00" respectively.

Do not use Memoize

In 5.xx, it was documented that you could use the module Memoize to speed up Date::Manip, especially when sorting dates.

This information is no longer accurate. Using Memoize in conjunction with Date::Manip should have little impact on performance, and may lead to incorrect results, especially if you change config variables.

Please refer to "GENERAL CHANGES" in Date::Manip::Changes5to6 for more information.

If you find other instances where it is necessary to modify your script, please email me so that I can add that information to this document.

BUGS AND QUESTIONS

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

SEE ALSO

Date::Manip - main module documentation

LICENSE

This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHOR

Sullivan Beck (sbeck@cpan.org)