haskell / haskell/time

Timezone offset parsers accept out-of-range minute fields

Open
#305 0 comments 0 reactions 0 assignees View on GitHub
defect
Dominant language
Haskell
Stars
135
Forks
83
PR merge metrics
No merged PRs in 30d

Description

Codex found this during an algorithm-defect audit of the `time` codebase.

Audited revision: `8706e568aafcd4562fde792374b94b735ae53a0a`.

## Summary

Both `%z` parsing and the ISO 8601 `timeOffsetFormat` accept numeric timezone offsets without validating their hour/minute components. A minute field of `60` is normalized into an extra hour instead of being rejected.

## Reproduction

```haskell
parseTimeM False defaultTimeLocale "%z" "+2360" :: Maybe TimeZone
-- Just +2400

formatParseM (timeOffsetFormat ExtendedFormat) "+23:60"
-- Just +2400

formatParseM (timeOffsetFormat ExtendedFormat) "+24:01"
-- Just +2401
```

## Expected

Malformed offsets should fail. In particular, the minute component must be in `00..59`; the ISO parser should also enforce the permitted overall ISO 8601 offset range.

## Actual

The parsers calculate `hours * 60 + minutes`, accepting invalid input as a different offset.

## Affected code

- `lib/Data/Time/Format/Parse/Instances.hs`: `readTzOffset`.
- `lib/Data/Time/Format/ISO8601.hs`: `timeOffsetFormat` (`digits2` plus unrestricted `isoMap`).

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with `readTzOffset` in `lib/Data/Time/Format/Parse/Instances.hs` and `timeOffsetFormat` in `lib/Data/Time/Format/ISO8601.hs`, reproducing the `%z` and ISO examples from the issue. Trace how the hour and minute fields are converted, then verify that malformed offsets fail while valid offsets continue to parse within the permitted range.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.