Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/third_party/heimdal/lib/base/string.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2010 Kungliga Tekniska Högskolan
3
 * (Royal Institute of Technology, Stockholm, Sweden).
4
 * All rights reserved.
5
 *
6
 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * 3. Neither the name of the Institute nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include "baselocl.h"
37
#include <string.h>
38
39
static void HEIM_CALLCONV
40
string_dealloc(void *ptr)
41
0
{
42
0
    heim_string_t s = ptr;
43
0
    heim_string_free_f_t *deallocp;
44
0
    heim_string_free_f_t dealloc;
45
46
0
    if (*(const char *)ptr != '\0')
47
0
  return;
48
49
    /* Possible string ref */
50
0
    deallocp = _heim_get_isaextra(s, 0);
51
0
    dealloc = *deallocp;
52
0
    if (dealloc != NULL) {
53
0
  char **strp = _heim_get_isaextra(s, 1);
54
0
  dealloc(*strp);
55
0
    }
56
0
}
57
58
static int
59
string_cmp(void *a, void *b)
60
0
{
61
0
    if (*(char *)a == '\0') {
62
0
  char **strp = _heim_get_isaextra(a, 1);
63
64
0
  if (*strp != NULL)
65
0
      a = *strp; /* a is a string ref */
66
0
    }
67
0
    if (*(char *)b == '\0') {
68
0
  char **strp = _heim_get_isaextra(b, 1);
69
70
0
  if (*strp != NULL)
71
0
      b = *strp; /* b is a string ref */
72
0
    }
73
0
    return strcmp(a, b);
74
0
}
75
76
static uintptr_t
77
string_hash(void *ptr)
78
0
{
79
0
    const char *s = ptr;
80
0
    uintptr_t n;
81
82
0
    for (n = 0; *s; ++s)
83
0
  n += *s;
84
0
    return n;
85
0
}
86
87
struct heim_type_data _heim_string_object = {
88
    HEIM_TID_STRING,
89
    "string-object",
90
    NULL,
91
    string_dealloc,
92
    NULL,
93
    string_cmp,
94
    string_hash,
95
    NULL
96
};
97
98
/**
99
 * Create a string object
100
 *
101
 * @param string the string to create, must be an utf8 string
102
 *
103
 * @return string object
104
 */
105
106
heim_string_t
107
heim_string_create(const char *string)
108
0
{
109
0
    return heim_string_create_with_bytes(string, strlen(string));
110
0
}
111
112
/**
113
 * Create a string object without copying the source.
114
 *
115
 * @param string the string to referenced, must be UTF-8
116
 * @param dealloc the function to use to release the referece to the string
117
 *
118
 * @return string object
119
 */
120
121
heim_string_t
122
heim_string_ref_create(const char *string, heim_string_free_f_t dealloc)
123
0
{
124
0
    heim_string_t s;
125
0
    heim_string_free_f_t *deallocp;
126
127
0
    s = _heim_alloc_object(&_heim_string_object, 1);
128
0
    if (s) {
129
0
  const char **strp;
130
131
0
  ((char *)s)[0] = '\0';
132
0
  deallocp = _heim_get_isaextra(s, 0);
133
0
  *deallocp = dealloc;
134
0
  strp = _heim_get_isaextra(s, 1);
135
0
  *strp = string;
136
0
    }
137
0
    return s;
138
0
}
139
140
/**
141
 * Create a string object
142
 *
143
 * @param string the string to create, must be an utf8 string
144
 * @param len the length of the string
145
 *
146
 * @return string object
147
 */
148
149
heim_string_t
150
heim_string_create_with_bytes(const void *data, size_t len)
151
0
{
152
0
    heim_string_t s;
153
154
0
    s = _heim_alloc_object(&_heim_string_object, len + 1);
155
0
    if (s) {
156
0
        if (len)
157
0
            memcpy(s, data, len);
158
0
  ((char *)s)[len] = '\0';
159
0
    }
160
0
    return s;
161
0
}
162
163
/**
164
 * Create a string object using a format string
165
 *
166
 * @param fmt format string
167
 * @param ...
168
 *
169
 * @return string object
170
 */
171
172
heim_string_t
173
heim_string_create_with_format(const char *fmt, ...)
174
0
{
175
0
    heim_string_t s;
176
0
    char *str = NULL;
177
0
    va_list ap;
178
0
    int ret;
179
180
0
    va_start(ap, fmt);
181
0
    ret = vasprintf(&str, fmt, ap);
182
0
    va_end(ap);
183
0
    if (ret < 0 || str == NULL)
184
0
  return NULL;
185
186
0
    s = heim_string_ref_create(str, free);
187
0
    if (s == NULL)
188
0
  free(str);
189
0
    return s;
190
0
}
191
192
/**
193
 * Return the type ID of string objects
194
 *
195
 * @return type id of string objects
196
 */
197
198
heim_tid_t
199
heim_string_get_type_id(void)
200
0
{
201
0
    return HEIM_TID_STRING;
202
0
}
203
204
/**
205
 * Get the string value of the content.
206
 *
207
 * @param string the string object to get the value from
208
 *
209
 * @return a utf8 string
210
 */
211
212
const char *
213
heim_string_get_utf8(heim_string_t string)
214
0
{
215
0
    if (*(const char *)string == '\0') {
216
0
  const char **strp;
217
218
  /* String ref */
219
0
  strp = _heim_get_isaextra(string, 1);
220
0
  if (*strp != NULL)
221
0
      return *strp;
222
0
    }
223
0
    return (const char *)string;
224
0
}
225
226
/*
227
 *
228
 */
229
230
static void
231
init_string(void *ptr)
232
0
{
233
0
    heim_dict_t *dict = ptr;
234
0
    *dict = heim_dict_create(101);
235
0
    heim_assert(*dict != NULL, "__heim_string_constant");
236
0
}
237
238
heim_string_t
239
__heim_string_constant(const char *_str)
240
0
{
241
0
    static HEIMDAL_MUTEX mutex = HEIMDAL_MUTEX_INITIALIZER;
242
0
    static heim_base_once_t once = HEIM_BASE_ONCE_INIT;
243
0
    static heim_dict_t dict = NULL;
244
0
    heim_string_t s, s2;
245
246
0
    heim_base_once_f(&once, &dict, init_string);
247
0
    s = heim_string_create(_str);
248
249
0
    HEIMDAL_MUTEX_lock(&mutex);
250
0
    s2 = heim_dict_get_value(dict, s);
251
0
    if (s2) {
252
0
  heim_release(s);
253
0
  s = s2;
254
0
    } else {
255
0
  _heim_make_permanent(s);
256
0
  heim_dict_set_value(dict, s, s);
257
0
    }
258
0
    HEIMDAL_MUTEX_unlock(&mutex);
259
260
0
    return s;
261
0
}