使用attoparsec解析IP地址

多纳泰洛

https://www.fpcomplete.com/school/starting-with-haskell/libraries-and-frameworks/text-manipulation/attoparsec给出的解析器似乎可以正常工作,但是有问题。

代码(此处重复)为:

{-# LANGUAGE OverloadedStrings #-}

-- This attoparsec module is intended for parsing text that is
-- represented using an 8-bit character set, e.g. ASCII or ISO-8859-15.
import Data.Attoparsec.Char8
import Data.Word

-- | Type for IP's.
data IP = IP Word8 Word8 Word8 Word8 deriving Show

parseIP :: Parser IP
parseIP = do
  d1 <- decimal
  char '.'
  d2 <- decimal
  char '.'
  d3 <- decimal
  char '.'
  d4 <- decimal
  return $ IP d1 d2 d3 d4

main :: IO ()
main = print $ parseOnly parseIP "131.45.68.123"

如果解析器输入了无效的IP地址(例如“ 1000.1000.1000.1000”),则由于强制数字转换,它不会失败并返回垃圾结果。

有简单的方法可以解决此问题吗?一种方法是使用较大的Word类型,例如,Word32并检查数字是否小于256。但是,如果输入是病理性的,即使返回的数也可能会返回垃圾(例如Word32,也发生溢出)。转换为Integer似乎是一个选择,因为它是不受限制的,但是同样,对抗性输入可能会使程序用尽内存。

那么,一个避免这些问题的(非常优雅的)解析器会是什么样呢?

用户名

我对您的问题的理解是,您不仅要在输入数字太大时失败,而且也不想让解析器消耗比所需更多的输入。

我们可以定义一个函数来解析最大整数,否则将失败:

import Data.Attoparsec.ByteString.Char8
import Data.Word
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Control.Applicative
import Data.List (foldl')
import Control.Monad 

decimalMax :: Integral a => Integer -> Parser a 
decimalMax dMax = do  
  let numDigs = ceiling $ log (fromIntegral(dMax+1)) / log 10
      getVal = foldl' (\s d -> s*10+fromIntegral (d-48)) 0 . B.unpack
  val <- getVal <$> scan 0 (\n c -> 
          if n > numDigs || not (isDigit c) then Nothing else Just (n+1)) 
  if val <= dMax 
    then return $ fromIntegral val 
    else fail $ "decimalMax: parsed decimal exceeded" ++ show dMax

此函数计算最大位数中的位数,然后仅消耗最多位数。您的IP地址解析器几乎保持不变:

parseIP :: Parser IP
parseIP = IP <$> dd <*> dd <*> dd <*> dig where 
  dig = decimalMax 255
  dd = dig <* char '.' 

main :: IO ()
main = do
  print $ parseOnly parseIP "131.45.68.123"
  print $ parseOnly parseIP "1000.1000.1000.1000"

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用Ruby从IP地址解析域

来自分类Dev

使用Ruby从IP地址解析域

来自分类Dev

使用Attoparsec解析简单的分子名称

来自分类Dev

如何使用Attoparsec解析雅虎历史csv

来自分类Dev

使用Attoparsec解析简单的分子名称

来自分类Dev

解析ifconfig以使用Bash仅获取我的IP地址

来自分类Dev

使用awk在MacOS上从netstat输出解析IP地址

来自分类Dev

在Linux中从IP地址解析MAC地址

来自分类Dev

用dpkt解析IP地址

来自分类Dev

解析IP地址以获得域名

来自分类Dev

解析txt中的IP地址

来自分类Dev

使用attoparsec解析逗号内的逗号分隔字符串

来自分类Dev

当前使用的IP地址

来自分类Dev

IP地址使用的语言

来自分类Dev

从ARP命令BATCH解析IP地址

来自分类Dev

解析与多个域名对应的IP地址

来自分类Dev

在Python上从.TXT文件解析IP地址

来自分类Dev

IP地址解析为Ubuntu版本

来自分类Dev

MySQL 警告:无法解析 IP 地址

来自分类Dev

使用Ruby将IP地址的文本文件解析为数组?

来自分类Dev

使用标准命令行工具解析命令输出中的所有IP地址

来自分类Dev

如何在Linux下使用host命令批量反向解析IP地址?

来自分类Dev

使用php检查IP地址

来自分类Dev

获取未使用的IP地址

来自分类Dev

IP地址0.0.0.0是否使用?

来自分类Dev

使用VPN时的IP地址

来自分类Dev

使用SpamAssassin阻止IP地址

来自分类Dev

Twitterbot使用的IP地址列表

来自分类Dev

使用grep获取IP地址