{"action":"created","issue":{"url":"https://api.github.com/repos/UweSchmidt/hxt/issues/14","labels_url":"https://api.github.com/repos/UweSchmidt/hxt/issues/14/labels{/name}","comments_url":"https://api.github.com/repos/UweSchmidt/hxt/issues/14/comments","events_url":"https://api.github.com/repos/UweSchmidt/hxt/issues/14/events","html_url":"https://github.com/UweSchmidt/hxt/issues/14","id":25423222,"number":14,"title":"Stack overflow while unpickling valid document","user":{"login":"orlitzky","id":1432135,"avatar_url":"https://avatars.githubusercontent.com/u/1432135?v=3","gravatar_id":"","url":"https://api.github.com/users/orlitzky","html_url":"https://github.com/orlitzky","followers_url":"https://api.github.com/users/orlitzky/followers","following_url":"https://api.github.com/users/orlitzky/following{/other_user}","gists_url":"https://api.github.com/users/orlitzky/gists{/gist_id}","starred_url":"https://api.github.com/users/orlitzky/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/orlitzky/subscriptions","organizations_url":"https://api.github.com/users/orlitzky/orgs","repos_url":"https://api.github.com/users/orlitzky/repos","events_url":"https://api.github.com/users/orlitzky/events{/privacy}","received_events_url":"https://api.github.com/users/orlitzky/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2014-01-10T21:19:09Z","updated_at":"2015-01-09T15:03:01Z","closed_at":"2015-01-09T15:03:01Z","body":"I realize this schema is not entirely sane; nevertheless I have to parse it. Given a message.dtd,\r\n\r\n```XML\r\n<!ELEMENT Notes (#PCDATA)>\r\n<!ELEMENT GameID (#PCDATA)>\r\n<!ELEMENT Game ( GameID )>\r\n<!ELEMENT message ( ( Notes*, Game+ )* )>\r\n```\r\n\r\nAnd a conforming XML document message.xml,\r\n\r\n```XML\r\n<?xml version=\"1.0\" standalone=\"no\" ?>\r\n<!DOCTYPE message PUBLIC \"-//TSN//DTD Statistics 1.0/EN\" \"message.dtd\">\r\n<message>\r\n</message>\r\n```\r\n\r\nWe check that the document is valid:\r\n\r\n```bash\r\n$ xmllint --valid --noout message.xml && echo $?\r\n0\r\n```\r\n\r\nThe following Haskell code should(?) unpickle this; instead, it crashes at runtime from a stack overflow. I'm aware that non-deterministic schemas are not valid -- and this looks like one to me -- but usually xmllint catches those so it may be possible to parse this.\r\n\r\n```Haskell\r\nmodule Main\r\nwhere\r\n\r\nimport Text.XML.HXT.Core\r\n\r\ndata GameSet =\r\n  GameSet {\r\n    notes :: [String],\r\n    games :: [Game] }\r\n  deriving (Show)\r\n\r\nnewtype Game =\r\n  Game {\r\n    gameId :: Int }\r\n  deriving (Show)\r\n\r\nnewtype Message =\r\n  Message {\r\n    gamesets :: [GameSet] }\r\n  deriving (Show)\r\n\r\npickleGame :: PU Game\r\npickleGame =\r\n  xpWrap (Game, ungame) $\r\n    xpElem \"Game\" $ xpElem \"GameID\" xpInt\r\n  where\r\n    ungame (Game x) = x\r\n\r\npickleGameset :: PU GameSet\r\npickleGameset =\r\n  xpWrap (from_tuple, to_tuple) $\r\n    xpPair (xpList $ xpElem \"Notes\" xpText)\r\n           (xpList pickleGame)\r\n  where\r\n    from_tuple = uncurry GameSet\r\n    to_tuple (GameSet x y) = (x,y)\r\n\r\npickleMessage :: PU Message\r\npickleMessage =\r\n  xpElem \"message\" $\r\n    xpWrap (Message, unmessage) $ xpList pickleGameset\r\n  where\r\n    unmessage (Message gs) = gs\r\n\r\nmain :: IO ()\r\nmain = do\r\n  foo <- runX $ xunpickleDocument\r\n                  pickleMessage\r\n                  [withRemoveWS yes]\r\n                  \"message.xml\"\r\n  print foo\r\n```"},"comment":{"url":"https://api.github.com/repos/UweSchmidt/hxt/issues/comments/69345096","html_url":"https://github.com/UweSchmidt/hxt/issues/14#issuecomment-69345096","issue_url":"https://api.github.com/repos/UweSchmidt/hxt/issues/14","id":69345096,"user":{"login":"UweSchmidt","id":417431,"avatar_url":"https://avatars.githubusercontent.com/u/417431?v=3","gravatar_id":"","url":"https://api.github.com/users/UweSchmidt","html_url":"https://github.com/UweSchmidt","followers_url":"https://api.github.com/users/UweSchmidt/followers","following_url":"https://api.github.com/users/UweSchmidt/following{/other_user}","gists_url":"https://api.github.com/users/UweSchmidt/gists{/gist_id}","starred_url":"https://api.github.com/users/UweSchmidt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/UweSchmidt/subscriptions","organizations_url":"https://api.github.com/users/UweSchmidt/orgs","repos_url":"https://api.github.com/users/UweSchmidt/repos","events_url":"https://api.github.com/users/UweSchmidt/events{/privacy}","received_events_url":"https://api.github.com/users/UweSchmidt/received_events","type":"User","site_admin":false},"created_at":"2015-01-09T15:03:01Z","updated_at":"2015-01-09T15:03:01Z","body":"The problem with your picklers lies in the `pickleGamset`. This pickler builds an empty list of Notes AND an empty list of `Game`s and wraps this into an empty `GameSet`. So the pickler does not consume any XML elements, but generates an element of the list contained in the message element. `xpList pickleGame` must be rewritten into `xpList1 pickleGame` to prevent the infinite loop when unpickling.\r\n"}}