GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/locale/rune.c Lines: 82 117 70.1 %
Date: 2017-11-07 Branches: 40 76 52.6 %

Line Branch Exec Source
1
/*	$OpenBSD: rune.c,v 1.7 2016/09/05 09:47:03 schwarze Exp $ */
2
/*	$NetBSD: rune.c,v 1.26 2004/05/09 11:26:33 kleink Exp $	*/
3
4
/*-
5
 * Copyright (c)1999 Citrus Project,
6
 * 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
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
/*-
31
 * Copyright (c) 1993
32
 *	The Regents of the University of California.  All rights reserved.
33
 *
34
 * This code is derived from software contributed to Berkeley by
35
 * Paul Borman at Krystal Technologies.
36
 *
37
 * Redistribution and use in source and binary forms, with or without
38
 * modification, are permitted provided that the following conditions
39
 * are met:
40
 * 1. Redistributions of source code must retain the above copyright
41
 *    notice, this list of conditions and the following disclaimer.
42
 * 2. Redistributions in binary form must reproduce the above copyright
43
 *    notice, this list of conditions and the following disclaimer in the
44
 *    documentation and/or other materials provided with the distribution.
45
 * 3. Neither the name of the University nor the names of its contributors
46
 *    may be used to endorse or promote products derived from this software
47
 *    without specific prior written permission.
48
 *
49
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59
 * SUCH DAMAGE.
60
 */
61
62
#include <sys/types.h>
63
#include <sys/stat.h>
64
#include <assert.h>
65
#include <errno.h>
66
#include <stdint.h>
67
#include <stdio.h>
68
#include <stdlib.h>
69
#include <string.h>
70
#include <wchar.h>
71
#include "rune.h"
72
#include "rune_local.h"
73
74
#define SAFE_ADD(x, y)			\
75
do {					\
76
	if ((x) > SIZE_MAX - (y))	\
77
		return NULL;		\
78
	(x) += (y);			\
79
} while (0);
80
81
static int readrange(_RuneLocale *, _RuneRange *, uint32_t, void *, FILE *);
82
static void _freeentry(_RuneRange *);
83
static void _wctype_init(_RuneLocale *rl);
84
85
static int
86
readrange(_RuneLocale *rl, _RuneRange *rr, uint32_t nranges, void *lastp,
87
	FILE *fp)
