module Hadolint.Rule.DL3066 (rule) where import qualified Data.Char as Char import qualified Data.Set as Set import qualified Data.Text as Text import Hadolint.Rule import Language.Docker.Syntax data Acc = Acc { Acc -> Set Text args :: Set.Set Text.Text } | Empty deriving (Int -> Acc -> ShowS [Acc] -> ShowS Acc -> String (Int -> Acc -> ShowS) -> (Acc -> String) -> ([Acc] -> ShowS) -> Show Acc forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a $cshowsPrec :: Int -> Acc -> ShowS showsPrec :: Int -> Acc -> ShowS $cshow :: Acc -> String show :: Acc -> String $cshowList :: [Acc] -> ShowS showList :: [Acc] -> ShowS Show) rule :: Rule args rule :: forall args. Rule args rule = (Int -> State Acc -> Instruction args -> State Acc) -> State Acc -> Rule args forall a args. (Int -> State a -> Instruction args -> State a) -> State a -> Rule args customRule Int -> State Acc -> Instruction args -> State Acc forall {args}. Int -> State Acc -> Instruction args -> State Acc check (Acc -> State Acc forall a. a -> State a emptyState Acc Empty) where code :: RuleCode code = RuleCode "DL3066" severity :: DLSeverity severity = DLSeverity DLInfoC message :: Text message = Text "Non-numeric user-id may not be resolvable by host system" check :: Int -> State Acc -> Instruction args -> State Acc check Int line State Acc st (User Text u) | (Char -> Bool) -> Text -> Bool Text.all Char -> Bool Char.isDigit (Text -> Bool) -> Text -> Bool forall a b. (a -> b) -> a -> b $ Text -> Text getUid Text u = State Acc st | Acc -> Text -> Bool uidIsDefinedArg (State Acc -> Acc forall a. State a -> a state State Acc st) Text u = State Acc st | Bool otherwise = State Acc st State Acc -> (State Acc -> State Acc) -> State Acc forall a b. a -> (a -> b) -> b |> CheckFailure -> State Acc -> State Acc forall a. CheckFailure -> State a -> State a addFail CheckFailure {Int Text RuleCode DLSeverity code :: RuleCode severity :: DLSeverity message :: Text line :: Int line :: Int message :: Text severity :: DLSeverity code :: RuleCode ..} check Int _ State Acc st (Arg Text arg Maybe Text _) = State Acc st State Acc -> (State Acc -> State Acc) -> State Acc forall a b. a -> (a -> b) -> b |> (Acc -> Acc) -> State Acc -> State Acc forall a. (a -> a) -> State a -> State a modify (Text -> Acc -> Acc registerArg Text arg) check Int _ State Acc st Instruction args _ = State Acc st {-# INLINEABLE rule #-} getUid :: Text.Text -> Text.Text getUid :: Text -> Text getUid Text t | Text ":" Text -> Text -> Bool `Text.isInfixOf` Text t = [Text] -> Text forall {a}. IsString a => [a] -> a u ( HasCallStack => Text -> Text -> [Text] Text -> Text -> [Text] Text.splitOn Text ":" Text t ) | Bool otherwise = Text t where u :: [a] -> a u [] = a "" u (a h:[a] _) = a h uidIsDefinedArg :: Acc -> Text.Text -> Bool uidIsDefinedArg :: Acc -> Text -> Bool uidIsDefinedArg Acc Empty Text _ = Bool False uidIsDefinedArg (Acc Set Text args) Text u = (Text -> Bool) -> Set Text -> Bool forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool any (Text -> Text -> Bool `varInUid` Text u) Set Text args where varInUid :: Text.Text -> Text.Text -> Bool varInUid :: Text -> Text -> Bool varInUid Text var Text uid = ( String -> Text Text.pack String "${" Text -> Text -> Text forall a. Semigroup a => a -> a -> a <> Text var Text -> Text -> Text forall a. Semigroup a => a -> a -> a <> String -> Text Text.pack String "}" ) Text -> Text -> Bool `Text.isInfixOf` Text uid Bool -> Bool -> Bool || ( String -> Text Text.pack String "$" Text -> Text -> Text forall a. Semigroup a => a -> a -> a <> Text var ) Text -> Text -> Bool `Text.isInfixOf` Text uid registerArg :: Text.Text -> Acc -> Acc registerArg :: Text -> Acc -> Acc registerArg Text arg Acc Empty = Acc { args :: Set Text args = Text -> Set Text forall a. a -> Set a Set.singleton Text arg } registerArg Text arg (Acc Set Text args) = Acc { args :: Set Text args = Text -> Set Text -> Set Text forall a. Ord a => a -> Set a -> Set a Set.insert Text arg Set Text args }