Overflow While Parsing IPv4 Addresses
The DecimalMaxSO implementation on Stack Overflow was written in the context of parsing octets of IPv4 addresses. Curious to see if the libraries on Hackage deal with overflow, I checked out the most popular libraries that parse IPv4 addresses.
Some test code is available on GitHub.
iproute
The iproute
library parses strings using the appar library.
Octet values are accumulated using an Int
type. The octet
bounds are checked after the whole number has been parsed,
however, so it is subject to Int
overflow.
λ: import Data.IP (IPv4)
λ: print @IPv4 $ read "127.0.0.18446744073709551617"
127.0.0.1
While I do not think that this issue is significant, I created a GitHub issue to report it.
Note that the DecimalMaxStrict implementation does not have this issue because the maximum bound is checked as the number is parsed.
λ: import DecimalMaxStrict
λ: import qualified Data.Attoparsec.Text as AT
λ: AT.parseOnly (word8 True) "18446744073709551617"
Left "decimalMax: Failed reading: overflow"
it :: Either String Word8
ip
The ip library
parses strings using a text Reader.
Octet values are parsed by the decimal
function using a
Word
type. The octet bounds are checked after the
whole number has been parsed, so it is subject to Word
overflow.
λ: import Net.IPv4 (decode)
λ: print $ decode "127.0.0.18446744073709551617"
Just (ipv4 127 0 0 1)
While I do not think that this issue is significant, I created a GitHub issue to report it.
network-ip
The network-ip
library parses strings using the data-textual
library. It parses octets using an Int
type, and it uses
the nnUpTo
function to limit each octet to three digits, avoiding overflow.
hw-ip
The hw-ip
library also parses strings using the appar library. It
parses octets by matching digits similar to how people use regular
expressions for validation, using overlapping groups for improved
performance. (I wondered what kind of error messages this leads to, and
I found that appar only parses
to Maybe
and therefore does not provide error messages.)
This constrains the parsed value, avoiding overflow.
octet :: AP.Parser Word8
= AP.try ((digits 1 2 #<*># digit 5 ) #<*># digits 0 5)
octet <|> AP.try ((digits 1 2 #<*># digits 0 4) #<*># digits 0 9)
<|> AP.try (( digit 1 #<*># digits 0 9) #<*># digits 0 9)
<|> AP.try ( digits 1 9 #<*># digits 0 9)
<|> digits 0 9