184 Commits
Author SHA1 Message Date
Cole Munz dcc4b9166c reject hex jump and repeat lengths that overflow an int (#2237)
The hex string and regexp lexers parse jump lengths and repeat intervals
with atoi, which is undefined for numbers that don't fit in an int. glibc
hands back the low 32 bits, so a value that wraps to a small positive
number passes every bounds check and silently changes the pattern:

  rule r1 { strings: $a = /a{4294967296}/ condition: $a }
  rule r2 { strings: $b = { 61 [0-4294967297] 62 } condition: $b }

Before this change r1 compiled as a{0} and matched at every offset, and
r2 compiled as { 61 [0-1] 62 }. MSVC saturates atoi at INT_MAX instead,
so the same rule behaves differently there, which is what #1791 reports.

Parse with strtoll instead. Numbers too large for a long long are clamped
to LLONG_MAX, which still fails the range check, so "repeat interval too
large" now fires for everything above RE_MAX_RANGE on any platform. Hex
jumps get an explicit INT_MAX check because RE_NODE stores start and end
as ints, and the grammar already casts to int.

The hi_bound < 0 and lo_bound < 0 checks are gone. They were there to
catch atoi wrapping negative and are unreachable now that the only thing
the pattern matches is digits.

Fixes #1791.
2026-08-21 10:34:22 +02:00
Eritque arcus 510eca24fd fix: Fix INT64_MIN UB in constant folding (*, \, unary -) (#2211)
Constant folding in `grammar.y` hits UB at the `INT64_MIN` boundary, reachable from rule text:

- `*`: `llabs(INT64_MIN)` is UB and returns a negative value, so the overflow guard is bypassed and folds to a garbage constant instead of `ERROR_INTEGER_OVERFLOW`. Now compares magnitudes in unsigned space.
- `\`: `INT64_MIN / -1` is overflow UB and raises SIGFPE on x86. Now rejected with `ERROR_INTEGER_OVERFLOW`.
- unary `-`: `-INT64_MIN` is negation UB. Now negated in unsigned space (wraps to `INT64_MIN`, unchanged behavior).

Reproduce  `condition` expr (each reported an UBSan error):
    `~9223372036854775807 * 9223372036854775807`
    `~9223372036854775807 \ -1`
    `-(~9223372036854775807)`

Example Logs:
```
libyara/grammar.y:2813:30: runtime error: negation of -9223372036854775808 cannot be represented in type 'int64_t' (aka 'long'); cast to an unsigned type to negate this value to itself
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior libyara/grammar.y:2813:30 
```

Note: The VM ops in `exec.c` and the `%` rule likely share this UB.

Disclose: assisted with AI
2026-06-30 20:19:29 +02:00
secDre4mer d3eae3258a fix: correct indentation issues (#2133) 2025-01-13 10:12:02 +01:00
Victor M. Alvarez 8616165472 Fix segfault with regular expressions that matched the zero-length string.
In regular expressions, repetition operators`{0,0}` and `{,0}` are valid, but they always match the zero-length string. For instance, `a{0,0}` and `[a-z]{0,0}` both match the zero-length string.

When the whole regular expression consists in one of these repetitions it caused a segfault during the evaluation of the regular expression because the `forward_code_ref` field for the root atom in the atom's tree was null.

Closes #2084.
2024-06-19 13:47:58 +02:00
Victor M. Alvarez f1640e24ec Allow spaces in regexp repetition operators.
For instance, `x{n, m}`, `x{n ,m}` and `x{n  ,  m}` are all equivalent to `x{n,m}`. This is done for compatibility with YARA-X, but I've seen real-life regular expressions in that contain such spaces, for example:

```
/C:\\Users\\qqq\\.{30, 50}\.pdb/
```
2024-05-22 15:51:43 +02:00
Victor M. Alvarez 924fa58ce9 Fix issue #2065
The issue was causing false negative with certain patterns.
2024-04-08 10:28:31 +02:00
Victor M. Alvarez ff959e562a Add more test cases. 2024-03-20 15:49:14 +01:00
Victor M. Alvarez c80cd9debf Fix issue with matches operator not matching empty strings
The `matches` operator was returning false if the left operand was an empty strings. So, `"" matches <some regexp>` was returning false regardless of the regexp used. However, some regexp *do* match the empty strings, like for example `/foo|/`.
2024-03-20 15:47:37 +01:00
Victor M. Alvarez f3b3027154 Allow quantifiers {0} and {0,0}.
Regexps with quantifiers `{0}` and `{0,0}` were considered syntactically invalid. These quantifiers are not  actually useful, but they are now allowed for compatibility with other regexp engines.

Closes #2037.
2024-02-12 11:47:17 +01:00
Victor M. Alvarez 79794c4053 Fix issue with regexps not matching empty strings.
Some regexps like `/(abc|)/` where not matching the empty string even if they should. Matching an empty string is not very useful, as such regexp will match on every offset of every file, but this is fixed for correctness.

Also fixes another issue with the `\b` metacharacter in regexps, which was exposed after fixing the main issue.
2024-01-15 16:51:11 +01:00
Victor M. Alvarez a3d938b429 Minor style fixes. 2024-01-15 13:07:34 +01:00
Victor M. Alvarez cddec11934 Fix bug that broke global rules.
PR #1927 didn't take into account that as a side-effect of skipping the evaluation of global rules, the corresponding namespace was not flagged as unsatisfied (i.e: a global rule that evaluates to false prevents all other rules in the namespace from evaluating to true). The issue was not caught by any test case because the test case for global rules were using rules that didn't required any strings to match, and therefore were unaffected by the changes introduced in #1927.

This change makes sure that any global rule that is skipped is considered false, and therefore its namespace is flagged as unsatisfied.

Closes #2022.
2023-12-10 20:27:05 +01:00
Tomáš Ďuriš d7e67ff54b Added warning on unknown escape sequences (#1880)
* Added warning on unknown escape sequences

* fixed memory leaks and different output when using regex as operand with strict-escape parameter

* Remove some unwanted characters from strict escaping, add testcases
2023-08-23 15:26:43 +02:00
Wesley Shields ba07831d5b Allow unreferenced strings if they start with '_' (#1941)
As briefly discussed in #1937, this change will make it so that any string
identifier that starts with '_' can be unreferenced. Any anonymous strings
must still be referenced.

While testing this out I realized that an unreferenced string still had the
STRING_FLAG_FIXED_OFFSET set, which meant any unreferenced string would have a
fixed_offset of YR_UNDEFINED. To deal with this when we are reducing the rule
we unset STRING_FLAG_FIXED_OFFSET if the string is unreferenced.
2023-08-23 12:03:59 +02:00
Victor M. Alvarez 95dafbdb3c Fix issue #1933 2023-07-21 10:15:11 +02:00
Victor M. Alvarez bcc631299c Fix bug in yr_re_fast_exec causing assertion in _yr_scan_match_callback
When an arbitrary file is scanned with the rule below it triggers the assertion at https://github.com/VirusTotal/yara/blob/v4.3.1/libyara/scan.c#L670
```
rule test {
     strings:
       $a = { 31[-][8-][-]30 }
     condition: 
       $a 
}
```
2023-06-12 11:24:48 +02:00
Victor M. Alvarez f3d838d2ac Some additional test cases for the defined operator. 2023-02-07 16:32:24 +01:00
Wesley Shields 97cab27e3e Ban floating point values in for expressions. (#1844)
This is now illegal syntax:

for 3.14159 in (1): (1)

It doesn't make sense to allow floating point in the primary expression used in
for expressions. This is an extension of the work done in a5903e1d which banned
negative integers, strings and regexp from being used here too.
2022-12-29 11:59:43 +01:00
Vincent Thiberville 55581a88ff Revert "fix: reject non ascii bytes in regex (#1770)"
This reverts commit a87c77c735.
2022-12-19 13:40:13 +01:00
Victor M. Alvarez 65feab41d4 Fix issue #1819 2022-12-05 10:15:32 +01:00
Victor M. Alvarez c2557fc365 Fix SIGFPE when dividing INT64_MIN by -1.
Submitted by @vthib
2022-12-05 10:04:00 +01:00
Wesley Shields c67837f6a4 Add warnings for edge cases. (#1806)
* Add warnings for edge cases.

When using "all of them at 0" it is now a warning if you have more than 1 string
defined in "them".

"N of them" (where N > 1) is also a warning.

* Use IS_UNDEFINED when checking integer expression.
2022-10-20 10:01:30 +02:00
Wesley Shields c0a2b5a6c3 Add OP_OF_FOUND_AT. (#1790)
* Add OP_OF_FOUND_AT.

Add support for "any of them at 0" constructs to the language. This allows users
to avoid using long or chains like "$a at 0 or $b at 0" and also is a nicer way
to write "for any of them: ($ at 0)".

* Add short blurb to docs about new string set at offset.
2022-09-26 09:25:34 +02:00
Wesley Shields d6fc080492 Implement text string sets. (#1787)
* Implement text string sets.

Add support for text string sets into the grammar. They look like this:

for any s in ("a", "b"): (pe.imphash() == s)

This requires changing integer_set and integer_enumeration to just be set and
enumeration, and adding a new type (YR_ENUMERATION) that tracks the type of
enumeration (integer or otherwise) and the number of items in the enumeration.

The enumeration now checks that each type of the item in the enumeration is
consistent and will cause a compiler error if they are not. For example, this is
an error:

for any s in ("a", 0): (s)

Also, fix the build when using --with-debug-verbose option as it was missing the
assert.h include.

* Add docs and adjust constants layout.
2022-09-23 12:05:46 +02:00
Hilko Bengen 666d5a4fd6 Tidy #include's (#1769)
- Add assert.h for assert()
- Add yara/strutils.h for PRIxXX macros, memmem
- Remove unneeded utils.h -> strutils.h dependency
- Don't include sys/wait.h on Windows (native)
2022-08-26 12:04:32 +02:00
Vincent Thiberville a87c77c735 fix: reject non ascii bytes in regex (#1770) 2022-08-22 11:05:52 +02:00
Vincent Thiberville 7acfe90609 propagate undefined value in OP_FOUND_AT (#1759)
Before, this fix, this rule was true:

```
import "tests"

rule a {
    strings:
        $foo = "foo"
    condition:
        not defined ($foo in (0..tests.integer_array[40])) and
        defined ($foo at tests.integer_array[40])
}
```

where `tests.integer_array[40]` is just a way to get an undefined value.

This is surprising, OP_FOUND_AT is the only operation of this kind that
is not propagating the undefined value. This commit fixes this behavior.
2022-08-09 10:22:33 +02:00
Victor M. Alvarez b77e4f45b4 Prevent undefined values in offset ranges from corrupting the VM's stack. 2022-08-08 12:32:07 +02:00
Victor M. Alvarez fc982b002c Fix issue #1757. 2022-08-04 13:01:22 +02:00
Victor M. Alvarez 811c20f2bf Fix issue #1729. 2022-06-15 13:51:52 +02:00
Victor M. Alvarez 3484fcb60b Fix multiple memory alignment issues. (#1724)
The x86 platform is very forgiving when you access a 16-bits variable stored at a memory address that is not aligned to a 2-bytes boundary, or a 32-bits variable that is not aligned to 4-bytes boundary, and so on. Other platforms, like ARM or Sparc are not that flexible, and accessing a value by dereferencing a pointer that is not aligned to the size of the value causes a processor fault.

This fixes multiple issues caused by pointers that are not aligned to the size of the value.

Fixes: #1700
2022-06-07 09:37:27 +02:00
Wesley Shields ccbc405cc9 Fix another compiler edge case. (#1722)
* Fix another compiler edge case.

When compiling and we encounter a range that has values we can determine at
compile time we should error out if the lower bound is less than 0.

* Fix OP_COUNT_IN paranoid check.

The OP_COUNT_IN operation does not need the paranoid check on r1 as it is the
lower bound of the range, and thus a constant and not a pointer somewhere. It
should, instead, be checking r3.

Fixes #1721 (the first half of it).
2022-06-01 16:03:22 +02:00
Victor M. Alvarez 1fd688e56b Reduce the amount of time that processes are maintained alive in test_process_scan.
test_process_scan launches a process and tests YARA's process scanning capabilities on it. This process was maintained alive for 10 minutes, which caused `make -j32 check` to hang during all that time before returning. This change reduces the time to 5 seconds, which should be enough for running the test cases.

Closes #1667 .
2022-05-18 10:05:39 +02:00
Mario Haustein bbd70441e4 finish all processes spawned in the test suite (#1683) 2022-05-17 18:22:02 +02:00
Wesley Shields a5903e1d24 Fix some compiler edge cases. (#1709)
* Fix some compiler edge cases.

Add a warning when "0 of them" is used. Point to some new documentation that
explains why "none of them" is preferred.

Handle some edge cases, which are all now errors:

* -1 of them
* "foo" of them
* /foo/ of them

And this one is also an error if the external variable "x" is a negative integer
or a string:

* x of them

I've also made sure this works with a construct like "0 + x of them" where x is
defined as a negative integer.

Add test cases for as many of these as I can. I don't have test cases for the
external variable case, but it does work as expected. Here is the output of a
rule using external variables where the variable is defined to be 1, 0, -1 and
foo:

```
wxs@mbp yara % cat rules/test.yara
rule a {
  strings:
    $a = "FreeBSD"
  condition:
    x of them
}
wxs@mbp yara % ./yara -d x=1 rules/test.yara /bin/ls
a /bin/ls
wxs@mbp yara % ./yara -d x=0 rules/test.yara /bin/ls
warning: rule "a" in rules/test.yara(5): Consider using "none" keyword, it is less ambiguous. Please see https://yara.readthedocs.io/en/stable/writingrules.html#sets-of-strings-1 for an explanation.
wxs@mbp yara % ./yara -d x=-1 rules/test.yara /bin/ls
error: rule "a" in rules/test.yara(5): invalid value in condition: "-1"
wxs@mbp yara % ./yara -d x=foo rules/test.yara /bin/ls
error: rule "a" in rules/test.yara(5): invalid value in condition: "string in for_expression is invalid"
wxs@mbp yara %
```

* More compiler warnings and errors.

If you specify "2 of ($a)" it is now a warning because it will always evaluate
to false, and is quite possibly not what you wanted to write. This is true for
string sets, rule sets and string sets in a range like "2 of ($a) in (0..10)".

If you are using an integer range it is now an error if the lower bound is
greater than the upper bound.

To support rule sets I needed to modify yr_parser_emit_pushes_for_rules() to
use a count parameter, which it will update with the number of pushed rules.
This is identical to how yr_parser_emit_pushes_for_strings() works.

While I'm here, remove the link from the warning message for the "none" keyword.
2022-05-17 18:20:57 +02:00
Wesley Shields a6ccc8f161 Fix an issue with none and 0 in expressions. (#1697)
As discussed in https://github.com/VirusTotal/yara/issues/1695, there is an
issue with some expressions involving "0" (and by extension "none"). If you
said "0 of them" and one of them matched we would evaluate that expression to
true because we never checked for the special 0 case.

Turns out this bug has existed for a while now but was likely never triggered
because not many people would say "0 of them" before the "none" keyword came
around. However, the author of the issue is correct that this should have been
exposed with better tests when I implemented the none keyword.

Fixes #1695.
2022-04-28 23:28:11 +02:00
Victor M. Alvarez ee96a35dad Fix regression introduced in #1692. 2022-04-25 16:02:52 +02:00
Victor M. Alvarez a91b8a1eec Fix issue #1690 (#1692)
Regular expressions with a character class followed by a dash (-) failed with "bad character range". For example,  /[0-9]-2/ was not accepted as a valid regexp.
2022-04-25 12:18:54 +02:00
Shane Huntley 2f96c5ab22 Allow hexstring not operator to be used with wild-cards (#1680) 2022-04-15 12:33:21 +02:00
Shane Huntley 2f6dd0144b Add a "not" operator for hex bytes (#1676)
* Add not operator (~) for bytes in hex strings.

* Describe not hexstring not operator in documentation.

* Basic tests for the hextring NOT operator

* Fix not operator documentation ordering
2022-04-06 11:17:11 +02:00
Wesley Shields 136794355c Fix #1660. (#1661)
There is an issue where the OP_OF_FOUND_IN opcode is broken when using "all of".
This is because the UNDEF that is pushed on the stack to indicate "all" is
compared to the number of matched strings as signed integers. If there are no
matched strings the condition still evaluates to true because 0 > (signed)
UNDEF.

Fix it by checking if we are using an UNDEF and compare it to the number of
strings checked if that is the case.
2022-03-09 17:17:41 +01:00
Victor M. Alvarez 384265e85e Improve atom extraction logic (#1656)
Fix issue #1646 by generalizing the solution provided in #1647. Atoms with a higher number of unique bytes are prioritized over atoms that have repeated characters.

Also fixes issue #1654, which was discovered in a debug session, but has been there for a long time.
2022-02-25 10:20:30 +01:00
Victor M. Alvarez d4aa53a026 Implement test cases for issue #1631 2022-01-14 14:09:32 +01:00
Victor M. Alvarez dd6fdf29e0 Define operator precedence in grammar.y exactly as documented.
Add some more test cases for "defined" operator and generate grammar with Bison 3.8.2.
2022-01-12 17:08:36 +01:00
Wesley Shields 7fabd955ab Implement rule sets. (#1597)
This adds the ability to use rule sets just like we do with string sets.
Specifically, it enables conditions like the following:

5 of (a, b)
50% of (a*)

where "a" is an existing rule and "b*" is a wildcard rule identifier, which is
expanded out precisely as wildcard string identifiers are.

I chose to make OP_OF and OP_OF_PERCENT emit an argument which is the "type" of
set it is expected to match on. The two acceptable values are OF_STRING_SET and
OF_RULE_SET. When OF_STRING_SET is used then the references on the stack are
expected to be strings and OF_RULE_SET will check if the rules on the stack
match.

I added a yr_parser_emit_pushes_for_rules() which behaves similarly to the
string counterpart. The one big exception is that I can't use yr_rules_foreach
macro since that needs the terminating "null" rule which is not yet added, so
instead I have to iterate the rules manually using yr_arena_get_ptr() to walk
all the currently compiled rules.

* Stricter ordering of rule set in compiler.

Make sure that when we compile a new rule that any existing rule sets do not
match the new rule. Specifically we are making the following a compiler error:

rule a1 { condition: true }
rule b { condition: 1 of (a*) }
rule a2 { condition: true }

This is a compiler error because "a2" is defined after the usage of (a*) in rule
b.

There is still an edge case here. These rules compile:

rule a { condition 1 of (a) }
rule b { condition: 1 of (b*) }

In both cases those rules evaluate to false, which is in line with the behavior
of this rule:

rule c { condition: c }

Given that the behavior around rule sets matches the current behavior I think
this is acceptable.

* Add docs for rule sets.

* Implement hash table iterators.

* Remove old comment about linked list.

* Move variable declaration.

* Iterate over rules better.
2021-12-21 12:46:33 +01:00
LearnToGetBetter 3c77ddc02f Add interface tests, including string_md5, string_sha1, string_sha26, data_checksum32, string_checksum32 (#1614) 2021-12-10 11:06:23 +01:00
xbabka01 dc4e0096c2 Added unary operation defined (#1529)
YARA didn't support any expression which would check value against YR_UNDEFINED constant so checking for non-existence of something can be very problematic. But we run multiple times into issue of people asking us for checking of absence of something.

Because of this we propose operator defined which would be unary operator (like not) which works like this:

defined x evaluates to

true - whenever x != YR_UNDEFINED
false - whenever x == YR_UNDEFINED

Related to issue #835
2021-10-21 10:41:40 +02:00
Wesley Shields e71801644f Implement OP_COUNT_IN. (#1565)
* Implement OP_COUNT_IN.

Add a new instruction (OP_COUNT_IN) which is used to check the number of
occurrences of a string in a range. You can use this with the following syntax:

 #a in (0..100) == 2

This will check that the $a string matches exactly 2 times in the range
provided.

* Add docs for counting strings in a range.
2021-09-16 15:16:33 +02:00
Wesley ShieldsandVictor M. Alvarez eb92e6b5aa Implement "none" keyword (#1559)
Co-authored-by: Victor M. Alvarez <[email protected]>
2021-09-02 20:57:39 +02:00
Victor M. Alvarez 6f7ebbc9ac Fix warning and reformat test-rules.c 2021-09-01 11:33:45 +02:00