Coverage Report

Created: 2023-11-19 07:08

/src/git/parse.c
Line
Count
Source (jump to first uncovered line)
1
#include "git-compat-util.h"
2
#include "gettext.h"
3
#include "parse.h"
4
5
static uintmax_t get_unit_factor(const char *end)
6
10.1k
{
7
10.1k
  if (!*end)
8
10.1k
    return 1;
9
0
  else if (!strcasecmp(end, "k"))
10
0
    return 1024;
11
0
  else if (!strcasecmp(end, "m"))
12
0
    return 1024 * 1024;
13
0
  else if (!strcasecmp(end, "g"))
14
0
    return 1024 * 1024 * 1024;
15
0
  return 0;
16
10.1k
}
17
18
int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
19
10.1k
{
20
10.1k
  if (value && *value) {
21
10.1k
    char *end;
22
10.1k
    intmax_t val;
23
10.1k
    intmax_t factor;
24
25
10.1k
    if (max < 0)
26
0
      BUG("max must be a positive integer");
27
28
10.1k
    errno = 0;
29
10.1k
    val = strtoimax(value, &end, 0);
30
10.1k
    if (errno == ERANGE)
31
0
      return 0;
32
10.1k
    if (end == value) {
33
0
      errno = EINVAL;
34
0
      return 0;
35
0
    }
36
10.1k
    factor = get_unit_factor(end);
37
10.1k
    if (!factor) {
38
0
      errno = EINVAL;
39
0
      return 0;
40
0
    }
41
10.1k
    if ((val < 0 && -max / factor > val) ||
42
10.1k
        (val > 0 && max / factor < val)) {
43
0
      errno = ERANGE;
44
0
      return 0;
45
0
    }
46
10.1k
    val *= factor;
47
10.1k
    *ret = val;
48
10.1k
    return 1;
49
10.1k
  }
50
0
  errno = EINVAL;
51
0
  return 0;
52
10.1k
}
53
54
static int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
55
0
{
56
0
  if (value && *value) {
57
0
    char *end;
58
0
    uintmax_t val;
59
0
    uintmax_t factor;
60
61
    /* negative values would be accepted by strtoumax */
62
0
    if (strchr(value, '-')) {
63
0
      errno = EINVAL;
64
0
      return 0;
65
0
    }
66
0
    errno = 0;
67
0
    val = strtoumax(value, &end, 0);
68
0
    if (errno == ERANGE)
69
0
      return 0;
70
0
    if (end == value) {
71
0
      errno = EINVAL;
72
0
      return 0;
73
0
    }
74
0
    factor = get_unit_factor(end);
75
0
    if (!factor) {
76
0
      errno = EINVAL;
77
0
      return 0;
78
0
    }
79
0
    if (unsigned_mult_overflows(factor, val) ||
80
0
        factor * val > max) {
81
0
      errno = ERANGE;
82
0
      return 0;
83
0
    }
84
0
    val *= factor;
85
0
    *ret = val;
86
0
    return 1;
87
0
  }
88
0
  errno = EINVAL;
89
0
  return 0;
90
0
}
91
92
int git_parse_int(const char *value, int *ret)
93
10.1k
{
94
10.1k
  intmax_t tmp;
95
10.1k
  if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int)))
96
0
    return 0;
97
10.1k
  *ret = tmp;
98
10.1k
  return 1;
99
10.1k
}
100
101
int git_parse_int64(const char *value, int64_t *ret)
102
0
{
103
0
  intmax_t tmp;
104
0
  if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int64_t)))
105
0
    return 0;
106
0
  *ret = tmp;
107
0
  return 1;
108
0
}
109
110
int git_parse_ulong(const char *value, unsigned long *ret)
111
0
{
112
0
  uintmax_t tmp;
113
0
  if (!git_parse_unsigned(value, &tmp, maximum_unsigned_value_of_type(long)))
114
0
    return 0;
115
0
  *ret = tmp;
116
0
  return 1;
117
0
}
118
119
int git_parse_ssize_t(const char *value, ssize_t *ret)
120
0
{
121
0
  intmax_t tmp;
122
0
  if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(ssize_t)))
123
0
    return 0;
124
0
  *ret = tmp;
125
0
  return 1;
126
0
}
127
128
int git_parse_maybe_bool_text(const char *value)
129
118k
{
130
118k
  if (!value)
131
0
    return 1;
132
118k
  if (!*value)
133
0
    return 0;
134
118k
  if (!strcasecmp(value, "true")
135
118k
      || !strcasecmp(value, "yes")
136
118k
      || !strcasecmp(value, "on"))
137
66.0k
    return 1;
138
52.2k
  if (!strcasecmp(value, "false")
139
52.2k
      || !strcasecmp(value, "no")
140
52.2k
      || !strcasecmp(value, "off"))
141
52.2k
    return 0;
142
0
  return -1;
143
52.2k
}
144
145
int git_parse_maybe_bool(const char *value)
146
118k
{
147
118k
  int v = git_parse_maybe_bool_text(value);
148
118k
  if (0 <= v)
149
118k
    return v;
150
0
  if (git_parse_int(value, &v))
151
0
    return !!v;
152
0
  return -1;
153
0
}
154
155
/*
156
 * Parse environment variable 'k' as a boolean (in various
157
 * possible spellings); if missing, use the default value 'def'.
158
 */
159
int git_env_bool(const char *k, int def)
160
118k
{
161
118k
  const char *v = getenv(k);
162
118k
  int val;
163
118k
  if (!v)
164
94.6k
    return def;
165
23.9k
  val = git_parse_maybe_bool(v);
166
23.9k
  if (val < 0)
167
0
    die(_("bad boolean environment value '%s' for '%s'"),
168
0
        v, k);
169
23.9k
  return val;
170
23.9k
}
171
172
/*
173
 * Parse environment variable 'k' as ulong with possibly a unit
174
 * suffix; if missing, use the default value 'val'.
175
 */
176
unsigned long git_env_ulong(const char *k, unsigned long val)
177
29.3k
{
178
29.3k
  const char *v = getenv(k);
179
29.3k
  if (v && !git_parse_ulong(v, &val))
180
0
    die(_("failed to parse %s"), k);
181
29.3k
  return val;
182
29.3k
}