[PATCH] Ensure safe 32-bit date if timegm() fails

dinkypumpkin dinkypumpkin at gmail.com
Thu Apr 7 16:43:52 EDT 2011


This patch originated from the thread that begins here:

http://lists.infradead.org/pipermail/get_iplayer/2011-March/001078.html

While hacking on get_iplayer to download embedded media clips from a couple 
of other BBC web sites, I discovered a problem (explained in the commit 
message below) with the logic used to compute expiry dates for downloaded
programmes.  A few media clips had expiry dates too large for get_iplayer
to handle, so it would bomb.  This is an esoteric issue that will likely
never affect normal iPlayer programmes, which of course expire fairly 
quickly.  Still, I couldn't let a bug remain unfixed if I could help it.
I also hope to work in general support for downloading from embedded clip
URLs, and this patch would be necessary for that.

Updated get_iplayer script here:

https://github.com/dinkypumpkin/get_iplayer/raw/patched/get_iplayer

Commit history here:

https://github.com/dinkypumpkin/get_iplayer/commits/patched/

Patch follows -

get_iplayer uses timegm() to calculate expiry dates for
downloaded programmes.  In 32-bit versions of perl or any
perl < 5.10.1, timegm() croaks for any date greater than
2038-01-16 23:59:59.  The current approach of setting
year = 2038 for any dates in 2038 and after is insufficient
to ensure a safe 32-bit date.  This patch changes the code
to run timegm() within an eval block.  If timegm() croaks,
epoch date is set to arbitrary safe value (2038-01-01 00:00:00).
Redundant calls to to timegm() have also been removed.

The problem corrected by this patch is very much an edge case,
so far only observed when using a hacked get_iplayer to download
media clips embedded in other BBC web sites.  However, the logic
is still incorrect, so this patch has been created to fix it.
---
 get_iplayer |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/get_iplayer b/get_iplayer
index 81d6dea..3d68865 100755
--- a/get_iplayer
+++ b/get_iplayer
@@ -4839,15 +4839,15 @@ sub get_time_string {
 	main::logger "DEBUG: $_ = $year, $mon, $mday, $hour, $min, $sec, $tzhour, $tzmin\n" if $opt->{debug};
 	# Sanity check date data
 	return '' if $year < 1970 || $mon < 1 || $mon > 12 || $mday < 1 || $mday > 31 || $hour < 0 || $hour > 24 || $min < 0 || $min > 59 || $sec < 0 || $sec > 59 || $tzhour < -13 || $tzhour > 13 || $tzmin < -59 || $tzmin > 59;
-	# Year cannot be > 2032 so limit accordingly :-/
-	$year = 2038 if $year > 2038;
 	# Calculate the seconds difference between epoch_now and epoch_datestring and convert back into array_time
-	my $epoch = timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60;
+	my $epoch = eval { timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60; };
+	# ensure safe 32-bit date if timegm croaks
+	if ( $@ ) { $epoch = timegm(0, 0, 0, 1, 0, 138, undef, undef, 0) - $tzhour*60*60 - $tzmin*60; };
 	my $rtn;
 	if ( $diff ) {
 		# Return time ago
 		if ( $epoch < $diff ) {
-			my @time = gmtime( $diff - ( timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60 ) );
+			my @time = gmtime( $diff - $epoch );
 			# The time() func gives secs since 1970, gmtime is since 1900
 			my $years = $time[5] - 70;
 			$rtn = "$years years " if $years;
@@ -4855,7 +4855,7 @@ sub get_time_string {
 			return $rtn;
 		# Return time to go
 		} elsif ( $epoch > $diff ) {
-			my @time = gmtime( ( timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60 ) - $diff );
+			my @time = gmtime( $epoch - $diff );
 			my $years = $time[5] - 70;
 			$rtn = 'in ';
 			$rtn .= "$years years " if $years;
@@ -4868,7 +4868,7 @@ sub get_time_string {
 	# Return time in epoch
 	} else {
 		# Calculate the seconds difference between epoch_now and epoch_datestring and convert back into array_time
-		return timegm($sec, $min, $hour, $mday, ($mon-1), ($year-1900), undef, undef, 0) - $tzhour*60*60 - $tzmin*60;
+		return $epoch;
 	}
 }
 
-- 
1.7.4.3




More information about the get_iplayer mailing list