Skip to content

Commit ac0083f

Browse files
glguyblackheaven
authored andcommitted
Support toml-parser-2.0.0.0
This new version provides native Text support and mapping schema errors back to source positions.
1 parent 4fe2935 commit ac0083f

File tree

3 files changed

+47
-44
lines changed

3 files changed

+47
-44
lines changed

code/hsec-tools/hsec-tools.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ library
6161
, safe >=0.3
6262
, text >=1.2 && <3
6363
, time >=1.9 && <1.14
64-
, toml-parser ^>=1.3.0.0
64+
, toml-parser ^>=2.0.0.0
6565
, validation-selective >=0.1 && <1
6666

6767
hs-source-dirs: src

code/hsec-tools/src/Security/Advisories/Parse.hs

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,17 @@ import qualified Commonmark.Parser as Commonmark
3636
import Commonmark.Types (HasAttributes(..), IsBlock(..), IsInline(..), Rangeable(..), SourceRange(..))
3737
import Commonmark.Pandoc (Cm(unCm))
3838
import qualified Toml
39-
import qualified Toml.Pretty as Toml
40-
import qualified Toml.FromValue as Toml
41-
import qualified Toml.FromValue.Matcher as Toml
42-
import qualified Toml.ToValue as Toml
39+
import qualified Toml.Syntax as Toml (startPos)
40+
import qualified Toml.Schema as Toml
4341
import Text.Pandoc.Builder (Blocks, Many(..))
4442
import Text.Pandoc.Definition (Block(..), Inline(..), Pandoc(..))
4543
import Text.Pandoc.Walk (query)
4644
import Text.Parsec.Pos (sourceLine)
4745

4846
import Security.Advisories.Core.HsecId
4947
import Security.Advisories.Core.Advisory
50-
import Security.OSV (Reference(..), referenceTypes)
48+
import Security.OSV (Reference(..), ReferenceType, referenceTypes)
5149
import qualified Security.CVSS as CVSS
52-
5350
-- | A source of attributes supplied out of band from the advisory
5451
-- content. Values provided out of band are treated according to
5552
-- the 'AttributeOverridePolicy'.
@@ -80,7 +77,7 @@ data ParseAdvisoryError
8077
= MarkdownError Commonmark.ParseError T.Text
8178
| MarkdownFormatError T.Text
8279
| TomlError String T.Text
83-
| AdvisoryError [Toml.MatchMessage] T.Text
80+
| AdvisoryError [Toml.MatchMessage Toml.Position] T.Text
8481
deriving stock (Eq, Show, Generic)
8582

8683
-- | The main parsing function. 'OutOfBandAttributes' are handled
@@ -99,7 +96,7 @@ parseAdvisory policy attrs raw = do
9996
(frontMatter, rest) <- first MarkdownFormatError $ advisoryDoc markdown
10097
let doc = Pandoc mempty rest
10198
!summary <- first MarkdownFormatError $ parseAdvisorySummary doc
102-
table <- case Toml.parse (T.unpack frontMatter) of
99+
table <- case Toml.parse frontMatter of
103100
Left e -> Left (TomlError e (T.pack e))
104101
Right t -> Right t
105102

@@ -129,10 +126,8 @@ parseAdvisory policy attrs raw = do
129126
(Commonmark.commonmark "input" raw :: Either Commonmark.ParseError (Html ()))
130127

131128
case parseAdvisoryTable attrs policy doc summary details html table of
132-
Toml.Failure es -> Left (AdvisoryError es (T.pack (unlines (map Toml.prettyMatchMessage es))))
133-
Toml.Success warnings adv
134-
| null warnings -> pure adv
135-
| otherwise -> Left (AdvisoryError warnings (T.pack (unlines (map Toml.prettyMatchMessage warnings)))) -- treat warnings as errors
129+
Left es -> Left (AdvisoryError es (T.pack (unlines (map Toml.prettyMatchMessage es))))
130+
Right adv -> pure adv
136131

