Coverage Report

Created: 2026-09-01 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/mcht-contains.c
Line
Count
Source
1
/* Copyright (c) Pigeonhole authors, see top-level COPYING file */
2
3
/* Match-type ':contains'
4
 */
5
6
#include "lib.h"
7
8
#include "sieve-match-types.h"
9
#include "sieve-comparators.h"
10
#include "sieve-interpreter.h"
11
#include "sieve-match.h"
12
13
#include <string.h>
14
#include <stdio.h>
15
16
/*
17
 * Forward declarations
18
 */
19
20
static int
21
mcht_contains_match_key(struct sieve_match_context *mctx,
22
      const char *val, size_t val_size,
23
      const char *key, size_t key_size);
24
25
/*
26
 * Match-type object
27
 */
28
29
const struct sieve_match_type_def contains_match_type = {
30
  SIEVE_OBJECT("contains", &match_type_operand,
31
         SIEVE_MATCH_TYPE_CONTAINS),
32
  .validate_context = sieve_match_substring_validate_context,
33
  .match_key = mcht_contains_match_key
34
};
35
36
/*
37
 * Match-type implementation
38
 */
39
40
/* FIXME: Naive substring match implementation. Should switch to more efficient
41
          algorithm if large values need to be searched (e.g. message body).
42
  
43
          The inner loop polls the interpreter CPU time limit periodically so
44
          that a single O(N*M) match on a large value cannot run for many times
45
          the configured sieve_max_cpu_time (which is otherwise only checked
46
    between bytecode operations).
47
 */
48
0
#define SIEVE_CONTAINS_CPU_CHECK_INTERVAL 64
49
50
static int
51
mcht_contains_match_key(struct sieve_match_context *mctx,
52
      const char *val, size_t val_size,
53
      const char *key, size_t key_size)
54
0
{
55
0
  const struct sieve_comparator *cmp = mctx->comparator;
56
0
  const char *vend = (const char *) val + val_size;
57
0
  const char *kend = (const char *) key + key_size;
58
0
  const char *vp = val;
59
0
  const char *kp = key;
60
0
  unsigned int counter = 0;
61
62
0
  if (val_size == 0)
63
0
    return (key_size == 0 ? 1 : 0);
64
65
0
  if (cmp->def == NULL || cmp->def->char_match == NULL)
66
0
    return 0;
67
68
0
  while ((vp < vend) && (kp < kend)) {
69
0
    if (!cmp->def->char_match(cmp, &vp, vend, &kp, kend))
70
0
      vp++;
71
72
0
    if ( ++counter >= SIEVE_CONTAINS_CPU_CHECK_INTERVAL ) {
73
0
      counter = 0;
74
0
      if ( sieve_runtime_cpu_limit_exceeded(mctx->runenv) ) {
75
0
        sieve_runtime_error(
76
0
          mctx->runenv, NULL,
77
0
          "execution exceeded CPU time limit");
78
0
        mctx->exec_status =
79
0
          SIEVE_EXEC_RESOURCE_LIMIT;
80
0
        return -1;
81
0
      }
82
0
    }
83
0
  }
84
85
0
  return (kp == kend ? 1 : 0);
86
0
}