Coverage Report

Created: 2026-07-30 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib-imap/imap-seqset.c
Line
Count
Source
1
/* Copyright (c) Dovecot authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "array.h"
5
#include "imap-seqset.h"
6
7
static uint32_t get_next_number(const char **str)
8
0
{
9
0
  uint32_t num;
10
11
0
  if (str_parse_uint32(*str, &num, str) < 0)
12
0
    return 0;
13
14
0
  if (num == (uint32_t)-1) {
15
    /* FIXME: ugly hack, we're using this number to mean the
16
       last existing message. In reality UIDs should never get
17
       this high, so we can quite safely just drop this one down. */
18
0
    num--;
19
0
  }
20
21
0
  return num;
22
0
}
23
24
static int
25
get_next_seq_range(const char **str, uint32_t *seq1_r, uint32_t *seq2_r)
26
0
{
27
0
  uint32_t seq1, seq2;
28
29
0
  if (**str == '*') {
30
    /* last message */
31
0
    seq1 = (uint32_t)-1;
32
0
    *str += 1;
33
0
  } else {
34
0
    seq1 = get_next_number(str);
35
0
    if (seq1 == 0)
36
0
      return -1;
37
0
  }
38
39
0
  if (**str != ':')
40
0
    seq2 = seq1;
41
0
  else {
42
    /* first:last range */
43
0
    *str += 1;
44
45
0
    if (**str == '*') {
46
0
      seq2 = (uint32_t)-1;
47
0
      *str += 1;
48
0
    } else {
49
0
      seq2 = get_next_number(str);
50
0
      if (seq2 == 0)
51
0
        return -1;
52
0
    }
53
0
  }
54
55
0
  if (seq1 > seq2) {
56
    /* swap, as specified by RFC-3501 */
57
0
    *seq1_r = seq2;
58
0
    *seq2_r = seq1;
59
0
  } else {
60
0
    *seq1_r = seq1;
61
0
    *seq2_r = seq2;
62
0
  }
63
0
  return 0;
64
0
}
65
66
int imap_seq_set_parse(const char *str, ARRAY_TYPE(seq_range) *dest)
67
0
{
68
0
  uint32_t seq1, seq2;
69
70
0
  do {
71
0
    if (get_next_seq_range(&str, &seq1, &seq2) < 0)
72
0
      return -1;
73
0
    seq_range_array_add_range(dest, seq1, seq2);
74
75
0
    if (*str == ',')
76
0
      str++;
77
0
  } while (*str != '\0');
78
0
  return 0;
79
0
}
80
81
int imap_seq_set_nostar_parse(const char *str, ARRAY_TYPE(seq_range) *dest)
82
0
{
83
0
  if (imap_seq_set_parse(str, dest) < 0)
84
0
    return -1;
85
86
0
  if (seq_range_exists(dest, (uint32_t)-1)) {
87
    /* '*' used */
88
0
    return -1;
89
0
  }
90
0
  return 0;
91
0
}
92
93
int imap_seq_set_ordered_parse(const char *str, ARRAY_TYPE(uint32_t) *dest)
94
0
{
95
0
  uint32_t seq1, seq2;
96
97
0
  for (;;) {
98
0
    seq1 = get_next_number(&str);
99
0
    if (seq1 == 0)
100
0
      return -1;
101
0
    if (*str != ':')
102
0
      seq2 = seq1;
103
0
    else {
104
0
      str++;
105
0
      seq2 = get_next_number(&str);
106
0
      if (seq2 == 0)
107
0
        return -1;
108
0
    }
109
0
    if (seq1 > seq2)
110
0
      return -1;
111
112
0
    for (uint32_t seq = seq1; seq <= seq2; seq++)
113
0
      array_push_back(dest, &seq);
114
115
0
    if (*str == '\0')
116
0
      break;
117
0
    if (*str != ',')
118
0
      return -1;
119
0
    str++;
120
0
  }
121
0
  return 0;
122
0
}
123
124
int imap_seq_range_parse(const char *str, uint32_t *seq1_r, uint32_t *seq2_r)
125
0
{
126
0
  if (get_next_seq_range(&str, seq1_r, seq2_r) < 0)
127
0
    return -1;
128
0
  return *str == '\0' ? 0 : -1;
129
0
}