Coverage Report

Created: 2026-06-09 06:49

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) 2002-2018 Pigeonhole authors, see the included COPYING file
2
 */
3
4
/* Match-type ':contains'
5
 */
6
7
#include "lib.h"
8
9
#include "sieve-match-types.h"
10
#include "sieve-comparators.h"
11
#include "sieve-interpreter.h"
12
#include "sieve-match.h"
13
14
#include <string.h>
15
#include <stdio.h>
16
17
/*
18
 * Forward declarations
19
 */
20
21
static int mcht_contains_match_key
22
  (struct sieve_match_context *mctx, 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",
31
    &match_type_operand, 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
41
 * efficient 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 that a
44
 * single O(N*M) match on a large value cannot run for many times the
45
 * configured sieve_max_cpu_time (which is otherwise only checked between
46
 * bytecode operations).
47
 */
48
0
#define SIEVE_CONTAINS_CPU_CHECK_INTERVAL 4096
49
50
static int mcht_contains_match_key
51
(struct sieve_match_context *mctx, const char *val, size_t val_size,
52
  const char *key, size_t key_size)
53
0
{
54
0
  const struct sieve_comparator *cmp = mctx->comparator;
55
0
  const char *vend = (const char *) val + val_size;
56
0
  const char *kend = (const char *) key + key_size;
57
0
  const char *vp = val;
58
0
  const char *kp = key;
59
0
  unsigned int counter = 0;
60
61
0
  if ( val_size == 0 )
62
0
    return ( key_size == 0 ? 1 : 0 );
63
64
0
  if ( cmp->def == NULL || cmp->def->char_match == NULL )
65
0
    return 0;
66
67
0
  while ( (vp < vend) && (kp < kend) ) {
68
0
    if ( !cmp->def->char_match(cmp, &vp, vend, &kp, kend) )
69
0
      vp++;
70
71
0
    if ( ++counter >= SIEVE_CONTAINS_CPU_CHECK_INTERVAL ) {
72
0
      counter = 0;
73
0
      if ( sieve_runtime_cpu_limit_exceeded(mctx->runenv) ) {
74
0
        sieve_runtime_error(
75
0
          mctx->runenv, NULL,
76
0
          "execution exceeded CPU time limit");
77
0
        mctx->exec_status =
78
0
          SIEVE_EXEC_RESOURCE_LIMIT;
79
0
        return -1;
80
0
      }
81
0
    }
82
0
  }
83
84
0
  return ( kp == kend ? 1 : 0 );
85
0
}
86
87