137132
where
138133
firstPretty
@@ -156,11 +151,11 @@ parseAdvisoryTable
156151
-> T.Text -- ^ summary
157152
-> T.Text -- ^ details
158153
-> T.Text -- ^ rendered HTML
159-
-> Toml.Table
160-
-> Toml.Result Toml.MatchMessage Advisory
154+
-> Toml.Table' Toml.Position
155+
-> Either [Toml.MatchMessage Toml.Position] Advisory
161156
parseAdvisoryTable oob policy doc summary details html tab =
162-
Toml.runMatcher $
163-
do fm <- Toml.fromValue (Toml.Table tab)
157+
Toml.runMatcherFatalWarn $
158+
do fm <- Toml.fromValue (Toml.Table' Toml.startPos tab)
164159
published <-
165160
mergeOobMandatory policy
166161
(oobPublished oob)
@@ -211,7 +206,7 @@ instance Toml.ToValue FrontMatter where
211206
toValue = Toml.defaultTableToValue
212207

213208
instance Toml.ToTable FrontMatter where
214-
toTable x = Map.fromList
209+
toTable x = Toml.table
215210
[ "advisory" Toml..= frontMatterAdvisory x
216211
, "affected" Toml..= frontMatterAffected x
217212
, "references" Toml..= frontMatterReferences x
@@ -253,7 +248,7 @@ instance Toml.ToValue AdvisoryMetadata where
253248
toValue = Toml.defaultTableToValue
254249

255250
instance Toml.ToTable AdvisoryMetadata where
256-
toTable x = Map.fromList $
251+
toTable x = Toml.table $
257252
["id" Toml..= amdId x] ++
258253
["modified" Toml..= y | Just y <- [amdModified x]] ++
259254
["date" Toml..= y | Just y <- [amdPublished x]] ++
@@ -283,7 +278,7 @@ instance Toml.ToValue Affected where
283278
toValue = Toml.defaultTableToValue
284279

285280
instance Toml.ToTable Affected where
286-
toTable x = Map.fromList $
281+
toTable x = Toml.table $
287282
[ "package" Toml..= affectedPackage x
288283
, "cvss" Toml..= affectedCVSS x
289284
, "versions" Toml..= affectedVersions x
@@ -307,7 +302,7 @@ instance Toml.ToValue AffectedVersionRange where
307302
toValue = Toml.defaultTableToValue
308303

309304
instance Toml.ToTable AffectedVersionRange where
310-
toTable x = Map.fromList $
305+
toTable x = Toml.table $
311306
("introduced" Toml..= affectedVersionRangeIntroduced x) :
312307
["fixed" Toml..= y | Just y <- [affectedVersionRangeFixed x]]
313308

@@ -316,7 +311,7 @@ instance Toml.FromValue HsecId where
316311
fromValue v =
317312
do s <- Toml.fromValue v
318313
case parseHsecId s of
319-
Nothing -> fail "invalid HSEC-ID: expected HSEC-[0-9]{4,}-[0-9]{4,}"
314+
Nothing -> Toml.failAt (Toml.valueAnn v) "invalid HSEC-ID: expected HSEC-[0-9]{4,}-[0-9]{4,}"
320315
Just x -> pure x
321316

322317
instance Toml.ToValue HsecId where
@@ -335,11 +330,11 @@ instance Toml.ToValue Keyword where
335330
toValue (Keyword x) = Toml.toValue x
336331

337332
-- | Get a datetime with the timezone defaulted to UTC and the time defaulted to midnight
338-
getDefaultedZonedTime :: Toml.Value -> Toml.Matcher ZonedTime
339-
getDefaultedZonedTime (Toml.ZonedTime x) = pure x
340-
getDefaultedZonedTime (Toml.LocalTime x) = pure (ZonedTime x utc)
341-
getDefaultedZonedTime (Toml.Day x) = pure (ZonedTime (LocalTime x midnight) utc)
342-
getDefaultedZonedTime _ = fail "expected a date with optional time and timezone"
333+
getDefaultedZonedTime :: Toml.Value' l -> Toml.Matcher l ZonedTime
334+
getDefaultedZonedTime (Toml.ZonedTime' _ x) = pure x
335+
getDefaultedZonedTime (Toml.LocalTime' _ x) = pure (ZonedTime x utc)
336+
getDefaultedZonedTime (Toml.Day' _ x) = pure (ZonedTime (LocalTime x midnight) utc)
337+
getDefaultedZonedTime v = Toml.failAt (Toml.valueAnn v) "expected a date with optional time and timezone"
343338

344339
advisoryDoc :: Blocks -> Either T.Text (T.Text, [Block])
345340
advisoryDoc (Many blocks) = case blocks of
@@ -375,21 +370,22 @@ inlineText = query f
375370

376371
instance Toml.FromValue Reference where
377372
fromValue = Toml.parseTableFromValue $
378-
do refTypeStr <- Toml.reqKey "type"
379-
refType <- case lookup refTypeStr (fmap swap referenceTypes) of
380-
Just a -> pure a
381-
Nothing ->
382-
fail $
383-
"Invalid format for reference.type: " ++ T.unpack refTypeStr ++
384-
" should be one of: " ++ intercalate ", " (T.unpack . snd <$> referenceTypes)
385-
url <- Toml.reqKey "url"
386-
pure $ Reference refType url
373+
do refType <- Toml.reqKey "type"
374+
url <- Toml.reqKey "url"
375+
pure (Reference refType url)
376+
377+
instance Toml.FromValue ReferenceType where
378+
fromValue (Toml.Text' _ refTypeStr)
379+
| Just a <- lookup refTypeStr (fmap swap referenceTypes) = pure a
380+
fromValue v =
381+
Toml.failAt (Toml.valueAnn v) $
382+
"reference.type should be one of: " ++ intercalate ", " (T.unpack . snd <$> referenceTypes)
387383

388384
instance Toml.ToValue Reference where
389385
toValue = Toml.defaultTableToValue
390386

391387
instance Toml.ToTable Reference where
392-
toTable x = Map.fromList
388+
toTable x = Toml.table
393389
[ "type" Toml..= fromMaybe "UNKNOWN" (lookup (referencesType x) referenceTypes)
394390
, "url" Toml..= referencesUrl x
395391
]
@@ -405,7 +401,7 @@ instance Toml.FromValue OS where
405401
"mingw32" -> pure Windows
406402
"netbsd" -> pure NetBSD
407403
"openbsd" -> pure OpenBSD
408-
other -> fail ("Invalid OS: " ++ show other)
404+
other -> Toml.failAt (Toml.valueAnn v) ("Invalid OS: " ++ show other)
409405

410406
instance Toml.ToValue OS where
411407
toValue x =
@@ -448,7 +444,7 @@ instance Toml.FromValue Architecture where
448444
"sparc64" -> pure SPARC64
449445
"vax" -> pure VAX
450446
"x86_64" -> pure X86_64
451-
other -> fail ("Invalid architecture: " ++ show other)
447+
other -> Toml.failAt (Toml.valueAnn v) ("Invalid architecture: " ++ show other)
452448

453449
instance Toml.ToValue Architecture where
454450
toValue x =
@@ -484,7 +480,7 @@ instance Toml.FromValue Version where
484480
fromValue v =
485481
do s <- Toml.fromValue v
486482
case eitherParsec s of
487-
Left err -> fail ("parse error in version range: " ++ err)
483+
Left err -> Toml.failAt (Toml.valueAnn v) ("parse error in version range: " ++ err)
488484
Right affected -> pure affected
489485

490486
instance Toml.ToValue Version where
@@ -494,7 +490,7 @@ instance Toml.FromValue VersionRange where
494490
fromValue v =
495491
do s <- Toml.fromValue v
496492
case eitherParsec s of
497-
Left err -> fail ("parse error in version range: " ++ err)
493+
Left err -> Toml.failAt (Toml.valueAnn v) ("parse error in version range: " ++ err)
498494
Right affected -> pure affected
499495

500496
instance Toml.ToValue VersionRange where
@@ -504,7 +500,7 @@ instance Toml.FromValue CVSS.CVSS where
504500
fromValue v =
505501
do s <- Toml.fromValue v
506502
case CVSS.parseCVSS s of
507-
Left err -> fail ("parse error in cvss: " ++ show err)
503+
Left err -> Toml.failAt (Toml.valueAnn v) ("parse error in cvss: " ++ show err)
508504
Right cvss -> pure cvss
509505

510506
instance Toml.ToValue CVSS.CVSS where
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
Left
22
( AdvisoryError
33
[ MatchMessage
4-
{ matchPath = []
4+
{ matchAnn = Just
5+
( Position
6+
{ posIndex = 0
7+
, posLine = 1
8+
, posColumn = 1
9+
}
10+
)
11+
, matchPath = []
512
, matchMessage = "missing key: affected"
613
}
7-
] "missing key: affected in top
14+
] "1:1: missing key: affected in <top-level>
815
"
916
)
1017

0 commit comments

Comments
 (0)