88
{
89
	uint32_t i;
90
	_RuneEntry *re;
91
240
	_FileRuneEntry fre;
92
93
120
	re = (_RuneEntry *)rl->rl_variable;
94
95
120
	rr->rr_nranges = nranges;
96
120
	if (rr->rr_nranges == 0) {
97
		rr->rr_rune_ranges = NULL;
98
		return 0;
99
	}
100
101
120
	rr->rr_rune_ranges = re;
102
150640
	for (i = 0; i < rr->rr_nranges; i++) {
103
75200
		if ((void *)re >= lastp)
104
			return -1;
105
106
75200
		if (fread(&fre, sizeof(fre), 1, fp) != 1)
107
			return -1;
108
109
75200
		re->re_min = ntohl((uint32_t)fre.fre_min);
110
75200
		re->re_max = ntohl((uint32_t)fre.fre_max);
111
75200
		re->re_map = ntohl((uint32_t)fre.fre_map);
112
75200
		re++;
113
	}
114
120
	rl->rl_variable = re;
115
120
	return 0;
116
120
}
117
118
static int
119
readentry(_RuneRange *rr, FILE *fp)
120
{
121
	_RuneEntry *re;
122
	size_t l, i, j;
123
	int error;
124
125
80
	re = rr->rr_rune_ranges;
126
49120
	for (i = 0; i < rr->rr_nranges; i++) {
127
24520
		if (re[i].re_map != 0) {
128
15920
			re[i].re_rune_types = NULL;
129
15920
			continue;
130
		}
131
132
8600
		if (re[i].re_max < re[i].re_min) {
133
			error = EINVAL;
134
			goto fail;
135
		}
136
137
8600
		l = re[i].re_max - re[i].re_min + 1;
138
8600
		re[i].re_rune_types = calloc(l, sizeof(_RuneType));
139
8600
		if (!re[i].re_rune_types) {
140
			error = ENOMEM;
141
			goto fail;
142
		}
143
144
8600
		if (fread(re[i].re_rune_types, sizeof(_RuneType), l, fp) != l)
145
			goto fail2;
146
147
7604200
		for (j = 0; j < l; j++)
148
3797800
			re[i].re_rune_types[j] = ntohl(re[i].re_rune_types[j]);
149
	}
150
40
	return 0;
151
152
fail:
153
	for (j = 0; j < i; j++) {
154
		free(re[j].re_rune_types);
155
		re[j].re_rune_types = NULL;
156
	}
157
	return error;
158
fail2:
159
	for (j = 0; j <= i; j++) {
160
		free(re[j].re_rune_types);
161
		re[j].re_rune_types = NULL;
162
	}
163
	return errno;
164
40
}
165
166
/* XXX: temporary implementation */
167
static int
168
find_codeset(_RuneLocale *rl)
169
{
170
	char *top, *codeset, *tail, *ep;
171
172
80
	if (rl->rl_variable == NULL)
173
		return 0;
174
175
	/* end of rl_variable region */
176
	ep = (char *)rl->rl_variable;
177
40
	ep += rl->rl_variable_len;
178
40
	rl->rl_codeset = NULL;
179
40
	if (!(top = strstr(rl->rl_variable, _RUNE_CODESET)))
180
		return 0;
181
40
	tail = strpbrk(top, " \t");
182
40
	codeset = top + sizeof(_RUNE_CODESET) - 1;
183
40
	if (tail) {
184
		*top = *tail;
185
		*tail = '\0';
186
		rl->rl_codeset = strdup(codeset);
187
		strlcpy(top + 1, tail + 1, (unsigned)(ep - (top + 1)));
188
	} else {
189
40
		*top = '\0';
190
40
		rl->rl_codeset = strdup(codeset);
191
	}
192
40
	return (rl->rl_codeset == NULL);
193
40
}
194
195
void
196
_freeentry(_RuneRange *rr)
197
{
198
	_RuneEntry *re;
199
	uint32_t i;
200
201
	re = rr->rr_rune_ranges;
202
	for (i = 0; i < rr->rr_nranges; i++) {
203
		free(re[i].re_rune_types);
204
		re[i].re_rune_types = NULL;
205
	}
206
}
207
208
void
209
_wctype_init(_RuneLocale *rl)
210
{
211
80
	memcpy(&rl->rl_wctype, &_DefaultRuneLocale.rl_wctype,
212
	       sizeof(rl->rl_wctype));
213
40
}
214
215
216
_RuneLocale *
217
_Read_RuneMagi(FILE *fp)
218
{
219
	/* file */
220
80
	_FileRuneLocale frl;
221
	/* host data */
222
	char *hostdata;
223
	size_t hostdatalen;
224
	void *lastp;
225
	_RuneLocale *rl;
226
40
	struct stat sb;
227
	int x;
228
	uint32_t runetype_nranges, maplower_nranges, mapupper_nranges, var_len;
229
230

120
	if (fstat(fileno(fp), &sb) < 0)
231
		return NULL;
232
233
40
	if (sb.st_size < sizeof(_FileRuneLocale))
234
		return NULL;
235
	/* XXX more validation? */
236
237
	/* Someone might have read the magic number once already */
238
40
	rewind(fp);
239
240
40
	if (fread(&frl, sizeof(frl), 1, fp) != 1)
241
		return NULL;
242
40
	if (memcmp(frl.frl_magic, _RUNE_MAGIC_1, sizeof(frl.frl_magic)))
243
		return NULL;
244
245
40
	runetype_nranges = ntohl(frl.frl_runetype_ext.frr_nranges);
246
40
	maplower_nranges = ntohl(frl.frl_maplower_ext.frr_nranges);
247
40
	mapupper_nranges = ntohl(frl.frl_mapupper_ext.frr_nranges);
248
40
	var_len = ntohl((uint32_t)frl.frl_variable_len);
249
250
#if SIZE_MAX <= UINT32_MAX
251
	if (runetype_nranges > SIZE_MAX / sizeof(_RuneEntry) ||
252
	    maplower_nranges > SIZE_MAX / sizeof(_RuneEntry) ||
253
	    mapupper_nranges > SIZE_MAX / sizeof(_RuneEntry))
254
		return NULL;
255
#endif
256
257
40
	if (var_len > INT32_MAX)
258
		return NULL;
259
260
	hostdatalen = sizeof(*rl);
261
80
	SAFE_ADD(hostdatalen, var_len);
262
80
	SAFE_ADD(hostdatalen, runetype_nranges * sizeof(_RuneEntry));
263
80
	SAFE_ADD(hostdatalen, maplower_nranges * sizeof(_RuneEntry));
264
80
	SAFE_ADD(hostdatalen, mapupper_nranges * sizeof(_RuneEntry));
265
266
40
	if ((hostdata = calloc(hostdatalen, 1)) == NULL)
267
		return NULL;
268
40
	lastp = hostdata + hostdatalen;
269
270
40
	rl = (_RuneLocale *)hostdata;
271
40
	rl->rl_variable = rl + 1;
272
273
40
	memcpy(rl->rl_magic, frl.frl_magic, sizeof(rl->rl_magic));
274
40
	memcpy(rl->rl_encoding, frl.frl_encoding, sizeof(rl->rl_encoding));
275
276
	/* XXX assumes rune_t = uint32_t */
277
40
	rl->rl_invalid_rune = ntohl((uint32_t)frl.frl_invalid_rune);
278
40
	rl->rl_variable_len = ntohl((uint32_t)frl.frl_variable_len);
279
280
20560
	for (x = 0; x < _CACHED_RUNES; ++x) {
281
10240
		rl->rl_runetype[x] = ntohl(frl.frl_runetype[x]);
282
283
		/* XXX assumes rune_t = uint32_t */
284
10240
		rl->rl_maplower[x] = ntohl((uint32_t)frl.frl_maplower[x]);
285
10240
		rl->rl_mapupper[x] = ntohl((uint32_t)frl.frl_mapupper[x]);
286
	}
287
288

80
	if (readrange(rl, &rl->rl_runetype_ext, runetype_nranges, lastp, fp) ||
289
40
	    readrange(rl, &rl->rl_maplower_ext, maplower_nranges, lastp, fp) ||
290
40
	    readrange(rl, &rl->rl_mapupper_ext, mapupper_nranges, lastp, fp))
291
		goto err;
292
293
40
	if (readentry(&rl->rl_runetype_ext, fp) != 0)
294
		goto err;
295
296
40
	if ((uint8_t *)rl->rl_variable + rl->rl_variable_len >
297
	    (uint8_t *)lastp)
298
		goto rune_err;
299
300
40
	if (rl->rl_variable_len == 0)
301
		rl->rl_variable = NULL;
302
40
	else if (fread(rl->rl_variable, rl->rl_variable_len, 1, fp) != 1)
303
		goto rune_err;
304
40
	if (find_codeset(rl))
305
		goto rune_err;
306
40
	_wctype_init(rl);
307
308
	/*
309
	 * error if we have junk at the tail,
310
	 * or if we can't allocate memory.
311
	 */
312

80
	if (ftello(fp) != sb.st_size || __make_ctype_tabs(rl) == -1)
313
		goto rune_err;
314
315
40
	return(rl);
316
rune_err:
317
	_freeentry(&rl->rl_runetype_ext);
318
err:
319
	free(hostdata);
320
	return NULL;
321
40
}