Skip to main content

yara_x/compiler/
errors.rs

1#![cfg_attr(any(), rustfmt::skip)]
2#![allow(clippy::duplicated_attributes)]
3
4use std::fmt::{Debug, Display, Formatter};
5use std::io;
6use serde::Serialize;
7
8use thiserror::Error;
9
10use yara_x_macros::ErrorEnum;
11use yara_x_macros::ErrorStruct;
12use yara_x_parser::ast;
13
14use crate::compiler::report::{Level, Patch, Report, ReportBuilder, CodeLoc, Label, Footer};
15
16/// Error returned by [`crate::Compiler::emit_wasm_file`].
17#[derive(Error, Debug)]
18#[error(transparent)]
19#[doc(hidden)]
20pub struct EmitWasmError(#[from] anyhow::Error);
21
22/// Error returned by [`crate::Compiler::switch_warning`] when the warning
23/// code is not valid.
24#[derive(Error, Debug, Eq, PartialEq)]
25#[error("`{0}` is not a valid warning code")]
26pub struct InvalidWarningCode(String);
27
28impl InvalidWarningCode {
29    pub(crate) fn new(code: String) -> Self {
30        Self(code)
31    }
32}
33
34/// Error returned while serializing/deserializing compiled rules.
35#[derive(Error, Debug)]
36pub enum SerializationError {
37    /// The data being deserialized was created with an incompatible version
38    /// of YARA-X.
39    #[error("incompatible version, expected {expected} got {actual}")]
40    InvalidVersion {
41        /// The expected version.
42        expected: u32,
43        /// The actual version found in the file.
44        actual: u32,
45    },
46
47    /// The data being deserialized doesn't contain YARA-X serialized rules.
48    #[error("not a YARA-X compiled rules file")]
49    InvalidFormat,
50
51    /// Error occurred while encoding YARA-X rules.
52    #[error("cannot encode YARA-X rules")]
53    EncodeError(#[from] bincode::error::EncodeError),
54
55    /// Error occurred while decoding YARA-X rules.
56    #[error("cannot decode YARA-X rules")]
57    DecodeError(#[from] bincode::error::DecodeError),
58
59    /// I/O error while trying to read or write serialized data.
60    #[error(transparent)]
61    IoError(#[from] io::Error),
62
63    /// Error occurred while deserializing WASM code.
64    #[error("invalid YARA-X compiled rules file")]
65    InvalidWASM(#[from] anyhow::Error),
66}
67
68/// Error returned when rule compilation fails.
69#[allow(missing_docs)]
70#[non_exhaustive]
71#[derive(ErrorEnum, Error, Clone, PartialEq, Eq)]
72#[derive(Serialize)]
73#[serde(tag = "type")]
74pub enum CompileError {
75    ArbitraryRegexpPrefix(Box<ArbitraryRegexpPrefix>),
76    AssignmentMismatch(Box<AssignmentMismatch>),
77    CircularIncludes(Box<CircularIncludes>),
78    ConflictingRuleIdentifier(Box<ConflictingRuleIdentifier>),
79    CustomError(Box<CustomError>),
80    DuplicateModifier(Box<DuplicateModifier>),
81    DuplicatePattern(Box<DuplicatePattern>),
82    DuplicateRule(Box<DuplicateRule>),
83    DuplicateTag(Box<DuplicateTag>),
84    EmptyPatternSet(Box<EmptyPatternSet>),
85    EntrypointUnsupported(Box<EntrypointUnsupported>),
86    IncludeError(Box<IncludeError>),
87    IncludeNotAllowed(Box<IncludeNotAllowed>),
88    IncludeNotFound(Box<IncludeNotFound>),
89    InvalidBase64Alphabet(Box<InvalidBase64Alphabet>),
90    InvalidEscapeSequence(Box<InvalidEscapeSequence>),
91    InvalidFloat(Box<InvalidFloat>),
92    InvalidInteger(Box<InvalidInteger>),
93    InvalidMetadata(Box<InvalidMetadata>),
94    InvalidModifier(Box<InvalidModifier>),
95    InvalidModifierCombination(Box<InvalidModifierCombination>),
96    InvalidPattern(Box<InvalidPattern>),
97    InvalidRange(Box<InvalidRange>),
98    InvalidRegexp(Box<InvalidRegexp>),
99    InvalidRegexpModifier(Box<InvalidRegexpModifier>),
100    InvalidRuleName(Box<InvalidRuleName>),
101    InvalidTag(Box<InvalidTag>),
102    InvalidUTF8(Box<InvalidUTF8>),
103    MethodNotAllowedInWith(Box<MethodNotAllowedInWith>),
104    MismatchingTypes(Box<MismatchingTypes>),
105    MissingMetadata(Box<MissingMetadata>),
106    MixedGreediness(Box<MixedGreediness>),
107    NumberOutOfRange(Box<NumberOutOfRange>),
108    PotentiallySlowLoop(Box<PotentiallySlowLoop>),
109    SlowPattern(Box<SlowPattern>),
110    SyntaxError(Box<SyntaxError>),
111    TooManyPatterns(Box<TooManyPatterns>),
112    UnexpectedEscapeSequence(Box<UnexpectedEscapeSequence>),
113    UnexpectedNegativeNumber(Box<UnexpectedNegativeNumber>),
114    UnknownField(Box<UnknownField>),
115    UnknownIdentifier(Box<UnknownIdentifier>),
116    UnknownModule(Box<UnknownModule>),
117    UnknownPattern(Box<UnknownPattern>),
118    UnknownTag(Box<UnknownTag>),
119    UnusedPattern(Box<UnusedPattern>),
120    WrongArguments(Box<WrongArguments>),
121    WrongType(Box<WrongType>),
122}
123
124impl CompileError {
125    pub(crate) fn from(
126        report_builder: &ReportBuilder,
127        err: ast::Error,
128    ) -> Self {
129        match err {
130            ast::Error::SyntaxError { message, span } => {
131                SyntaxError::build(report_builder, message, report_builder.span_to_code_loc(span))
132            }
133            ast::Error::InvalidInteger { message, span } => {
134                InvalidInteger::build(report_builder, message, report_builder.span_to_code_loc(span))
135            }
136            ast::Error::InvalidFloat { message, span } => {
137                InvalidFloat::build(report_builder, message, report_builder.span_to_code_loc(span))
138            }
139            ast::Error::InvalidRegexpModifier { message, span } => {
140                InvalidRegexpModifier::build(
141                    report_builder,
142                    message,
143                    report_builder.span_to_code_loc(span),
144                )
145            }
146            ast::Error::InvalidEscapeSequence { message, span } => {
147                InvalidEscapeSequence::build(
148                    report_builder,
149                    message,
150                    report_builder.span_to_code_loc(span),
151                )
152            }
153            ast::Error::UnexpectedEscapeSequence(span) => {
154                UnexpectedEscapeSequence::build(report_builder, report_builder.span_to_code_loc(span))
155            }
156            ast::Error::InvalidUTF8(span) => {
157                InvalidUTF8::build(report_builder, report_builder.span_to_code_loc(span))
158            }
159        }
160    }
161
162    /// Utility function that receives an array of strings and joins them
163    /// together separated by commas and with "or" before the last one.
164    /// For example, if input is `["s1", "s2", "s3"]` the result is:
165    ///
166    /// ```text
167    /// str1, str2 or str3
168    /// ```
169    ///
170    /// If `quotes` is true, the strings are enclosed in back tilts, like this:
171    ///
172    /// ```text
173    /// `str1`, `str2` or `str3`
174    /// ```
175    ///
176    pub(crate) fn join_with_or<S: ToString>(s: &[S], quotes: bool) -> String {
177        let mut strings = if quotes {
178            s.iter()
179                .map(|s| format!("`{}`", s.to_string()))
180                .collect::<Vec<String>>()
181        } else {
182            s.iter().map(|s| s.to_string()).collect::<Vec<String>>()
183        };
184
185        // Sort alphabetically.
186        strings.sort();
187
188        // Deduplicate repeated items.
189        strings.dedup();
190
191        match strings.len() {
192            1 => strings[0].to_owned(),
193            2 => format!("{} or {}", strings[0], strings[1]),
194            l => {
195                format!(
196                    "{}, or {}",
197                    strings[..l - 1].join(", "),
198                    strings[l - 1]
199                )
200            }
201        }
202    }
203}
204
205/// A syntax error was found in the rule.
206#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
207#[associated_enum(CompileError)]
208#[error(code = "E001", title = "syntax error")]
209#[label("{error}", error_loc)]
210pub struct SyntaxError {
211    report: Report,
212    error: String,
213    error_loc: CodeLoc,
214}
215
216/// Some expression has an unexpected type.
217#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
218#[associated_enum(CompileError)]
219#[error(code = "E002", title = "wrong type")]
220#[label(
221    "expression should be {expected_types}, but it is {actual_type}",
222    error_loc
223)]
224#[footer(help, Level::HELP)]
225pub struct WrongType {
226    report: Report,
227    expected_types: String,
228    actual_type: String,
229    error_loc: CodeLoc,
230    help: Option<String>,
231}
232
233/// Operands have mismatching types.
234#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
235#[associated_enum(CompileError)]
236#[error(code = "E003", title = "mismatching types")]
237#[label("this expression is `{type1}`", type1_loc)]
238#[label("this expression is `{type2}`", type2_loc)]
239pub struct MismatchingTypes {
240    report: Report,
241    type1: String,
242    type2: String,
243    type1_loc: CodeLoc,
244    type2_loc: CodeLoc,
245}
246
247/// Wrong arguments when calling a function.
248#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
249#[associated_enum(CompileError)]
250#[error(code = "E004", title = "wrong arguments")]
251#[label("wrong arguments in this call", error_loc)]
252#[footer(note)]
253pub struct WrongArguments {
254    report: Report,
255    error_loc: CodeLoc,
256    note: Option<String>,
257}
258
259/// Mismatch between number of variables and number of values in a loop
260/// expression.
261#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
262#[associated_enum(CompileError)]
263#[error(code = "E005", title = "assignment mismatch")]
264#[label("this expects {expected_values} value(s)", error_loc)]
265#[label("this produces {actual_values} value(s)", iterable_loc)]
266pub struct AssignmentMismatch {
267    report: Report,
268    expected_values: u8,
269    actual_values: u8,
270    iterable_loc: CodeLoc,
271    error_loc: CodeLoc,
272}
273
274/// Negative number used where positive number was expected.
275#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
276#[associated_enum(CompileError)]
277#[error(code = "E006", title = "unexpected negative number")]
278#[label("this number can not be negative", error_loc)]
279pub struct UnexpectedNegativeNumber {
280    report: Report,
281    error_loc: CodeLoc,
282}
283
284/// A number is out of the allowed range.
285#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
286#[associated_enum(CompileError)]
287#[error(code = "E007", title = "number out of range")]
288#[label("this number is out of the allowed range [{min}-{max}]", error_loc)]
289pub struct NumberOutOfRange {
290    report: Report,
291    min: i64,
292    max: i64,
293    error_loc: CodeLoc,
294}
295
296/// Unknown field or method name.
297#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
298#[associated_enum(CompileError)]
299#[error(code = "E008", title = "unknown field or method `{identifier}`")]
300#[label("this field or method doesn't exist", error_loc)]
301pub struct UnknownField {
302    report: Report,
303    identifier: String,
304    error_loc: CodeLoc,
305}
306
307/// Unknown identifier.
308#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
309#[associated_enum(CompileError)]
310#[error(code = "E009", title = "unknown identifier `{identifier}`")]
311#[label("this identifier has not been declared", identifier_loc)]
312#[footer(note)]
313pub struct UnknownIdentifier {
314    report: Report,
315    identifier: String,
316    identifier_loc: CodeLoc,
317    note: Option<String>,
318}
319
320impl UnknownIdentifier {
321    /// Name of the unknown identifier.
322    #[inline]
323    pub fn identifier(&self) -> &str {
324        self.identifier.as_str()
325    }
326    /// Location of the unknown identifier.
327    pub(crate) fn identifier_location(&self) -> &CodeLoc {
328        &self.identifier_loc
329    }
330}
331
332/// Unknown module.
333#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
334#[associated_enum(CompileError)]
335#[error(code = "E010", title = "unknown module `{identifier}`")]
336#[label("module `{identifier}` not found", error_loc)]
337pub struct UnknownModule {
338    report: Report,
339    identifier: String,
340    error_loc: CodeLoc,
341}
342
343/// Invalid range.
344#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
345#[associated_enum(CompileError)]
346#[error(code = "E011", title = "invalid range")]
347#[label("{error}", error_loc)]
348pub struct InvalidRange {
349    report: Report,
350    error: String,
351    error_loc: CodeLoc,
352}
353
354/// Two rules have the same name.
355#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
356#[associated_enum(CompileError)]
357#[error(code = "E012", title = "duplicate rule `{new_rule}`")]
358#[label(
359    "duplicate declaration of `{new_rule}`",
360    duplicate_rule_loc,
361    Level::ERROR
362)]
363#[label(
364    "`{new_rule}` declared here for the first time",
365    existing_rule_loc,
366    Level::NOTE
367)]
368pub struct DuplicateRule {
369    report: Report,
370    new_rule: String,
371    duplicate_rule_loc: CodeLoc,
372    existing_rule_loc: CodeLoc,
373}
374
375
376/// A rule has the same name as a module or global variable.
377#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
378#[associated_enum(CompileError)]
379#[error(
380    code = "E013",
381    title = "rule `{identifier}` conflicts with an existing identifier"
382)]
383#[label("identifier already in use by a module or global variable", error_loc)]
384pub struct ConflictingRuleIdentifier {
385    report: Report,
386    identifier: String,
387    error_loc: CodeLoc,
388}
389
390/// A regular expression is invalid.
391#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
392#[associated_enum(CompileError)]
393#[error(code = "E014", title = "invalid regular expression")]
394#[label("{error}", error_loc)]
395#[footer(note)]
396pub struct InvalidRegexp {
397    report: Report,
398    error: String,
399    error_loc: CodeLoc,
400    note: Option<String>,
401}
402
403/// A regular expression contains a mixture of greedy and non-greedy quantifiers.
404#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
405#[associated_enum(CompileError)]
406#[error(
407    code = "E015",
408    title = "mixing greedy and non-greedy quantifiers in regular expression"
409)]
410#[label("this is {quantifier1_greediness}", quantifier1_loc)]
411#[label("this is {quantifier2_greediness}", quantifier2_loc)]
412pub struct MixedGreediness {
413    report: Report,
414    quantifier1_greediness: String,
415    quantifier2_greediness: String,
416    quantifier1_loc: CodeLoc,
417    quantifier2_loc: CodeLoc,
418}
419
420/// A set of patterns doesn't contain any patterns.
421#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
422#[associated_enum(CompileError)]
423#[error(code = "E016", title = "no matching patterns")]
424#[label("there's no pattern in this set", error_loc)]
425#[footer(note)]
426pub struct EmptyPatternSet {
427    report: Report,
428    error_loc: CodeLoc,
429    note: Option<String>,
430}
431
432/// The `entrypoint` keyword is not supported.
433#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
434#[associated_enum(CompileError)]
435#[error(code = "E017", title = "`entrypoint` is unsupported")]
436#[label("the `entrypoint` keyword is not supported anymore", error_loc)]
437pub struct EntrypointUnsupported {
438    report: Report,
439    error_loc: CodeLoc,
440}
441
442/// Some pattern may be potentially slow.
443#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
444#[associated_enum(CompileError)]
445#[error(code = "E018", title = "slow pattern")]
446#[label("this pattern may slow down the scan", error_loc)]
447#[footer(note)]
448pub struct SlowPattern {
449    report: Report,
450    error_loc: CodeLoc,
451    note: Option<String>,
452}
453
454/// A pattern has modifiers that can't be used together.
455#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
456#[associated_enum(CompileError)]
457#[error(
458    code = "E019",
459    title = "invalid modifier combination: `{modifier1}` `{modifier2}`"
460)]
461#[label("`{modifier1}` modifier used here", modifier1_loc)]
462#[label("`{modifier2}` modifier used here", modifier2_loc)]
463#[footer(note)]
464pub struct InvalidModifierCombination {
465    report: Report,
466    modifier1: String,
467    modifier2: String,
468    modifier1_loc: CodeLoc,
469    modifier2_loc: CodeLoc,
470    note: Option<String>,
471}
472
473/// A pattern has duplicate modifiers.
474#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
475#[associated_enum(CompileError)]
476#[error(code = "E020", title = "duplicate pattern modifier")]
477#[label("duplicate modifier", error_loc)]
478pub struct DuplicateModifier {
479    report: Report,
480    error_loc: CodeLoc,
481}
482
483/// A rule has duplicate tags.
484#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
485#[associated_enum(CompileError)]
486#[error(code = "E021", title = "duplicate tag `{tag}`")]
487#[label("duplicate tag", error_loc)]
488pub struct DuplicateTag {
489    report: Report,
490    tag: String,
491    error_loc: CodeLoc,
492}
493
494/// A rule defines a pattern that is not used in the condition.
495#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
496#[associated_enum(CompileError)]
497#[error(code = "E022", title = "unused pattern `{pattern_ident}`")]
498#[label("this pattern was not used in the condition", error_loc)]
499pub struct UnusedPattern {
500    report: Report,
501    pattern_ident: String,
502    error_loc: CodeLoc,
503}
504
505/// A rule has two patterns with the same identifier.
506#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
507#[associated_enum(CompileError)]
508#[error(code = "E023", title = "duplicate pattern `{pattern_ident}`")]
509#[label("duplicate declaration of `{pattern_ident}`", error_loc)]
510#[label(
511    "`{pattern_ident}` declared here for the first time",
512    note_loc,
513    Level::NOTE
514)]
515pub struct DuplicatePattern {
516    report: Report,
517    pattern_ident: String,
518    error_loc: CodeLoc,
519    note_loc: CodeLoc,
520}
521
522/// A rule has an invalid pattern.
523#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
524#[associated_enum(CompileError)]
525#[error(code = "E024", title = "invalid pattern `{pattern_ident}`")]
526#[label("{error}", error_loc)]
527#[footer(note)]
528pub struct InvalidPattern {
529    report: Report,
530    pattern_ident: String,
531    error: String,
532    error_loc: CodeLoc,
533    note: Option<String>,
534}
535
536/// Some rule condition uses a pattern that was not defined.
537#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
538#[associated_enum(CompileError)]
539#[error(code = "E025", title = "unknown pattern `{pattern_ident}`")]
540#[label("this pattern is not declared in the `strings` section", error_loc)]
541pub struct UnknownPattern {
542    report: Report,
543    pattern_ident: String,
544    error_loc: CodeLoc,
545}
546
547/// Wrong alphabet for the `base64` or `base64wide` modifiers.
548#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
549#[associated_enum(CompileError)]
550#[error(code = "E026", title = "invalid base64 alphabet")]
551#[label("{error}", error_loc)]
552pub struct InvalidBase64Alphabet {
553    report: Report,
554    error: String,
555    error_loc: CodeLoc,
556}
557
558/// Invalid integer.
559#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
560#[associated_enum(CompileError)]
561#[error(code = "E027", title = "invalid integer")]
562#[label("{error}", error_loc)]
563pub struct InvalidInteger {
564    report: Report,
565    error: String,
566    error_loc: CodeLoc,
567}
568
569/// Invalid float.
570#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
571#[associated_enum(CompileError)]
572#[error(code = "E028", title = "invalid float")]
573#[label("{error}", error_loc)]
574pub struct InvalidFloat {
575    report: Report,
576    error: String,
577    error_loc: CodeLoc,
578}
579
580/// A text pattern contains an invalid escape sequence.
581#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
582#[associated_enum(CompileError)]
583#[error(code = "E029", title = "invalid escape sequence")]
584#[label("{error}", error_loc)]
585pub struct InvalidEscapeSequence {
586    report: Report,
587    error: String,
588    error_loc: CodeLoc,
589}
590
591/// Invalid modifier for a regular expression.
592#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
593#[associated_enum(CompileError)]
594#[error(code = "E030", title = "invalid regexp modifier `{modifier}`")]
595#[label("invalid modifier", error_loc)]
596pub struct InvalidRegexpModifier {
597    report: Report,
598    modifier: String,
599    error_loc: CodeLoc,
600}
601
602/// A string literal contains escaped sequences and it shouldn't.
603#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
604#[associated_enum(CompileError)]
605#[error(code = "E031", title = "unexpected escape sequence")]
606#[label("escape sequences are not allowed in this string", error_loc)]
607pub struct UnexpectedEscapeSequence {
608    report: Report,
609    error_loc: CodeLoc,
610}
611
612
613/// Source code contains invalid UTF-8 characters.
614#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
615#[associated_enum(CompileError)]
616#[error(code = "E032", title = "invalid UTF-8")]
617#[label("invalid UTF-8 character", error_loc)]
618pub struct InvalidUTF8 {
619    report: Report,
620    error_loc: CodeLoc,
621}
622
623/// Some pattern has an invalid modifier.
624#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
625#[associated_enum(CompileError)]
626#[error(code = "E033", title = "invalid pattern modifier")]
627#[label("{error}", error_loc)]
628pub struct InvalidModifier {
629    report: Report,
630    error: String,
631    error_loc: CodeLoc,
632}
633
634/// A rule contains a loop that could be very slow.
635///
636/// This error indicates that a rule contains a `for` loop that may be very
637/// slow because it iterates over a range with an upper bound that depends on
638/// `filesize`. For very large files this may mean hundreds of millions of
639/// iterations.
640///
641/// # Example
642///
643/// ```text
644/// error[E034]: potentially slow loop
645///  --> test.yar:1:34
646///   |
647/// 1 | rule t { condition: for any i in (0..filesize-1) : ( int32(i) == 0xcafebabe ) }
648///   |                                  --------------- this range can be very large
649///   |
650/// ```
651#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
652#[associated_enum(CompileError)]
653#[error(code = "E034", title = "potentially slow loop")]
654#[label(
655"this range can be very large",
656    loc
657)]
658pub struct PotentiallySlowLoop {
659    report: Report,
660    loc: CodeLoc,
661}
662
663/// A rule has too many patterns.
664#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
665#[associated_enum(CompileError)]
666#[error(code = "E035", title = "too many patterns in a rule")]
667#[label("this rule has more than {max_num_patterns} patterns", error_loc)]
668pub struct TooManyPatterns {
669    report: Report,
670    max_num_patterns: usize,
671    error_loc: CodeLoc,
672}
673
674/// A rule has too many patterns.
675#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
676#[associated_enum(CompileError)]
677#[error(code = "E036", title = "method not allowed in `with` statement")]
678#[label("this method is not allowed here", error_loc)]
679pub struct MethodNotAllowedInWith {
680    report: Report,
681    error_loc: CodeLoc,
682}
683
684/// Some metadata entry is invalid. This is only used if the compiler is
685/// configured to check for valid metadata (see: [`crate::linters::Metadata`]).
686///
687/// ## Example
688///
689/// ```text
690/// error[E037]: metadata `author` is not valid
691/// --> test.yar:4:5
692///   |
693/// 4 |     author = 1234
694///   |              ---- `author` must be a string
695///   |
696/// ```
697#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
698#[associated_enum(CompileError)]
699#[error(code = "E037", title = "metadata `{name}` is not valid")]
700#[label(
701    "{label}",
702    label_loc
703)]
704pub struct InvalidMetadata {
705    report: Report,
706    name: String,
707    label_loc: CodeLoc,
708    label: String,
709}
710
711/// Missing metadata. This is only used if the compiler is configured to check
712/// for required metadata (see:  [`crate::linters::Metadata`]).
713///
714/// ## Example
715///
716/// ```text
717/// error[E038]: required metadata is missing
718///  --> test.yar:12:6
719///    |
720/// 12 | rule pants {
721///    |      ----- required metadata "date" not found
722///    |
723/// ```
724#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
725#[associated_enum(CompileError)]
726#[error(
727    code = "E038",
728    title = "required metadata is missing"
729)]
730#[label(
731    "required metadata `{name}` not found",
732    rule_loc
733)]
734#[footer(note)]
735pub struct MissingMetadata {
736    report: Report,
737    rule_loc: CodeLoc,
738    name: String,
739    note: Option<String>,
740}
741
742/// Rule name does not match regex. This is only used if the compiler is
743/// configured to check for it (see: [`crate::linters::RuleName`]).
744///
745/// ## Example
746///
747/// ```text
748/// error[E039]: rule name does not match regex `APT_.*`
749///  --> test.yar:13:6
750///    |
751/// 13 | rule pants {
752///    |      ----- this rule name does not match regex `APT_.*`
753///    |
754/// ```
755#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
756#[associated_enum(CompileError)]
757#[error(
758    code = "E039",
759    title = "rule name does not match regex `{regex}`"
760)]
761#[label(
762    "this rule name does not match regex `{regex}`",
763    rule_loc
764)]
765pub struct InvalidRuleName {
766    report: Report,
767    rule_loc: CodeLoc,
768    regex: String,
769}
770
771/// Unknown tag. This is only used if the compiler is configured to check
772/// for required tags (see:  [`crate::linters::Tags`]).
773///
774/// ## Example
775///
776/// ```text
777/// error[E040]: tag not in allowed list
778///  --> rules/test.yara:1:10
779///   |
780/// 1 | rule a : foo {
781///   |          ^^^ tag `foo` not in allowed list
782///   |
783///   = note: Allowed tags: test, bar
784/// ```
785#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
786#[associated_enum(CompileError)]
787#[error(
788    code = "E040",
789    title = "tag not in allowed list"
790)]
791#[label(
792    "tag `{name}` not in allowed list",
793    tag_loc
794)]
795#[footer(note)]
796pub struct UnknownTag {
797    report: Report,
798    tag_loc: CodeLoc,
799    name: String,
800    note: Option<String>,
801}
802
803/// Tag does not match regex. This is only used if the compiler is configured to
804/// check for it (see: [`crate::linters::Tags`]).
805///
806/// ## Example
807///
808/// ```text
809/// error[E041]: tag does not match regex `bar`
810///  --> rules/test.yara:1:10
811///   |
812/// 1 | rule a : foo {
813///   |          ^^^ tag `foo` does not match regex `bar`
814///   |
815/// ```
816#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
817#[associated_enum(CompileError)]
818#[error(
819    code = "E041",
820    title = "tag does not match regex `{regex}`"
821)]
822#[label(
823    "tag `{name}` does not match regex `{regex}`",
824    tag_loc
825)]
826pub struct InvalidTag {
827    report: Report,
828    tag_loc: CodeLoc,
829    name: String,
830    regex: String,
831}
832
833/// An error occurred while including a file.
834///
835/// ## Example
836///
837/// ```text
838/// error[E042]: error including file
839///  --> line:1:1
840///   |
841/// 1 | include "unknown"
842///   | ^^^^^^^^^^^^^^^^^ failed with error: Permission denied (os error 13)
843///   |
844/// ```
845#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
846#[associated_enum(CompileError)]
847#[error(
848    code = "E042",
849    title = "error including file"
850)]
851#[label(
852    "failed with error: {error}",
853    include_loc
854)]
855pub struct IncludeError {
856    report: Report,
857    include_loc: CodeLoc,
858    error: String,
859}
860
861/// An included file was not found.
862///
863/// ## Example
864///
865/// ```text
866/// error[E042]: include file not found
867///  --> line:1:1
868///   |
869/// 1 | include "unknown"
870///   | ^^^^^^^^^^^^^^^^^ `unknown` not found in any of the include directories
871///   |
872/// ```
873#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
874#[associated_enum(CompileError)]
875#[error(
876    code = "E043",
877    title = "include file not found"
878)]
879#[label(
880    "`{file_path}` not found in any of the include directories",
881    include_loc
882)]
883pub struct IncludeNotFound {
884    report: Report,
885    file_path: String,
886    include_loc: CodeLoc,
887}
888
889/// An include statement was used, but includes are disabled
890///
891/// # Example
892///
893/// ```text
894/// error[E044]: include statements not allowed
895///  --> line:1:1
896///
897/// 1 | include "some_file"
898///   | ^^^^^^^^^^^^^^^^^^^ includes are disabled for this compilation
899///   |
900/// ```
901#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
902#[associated_enum(CompileError)]
903#[error(
904    code = "E044",
905    title = "include statements not allowed"
906)]
907#[label(
908    "includes are disabled for this compilation",
909    include_loc
910)]
911pub struct IncludeNotAllowed {
912    report: Report,
913    include_loc: CodeLoc,
914}
915
916/// Indicates that a regular expression has a prefix that can be arbitrarily
917/// long and matches any sequence of bytes.
918///
919/// # Example
920///
921/// ```text
922/// error[E045]: arbitrary regular expression prefix  
923///  --> line:3:11  
924///   |  
925/// 3 |     $a = /.*foo/s  
926///   |           ^^ this prefix can be arbitrarily long and matches all bytes  
927///   |
928/// ```  
929///
930/// Regular expressions with such prefixes are problematic because YARA will
931/// report a match at every file offset from the start of the file up to where
932/// the rest of the pattern matches. In most cases, this prefix can be removed
933/// without affecting the rule's semantics.
934#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
935#[associated_enum(CompileError)]
936#[error(code = "E045", title = "arbitrary regular expression prefix")]
937#[label("this prefix can be arbitrarily long and matches all bytes", error_loc)]
938pub struct ArbitraryRegexpPrefix {
939    report: Report,
940    error_loc: CodeLoc,
941}
942
943/// Include statements have circular dependencies.
944#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
945#[associated_enum(CompileError)]
946#[error(code = "E046", title = "circular include dependencies")]
947#[label("include statement has circular dependencies", error_loc)]
948#[footer(note)]
949pub struct CircularIncludes {
950    report: Report,
951    error_loc: CodeLoc,
952    note: Option<String>,
953}
954
955/// A custom error has occurred.
956#[derive(ErrorStruct, Clone, Debug, PartialEq, Eq)]
957#[associated_enum(CompileError)]
958#[error(code = "E100", title = "{title}")]
959#[label("{error}", error_loc)]
960pub struct CustomError {
961    report: Report,
962    title: String,
963    error: String,
964    error_loc: CodeLoc,
965}