enable split id bounds check in _yr_re_fiber_sync (#2208)

This commit is contained in:
jmestwa-coder
2026-06-24 12:00:26 +02:00
committed by GitHub
parent ff983bd822
commit 31d644a83a
2 changed files with 65 additions and 1 deletions
+2 -1
View File
@@ -44,6 +44,7 @@ order to avoid confusion with operating system threads.
#include <yara/error.h>
#include <yara/globals.h>
#include <yara/hex_lexer.h>
#include <yara/libyara.h>
#include <yara/limits.h>
#include <yara/mem.h>
#include <yara/re.h>
@@ -1524,7 +1525,7 @@ static int _yr_re_fiber_sync(
branch_b->ip += jmp_len;
#ifdef YR_PARANOID_MODE
#if YR_PARANOID_EXEC
// In normal conditions this should never happen. But with compiled
// rules that has been hand-crafted by a malicious actor this could
// happen.
+63
View File
@@ -28,10 +28,70 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <yara.h>
#include "util.h"
static int re_match_callback(
const uint8_t* match,
int match_length,
int flags,
void* args)
{
return 0;
}
// A compiled rule hand-crafted by a malicious actor can carry a regexp whose
// SPLIT instructions reference more distinct split ids than the compiler would
// ever emit (it caps them at RE_MAX_SPLIT_ID). _yr_re_fiber_sync tracks the
// executed split ids in an on-stack array of RE_MAX_SPLIT_ID entries, so such a
// stream must be rejected instead of writing past that array.
static void test_split_id_overflow(void)
{
int count = RE_MAX_SPLIT_ID + 64;
uint8_t code[(RE_MAX_SPLIT_ID + 64) * 4 + 1];
// A run of SPLIT_A instructions, each with a distinct split id and a branch
// that jumps to the trailing MATCH.
for (int i = 0; i < count; i++)
{
int16_t offset = (int16_t) ((count - i) * 4);
code[i * 4 + 0] = RE_OPCODE_SPLIT_A;
code[i * 4 + 1] = (uint8_t) i;
memcpy(code + i * 4 + 2, &offset, sizeof(offset));
}
code[count * 4] = RE_OPCODE_MATCH;
YR_SCAN_CONTEXT context;
memset(&context, 0, sizeof(context));
uint8_t input[1] = {0};
int matches = 0;
int result = yr_re_exec(
&context,
code,
input,
sizeof(input),
0,
RE_FLAGS_SCAN,
re_match_callback,
NULL,
&matches);
assert(result == ERROR_INTERNAL_FATAL_ERROR);
RE_FIBER* fiber = context.re_fiber_pool.fibers.head;
while (fiber != NULL)
{
RE_FIBER* next = fiber->next;
yr_free(fiber);
fiber = next;
}
}
int main(int argc, char** argv)
{
int result = 0;
@@ -81,6 +141,9 @@ int main(int argc, char** argv)
assert(re_ast_remain == NULL);
yr_re_ast_destroy(re_ast);
test_split_id_overflow();
yr_finalize();
YR_DEBUG_FPRINTF(