Skip to content

Commit ab8fec5

Browse files
authored
Merge pull request #51 from Matars/COverflow
C overflow
2 parents 672f0f9 + 374eb76 commit ab8fec5

File tree

3 files changed

+56
-7
lines changed

3 files changed

+56
-7
lines changed

src/gitfetch/cache.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,27 @@ def _is_cache_expired(self, cached_at: datetime) -> bool:
255255
Returns:
256256
True if expired, False otherwise
257257
"""
258-
expiry_time = datetime.now() - timedelta(minutes=self.cache_expiry_minutes)
258+
# Defensive handling: ensure cache_expiry_minutes is a reasonable int
259+
# and avoid passing an extremely large integer to timedelta which can
260+
# raise OverflowError on some platforms (assuming on 32-bit builds).
261+
try:
262+
minutes = int(self.cache_expiry_minutes)
263+
except Exception:
264+
minutes = 15
265+
266+
# Enforce sensible bounds: minimum 1 minute, cap to MAX_MINUTES
267+
# (10 years expressed in minutes). This prevents OverflowError while
268+
# still allowing very long cache durations when intentionally set.
269+
MAX_MINUTES = 5256000 # 10 years
270+
minutes = max(1, min(minutes, MAX_MINUTES))
271+
272+
try:
273+
expiry_time = datetime.now() - timedelta(minutes=minutes)
274+
except OverflowError:
275+
# In the unlikely event timedelta still overflows, treat cache as
276+
# non-expired (safe default) to avoid crashing the program.
277+
return False
278+
259279
return cached_at < expiry_time
260280

261281
def list_cached_accounts(self) -> list[tuple[str, datetime]]:

src/gitfetch/cli.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,19 @@ def main() -> int:
441441
return 0
442442

443443
except Exception as e:
444-
print(f"Error: {e}", file=sys.stderr)
444+
# When debugging, print full traceback to help diagnose issues
445+
# (useful when users report errors from package builds / other
446+
# environments where the short error message is not enough).
447+
try:
448+
import os
449+
import traceback
450+
if os.environ.get('GITFETCH_DEBUG'):
451+
traceback.print_exc()
452+
else:
453+
print(f"Error: {e}", file=sys.stderr)
454+
except Exception:
455+
# Fallback to simple message if traceback printing fails
456+
print(f"Error: {e}", file=sys.stderr)
445457
return 1
446458

447459
except KeyboardInterrupt:

src/gitfetch/display.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -951,10 +951,18 @@ def _build_month_line(self, weeks_data: list) -> str:
951951

952952
try:
953953
date_obj = datetime.fromisoformat(first_day)
954-
except ValueError:
954+
# Validate year is in reasonable range to avoid C int overflow
955+
if date_obj.year < 1900 or date_obj.year > 9999:
956+
continue
957+
except (ValueError, OverflowError):
955958
continue
956959

957-
month_abbr = date_obj.strftime('%b')
960+
try:
961+
month_abbr = date_obj.strftime('%b')
962+
except (ValueError, OverflowError):
963+
# strftime can fail with years outside 1900-9999
964+
continue
965+
958966
if month_abbr != last_month:
959967
month_chars.append(month_abbr)
960968
last_month = month_abbr
@@ -986,8 +994,11 @@ def _build_month_line_spaced(self, weeks_data: list) -> str:
986994

987995
try:
988996
date_obj = datetime.fromisoformat(first_day)
997+
# Validate year is in reasonable range to avoid C int overflow
998+
if date_obj.year < 1900 or date_obj.year > 9999:
999+
continue
9891000
current_month = date_obj.month
990-
except ValueError:
1001+
except (ValueError, OverflowError):
9911002
continue
9921003

9931004
# Check if this is a new month
@@ -1003,6 +1014,9 @@ def _build_month_line_spaced(self, weeks_data: list) -> str:
10031014
prev_date_obj = datetime.fromisoformat(
10041015
prev_first_day
10051016
)
1017+
# Validate year is in reasonable range
1018+
if prev_date_obj.year < 1900 or prev_date_obj.year > 9999:
1019+
continue
10061020
prev_month = prev_date_obj.month
10071021
if current_month != prev_month:
10081022
# New month - add spacing and month name
@@ -1016,7 +1030,7 @@ def _build_month_line_spaced(self, weeks_data: list) -> str:
10161030
needed_space = max(1, calc)
10171031
month_line += " " * needed_space
10181032
month_line += month_name
1019-
except ValueError:
1033+
except (ValueError, OverflowError):
10201034
pass
10211035

10221036
return f" {month_line}"
@@ -1298,8 +1312,11 @@ def _format_date(self, date_string: str) -> str:
12981312
"""
12991313
try:
13001314
dt = datetime.fromisoformat(date_string.replace('Z', '+00:00'))
1315+
# Validate year is in reasonable range to avoid C int overflow
1316+
if dt.year < 1900 or dt.year > 9999:
1317+
return date_string
13011318
return dt.strftime('%B %d, %Y')
1302-
except (ValueError, AttributeError):
1319+
except (ValueError, AttributeError, OverflowError):
13031320
return date_string
13041321

13051322
def _get_contribution_block(self, count: int) -> str:

0 commit comments

Comments
 (0)