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::Interfaces - A description of functional and OO interfaces

DESCRIPTION

There are three different ways to use Date::Manip . A complete description of each is included below. They are:

Functional interface (version 5)

Date::Manip version 5 runs on very old versions of perl. If you need to use Date::Manip with a version of perl older than 5.10, this is the only interface available.

Functional interface (version 6)

When Date::Manip was rewritten (version 6), it made use of some features of perl 5.10 . This is the recommended interface if you are supporting a script that uses the functional interface, but where a newer version of perl is available.

Object-oriented interface

The OO interface is the recommended interface wherever possible. It is the only one with access to the full functionality of the module.

VERSION 5 AND VERSION 6

Date::Manip version 5.xx was available for many years, but suffered from several weaknesses. It was slow, and did not handle timezones or daylight saving time correctly. It was written as a functional interface, even though an object-oriented interface would have been better. It did have the advantage of running on very old versions of perl (it is known to work on perl 5.6 and may work on even older versions of perl).

Date::Manip version 6.00 was a complete rewrite of the module. For detailed information about the differences, please refer to the Date::Manip::Changes5to6 document. The rewrite was needed in order to handle timezone operations, in addition to many other improvements including much better performance and more robust parsing.

The rewrite made use of features introduced in perl 5.10 which made the date parsing routines significantly cleaner. In addition, the 6.xx release was written as an object oriented set of modules which are much more powerful than the older functional interface. For backward compatibility, a new functional interface was rewritten (which is simply a set of wrapper functions which call the OO methods) which is almost entirely backward compatible with the version 5.xx interface.

The Date::Manip distribution includes all three of these interfaces: the older version 5 interface, and both the new OO interface and the backward compatible functional interface. Also, all three are installed, so you can use whichever interface is appropriate.

Since there are three different interfaces available, choosing the interface is the necessary.

If you are running on a system with a very old version of perl (older than 5.10), the version 5 interface is your only option.

If you are on a system running a newer version of perl, but need to support a script that was written using the functional interface, then you can use the version 6 functional interface.

For everyone else, it is strongly recommended that you use the object-oriented interface.

A more detailed description of each interface is included below. If you already know which interface you want to use, just go to the "SEE ALSO" in Date::Manip section for documentation for each interface.

FUNCTIONAL INTERFACE (VERSION 5)

When using a version of perl older than 5.10, this is the only interface available. This interface is documented in the Date::Manip::DM5 document. This interface has several weaknesses that need to be understood when using it:

Limited Support

The version 5 functional interface is no longer being developed, and only limited support is available for it.

As of December 2012, no development will be done, and I will not correct any remaining bugs in version 5. If a patch is supplied by someone else to fix bugs, I will apply it, provided it applies cleanly, and the resulting code continues to pass all tests. I will not apply patches to add features.

I intend to remove this in version 7.00.

Limited Time Zone Support

Time zone support is extremely limited, and is often incorrect. The lack of time zone support was the primary reason for rewriting Date::Manip.

The version 5 interface does not handle daylight saving time changes correctly.

Performance Issues

Considerable time has been spent speeding up Date::Manip, and fairly simple benchmarks show that version 6 is around twice as fast as version 5.

Feel free to email me concerns and comments.

FUNCTIONAL INTERFACE (VERSION 6)

The version 6 functional interface is almost completely identical to the version 5 functional interface, except that it uses the object-oriented modules to do all the real work.

Time zone support is greatly improved, but is still somewhat limited. Since the version 6 interface is backward compatible, dates do not store time zone information in them, so the programmer is responsible for keeping track of what time zone each date is in. If you want full access to the time zone support offered in Date::Manip, you have to use the object-oriented interface.

For the most part, scripts written for older versions of Date::Manip will continue to work (and scripts written for the version 6 functional interface will run with the version 5 interface), however in a few cases, you may need to modify your scripts. Please refer to the Date::Manip::Migration5to6 document for a list of changes which may be necessary.

OBJECT-ORIENTED INTERFACE

As of 6.00, Date::Manip consists of a set of OO modules. Each have their own document (see the "SEE ALSO" in Date::Manip section).

The OO interface consists of the following modules: Date::Manip::Date, Date::Manip::Delta, Date::Manip::Recur, Date::Manip::TZ, and Date::Manip::Base.

The object-oriented interface is the only way to get the full functionality of Date::Manip. It fully support time zones (and daylight saving time).

SELECTING AN INTERFACE

If you are running an older version of perl, the version 5 functional interface is the only one available to you, and it will automatically be used.

If you are running a newer version of perl (5.10 or higher), you can use the object-oriented modules by loading them directly, or you can use a functional interface.

If you use a functional interface, it will default to the version 6 interface, but you can choose to run the version 5 interface in one of three ways:

Using the OO interface

By including any of the following:

use Date::Manip::Date;
use Date::Manip::Delta;
use Date::Manip::Recur;
use Date::Manip::TZ;
use Date::Manip::Base;

you have access to the OO interface for the appropriate types of objects.

Use the default functional interface

By including:

use Date::Manip;

in your script, one of the functional interfaces will be loaded. If you are running a version of perl older than 5.10, it will automatically be the version 5 interface. If you are running a newer version of perl, it will automatically load the version 6 interface.

DATE_MANIP environment variable

By setting the DATE_MANIP environment variable to 'DM5' before running the perl script, the version 5 interface will be used.

Date::Manip::Backend variable

Alternately, you can set the Date::Manip::Backend variable to be 'DM5' before loading the module. Typically, this will be done in the following way:

BEGIN {
     $Date::Manip::Backend = 'DM5';
}
use Date::Manip;

Once a functional interface is loaded, you cannot switch between the version 5 and version 6 interfaces.

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)