Bug Summary

File:src/util.c
Warning:line 195, column 7
String copy function overflows destination buffer

Annotated Source Code

1/*
2 * Copyright (c) 2007, Novell Inc.
3 *
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
6 */
7
8#define _GNU_SOURCE
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <string.h>
14#include <sys/time.h>
15
16#include "util.h"
17
18void
19solv_oom(size_t num, size_t len)
20{
21 if (num)
22 fprintf(stderrstderr, "Out of memory allocating %zu*%zu bytes!\n", num, len);
23 else
24 fprintf(stderrstderr, "Out of memory allocating %zu bytes!\n", len);
25 abort();
26 exit(1);
27}
28
29void *
30solv_malloc(size_t len)
31{
32 void *r = malloc(len ? len : 1);
33 if (!r)
34 solv_oom(0, len);
35 return r;
36}
37
38void *
39solv_malloc2(size_t num, size_t len)
40{
41 if (len && (num * len) / len != num)
42 solv_oom(num, len);
43 return solv_malloc(num * len);
44}
45
46void *
47solv_realloc(void *old, size_t len)
48{
49 if (old == 0)
50 old = malloc(len ? len : 1);
51 else
52 old = realloc(old, len ? len : 1);
53 if (!old)
54 solv_oom(0, len);
55 return old;
56}
57
58void *
59solv_realloc2(void *old, size_t num, size_t len)
60{
61 if (len && (num * len) / len != num)
62 solv_oom(num, len);
63 return solv_realloc(old, num * len);
64}
65
66void *
67solv_calloc(size_t num, size_t len)
68{
69 void *r;
70 if (num == 0 || len == 0)
71 r = malloc(1);
72 else
73 r = calloc(num, len);
74 if (!r)
75 solv_oom(num, len);
76 return r;
77}
78
79/* this was solv_realloc2(old, len, size), but we now overshoot
80 * for huge len sizes */
81void *
82solv_extend_realloc(void *old, size_t len, size_t size, size_t block)
83{
84 size_t xblock = (block + 1) << 5;
85 len = (len + block) & ~block;
86 if (len >= xblock && xblock)
87 {
88 xblock <<= 1;
89 while (len >= xblock && xblock)
90 xblock <<= 1;
91 if (xblock)
92 {
93 size_t nlen;
94 xblock = (xblock >> 5) - 1;
95 nlen = (len + xblock) & ~xblock;
96 if (nlen > len)
97 len = nlen;
98 }
99 }
100 return solv_realloc2(old, len, size);
101}
102
103void *
104solv_free(void *mem)
105{
106 if (mem)
107 free(mem);
108 return 0;
109}
110
111char *
112solv_strdup(const char *s)
113{
114 char *r;
115 if (!s)
116 return 0;
117 r = strdup(s);
118 if (!r)
119 solv_oom(0, strlen(s));
120 return r;
121}
122
123unsigned int
124solv_timems(unsigned int subtract)
125{
126 struct timeval tv;
127 unsigned int r;
128
129 if (gettimeofday(&tv, 0))
130 return 0;
131 r = (((unsigned int)tv.tv_sec >> 16) * 1000) << 16;
132 r += ((unsigned int)tv.tv_sec & 0xffff) * 1000;
133 r += (unsigned int)tv.tv_usec / 1000;
134 return r - subtract;
135}
136
137/* bsd's qsort_r has different arguments, so we define our
138 own version in case we need to do some clever mapping
139
140 see also: http://sources.redhat.com/ml/libc-alpha/2008-12/msg00003.html
141 */
142#if (defined(__GLIBC__2) || defined(__NEWLIB__)) && (defined(HAVE_QSORT_R1) || defined(HAVE___QSORT_R))
143
144void
145solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard)
146{
147# if defined(HAVE_QSORT_R1)
148 qsort_r(base, nmemb, size, compar, compard);
149# else
150 /* backported for SLE10-SP2 */
151 __qsort_r(base, nmemb, size, compar, compard);
152# endif
153
154}
155
156#elif defined(HAVE_QSORT_R1) /* not glibc, but has qsort_r() */
157
158struct solv_sort_data {
159 int (*compar)(const void *, const void *, void *);
160 void *compard;
161};
162
163static int
164solv_sort_helper(void *compard, const void *a, const void *b)
165{
166 struct solv_sort_data *d = compard;
167 return (*d->compar)(a, b, d->compard);
168}
169
170void
171solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard)
172{
173 struct solv_sort_data d;
174 d.compar = compar;
175 d.compard = compard;
176 qsort_r(base, nmemb, size, &d, solv_sort_helper);
177}
178
179#else /* not glibc and no qsort_r() */
180/* use own version of qsort if none available */
181#include "qsort_r.c"
182#endif
183
184char *
185solv_dupjoin(const char *str1, const char *str2, const char *str3)
186{
187 int l1, l2, l3;
188 char *s, *str;
189 l1 = str1 ? strlen(str1) : 0;
2
Assuming 'str1' is non-null
3
'?' condition is true
190 l2 = str2 ? strlen(str2) : 0;
4
Assuming 'str2' is null
5
'?' condition is false
191 l3 = str3 ? strlen(str3) : 0;
6
Assuming 'str3' is null
7
'?' condition is false
192 s = str = solv_malloc(l1 + l2 + l3 + 1);
193 if (l1)
8
Assuming 'l1' is not equal to 0
9
Taking true branch
194 {
195 strcpy(s, str1);
10
String copy function overflows destination buffer
196 s += l1;
197 }
198 if (l2)
199 {
200 strcpy(s, str2);
201 s += l2;
202 }
203 if (l3)
204 {
205 strcpy(s, str3);
206 s += l3;
207 }
208 *s = 0;
209 return str;
210}
211
212char *
213solv_dupappend(const char *str1, const char *str2, const char *str3)
214{
215 char *str = solv_dupjoin(str1, str2, str3);
1
Calling 'solv_dupjoin'
216 solv_free((void *)str1);
217 return str;
218}
219
220int
221solv_hex2bin(const char **strp, unsigned char *buf, int bufl)
222{
223 const char *str = *strp;
224 int i;
225
226 for (i = 0; i < bufl; i++)
227 {
228 int c = *str;
229 int d;
230 if (c >= '0' && c <= '9')
231 d = c - '0';
232 else if (c >= 'a' && c <= 'f')
233 d = c - ('a' - 10);
234 else if (c >= 'A' && c <= 'F')
235 d = c - ('A' - 10);
236 else
237 break;
238 c = str[1];
239 d <<= 4;
240 if (c >= '0' && c <= '9')
241 d |= c - '0';
242 else if (c >= 'a' && c <= 'f')
243 d |= c - ('a' - 10);
244 else if (c >= 'A' && c <= 'F')
245 d |= c - ('A' - 10);
246 else
247 break;
248 buf[i] = d;
249 str += 2;
250 }
251 *strp = str;
252 return i;
253}
254
255char *
256solv_bin2hex(const unsigned char *buf, int l, char *str)
257{
258 int i;
259 for (i = 0; i < l; i++, buf++)
260 {
261 int c = *buf >> 4;
262 *str++ = c < 10 ? c + '0' : c + ('a' - 10);
263 c = *buf & 15;
264 *str++ = c < 10 ? c + '0' : c + ('a' - 10);
265 }
266 *str = 0;
267 return str;
268}
269
270size_t
271solv_validutf8(const char *buf)
272{
273 const unsigned char *p;
274 int x;
275
276 for (p = (const unsigned char *)buf; (x = *p) != 0; p++)
277 {
278 if (x < 0x80)
279 continue;
280 if (x < 0xc0)
281 break;
282 if (x < 0xe0)
283 {
284 /* one byte to follow */
285 if ((p[1] & 0xc0) != 0x80)
286 break;
287 if ((x & 0x1e) == 0)
288 break; /* not minimal */
289 p += 1;
290 continue;
291 }
292 if (x < 0xf0)
293 {
294 /* two bytes to follow */
295 if ((p[1] & 0xc0) != 0x80 || (p[2] & 0xc0) != 0x80)
296 break;
297 if ((x & 0x0f) == 0 && (p[1] & 0x20) == 0)
298 break; /* not minimal */
299 if (x == 0xed && (p[1] & 0x20) != 0)
300 break; /* d800-dfff surrogate */
301 if (x == 0xef && p[1] == 0xbf && (p[2] == 0xbe || p[2] == 0xbf))
302 break; /* fffe or ffff */
303 p += 2;
304 continue;
305 }
306 if (x < 0xf8)
307 {
308 /* three bytes to follow */
309 if ((p[1] & 0xc0) != 0x80 || (p[2] & 0xc0) != 0x80 || (p[3] & 0xc0) != 0x80)
310 break;
311 if ((x & 0x07) == 0 && (p[1] & 0x30) == 0)
312 break; /* not minimal */
313 if ((x & 0x07) > 4 || ((x & 0x07) == 4 && (p[1] & 0x30) != 0))
314 break; /* above 0x10ffff */
315 p += 3;
316 continue;
317 }
318 break; /* maybe valid utf8, but above 0x10ffff */
319 }
320 return (const char *)p - buf;
321}
322
323char *
324solv_latin1toutf8(const char *buf)
325{
326 int l = 1;
327 const char *p;
328 char *r, *rp;
329
330 for (p = buf; *p; p++)
331 if ((*(const unsigned char *)p & 128) != 0)
332 l++;
333 r = rp = solv_malloc(p - buf + l);
334 for (p = buf; *p; p++)
335 {
336 if ((*(const unsigned char *)p & 128) != 0)
337 {
338 *rp++ = *(const unsigned char *)p & 64 ? 0xc3 : 0xc2;
339 *rp++ = *p & 0xbf;
340 }
341 else
342 *rp++ = *p;
343 }
344 *rp = 0;
345 return r;
346}
347
348char *
349solv_replacebadutf8(const char *buf, int replchar)
350{
351 size_t l, nl;
352 const char *p;
353 char *r = 0, *rp = 0;
354 int repllen, replin;
355
356 if (replchar < 0 || replchar > 0x10ffff)
357 replchar = 0xfffd;
358 if (!replchar)
359 repllen = replin = 0;
360 else if (replchar < 0x80)
361 {
362 repllen = 1;
363 replin = (replchar & 0x40) | 0x80;
364 }
365 else if (replchar < 0x800)
366 {
367 repllen = 2;
368 replin = 0x40;
369 }
370 else if (replchar < 0x10000)
371 {
372 repllen = 3;
373 replin = 0x60;
374 }
375 else
376 {
377 repllen = 4;
378 replin = 0x70;
379 }
380 for (;;)
381 {
382 for (p = buf, nl = 0; *p; )
383 {
384 l = solv_validutf8(p);
385 if (rp && l)
386 {
387 memcpy(rp, p, l);
388 rp += l;
389 }
390 nl += l;
391 p += l;
392 if (!*p)
393 break;
394 /* found a bad char, replace with replchar */
395 if (rp && replchar)
396 {
397 switch (repllen)
398 {
399 case 4:
400 *rp++ = (replchar >> 18 & 0x3f) | 0x80;
401 case 3:
402 *rp++ = (replchar >> 12 & 0x3f) | 0x80;
403 case 2:
404 *rp++ = (replchar >> 6 & 0x3f) | 0x80;
405 default:
406 *rp++ = (replchar & 0x3f) | 0x80;
407 }
408 rp[-repllen] ^= replin;
409 }
410 nl += repllen;
411 p++;
412 while ((*(const unsigned char *)p & 0xc0) == 0x80)
413 p++;
414 }
415 if (rp)
416 break;
417 r = rp = solv_malloc(nl + 1);
418 }
419 *rp = 0;
420 return r;
421}
422